diff --git a/packages/twenty-front/src/modules/settings/admin-panel/health-status/components/JsonDataIndicatorHealthStatus.tsx b/packages/twenty-front/src/modules/settings/admin-panel/health-status/components/JsonDataIndicatorHealthStatus.tsx
index 7d2de522d..68f594c0c 100644
--- a/packages/twenty-front/src/modules/settings/admin-panel/health-status/components/JsonDataIndicatorHealthStatus.tsx
+++ b/packages/twenty-front/src/modules/settings/admin-panel/health-status/components/JsonDataIndicatorHealthStatus.tsx
@@ -1,8 +1,8 @@
import { SettingsAdminIndicatorHealthContext } from '@/settings/admin-panel/health-status/contexts/SettingsAdminIndicatorHealthContext';
-import { JsonTree } from '@/workflow/components/json-visualizer/components/JsonTree';
import styled from '@emotion/styled';
+import { useLingui } from '@lingui/react/macro';
import { useContext } from 'react';
-import { Section } from 'twenty-ui';
+import { JsonTree, Section } from 'twenty-ui';
import { AdminPanelHealthServiceStatus } from '~/generated/graphql';
const StyledDetailsContainer = styled.div`
@@ -21,6 +21,8 @@ const StyledErrorMessage = styled.div`
`;
export const JsonDataIndicatorHealthStatus = () => {
+ const { t } = useLingui();
+
const { indicatorHealth } = useContext(SettingsAdminIndicatorHealthContext);
const parsedDetails = indicatorHealth.details
@@ -41,7 +43,13 @@ export const JsonDataIndicatorHealthStatus = () => {
)}
{parsedDetails && (
-
+
)}
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonTree.tsx b/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonTree.tsx
deleted file mode 100644
index 43c474a1f..000000000
--- a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonTree.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { JsonList } from '@/workflow/components/json-visualizer/components/internal/JsonList';
-import { JsonNode } from '@/workflow/components/json-visualizer/components/JsonNode';
-import { JsonValue } from 'type-fest';
-
-export const JsonTree = ({
- value,
- shouldHighlightNode,
-}: {
- value: JsonValue;
- shouldHighlightNode?: (keyPath: string) => boolean;
-}) => {
- return (
-
-
-
- );
-};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepInputDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepInputDetail.tsx
index f1bee4ca5..c703fb2ad 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepInputDetail.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepInputDetail.tsx
@@ -1,11 +1,15 @@
-import { JsonNestedNode } from '@/workflow/components/json-visualizer/components/JsonNestedNode';
import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun';
import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow';
import { getWorkflowRunStepContext } from '@/workflow/workflow-steps/utils/getWorkflowRunStepContext';
import { getWorkflowVariablesUsedInStep } from '@/workflow/workflow-steps/utils/getWorkflowVariablesUsedInStep';
import styled from '@emotion/styled';
+import { useLingui } from '@lingui/react/macro';
import { isDefined } from 'twenty-shared';
-import { IconBrackets } from 'twenty-ui';
+import {
+ IconBrackets,
+ JsonNestedNode,
+ JsonTreeContextProvider,
+} from 'twenty-ui';
const StyledContainer = styled.div`
display: grid;
@@ -15,6 +19,8 @@ const StyledContainer = styled.div`
`;
export const WorkflowRunStepInputDetail = ({ stepId }: { stepId: string }) => {
+ const { t } = useLingui();
+
const workflowRunId = useWorkflowRunIdOrThrow();
const workflowRun = useWorkflowRun({ workflowRunId });
const step = workflowRun?.output?.flow.steps.find(
@@ -48,18 +54,27 @@ export const WorkflowRunStepInputDetail = ({ stepId }: { stepId: string }) => {
return (
- ({
- id,
- label: name,
- value: context,
- }))}
- Icon={IconBrackets}
- emptyElementsText=""
- depth={0}
- keyPath=""
- shouldHighlightNode={(keyPath) => variablesUsedInStep.has(keyPath)}
- />
+ variablesUsedInStep.has(keyPath),
+ }}
+ >
+ ({
+ id,
+ label: name,
+ value: context,
+ }))}
+ Icon={IconBrackets}
+ depth={0}
+ keyPath=""
+ emptyElementsText=""
+ />
+
);
};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepOutputDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepOutputDetail.tsx
index d8c9062cf..c547b9f5f 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepOutputDetail.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowRunStepOutputDetail.tsx
@@ -1,8 +1,9 @@
-import { JsonTree } from '@/workflow/components/json-visualizer/components/JsonTree';
import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun';
import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow';
import styled from '@emotion/styled';
+import { useLingui } from '@lingui/react/macro';
import { isDefined } from 'twenty-shared';
+import { JsonTree } from 'twenty-ui';
const StyledContainer = styled.div`
display: grid;
@@ -15,6 +16,8 @@ export const WorkflowRunStepOutputDetail = ({ stepId }: { stepId: string }) => {
const workflowRunId = useWorkflowRunIdOrThrow();
const workflowRun = useWorkflowRun({ workflowRunId });
+ const { t } = useLingui();
+
if (!isDefined(workflowRun?.output?.stepsOutput)) {
return null;
}
@@ -23,7 +26,13 @@ export const WorkflowRunStepOutputDetail = ({ stepId }: { stepId: string }) => {
return (
-
+
);
};
diff --git a/packages/twenty-ui/src/index.ts b/packages/twenty-ui/src/index.ts
index bd63145e4..561297ab1 100644
--- a/packages/twenty-ui/src/index.ts
+++ b/packages/twenty-ui/src/index.ts
@@ -3,6 +3,7 @@ export * from './components';
export * from './display';
export * from './feedback';
export * from './input';
+export * from './json-visualizer';
export * from './layout';
export * from './navigation';
export * from './testing';
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/__stories__/JsonTree.stories.tsx b/packages/twenty-ui/src/json-visualizer/__stories__/JsonTree.stories.tsx
similarity index 97%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/__stories__/JsonTree.stories.tsx
rename to packages/twenty-ui/src/json-visualizer/__stories__/JsonTree.stories.tsx
index 96b553db1..198b1d207 100644
--- a/packages/twenty-front/src/modules/workflow/components/json-visualizer/__stories__/JsonTree.stories.tsx
+++ b/packages/twenty-ui/src/json-visualizer/__stories__/JsonTree.stories.tsx
@@ -1,4 +1,3 @@
-import { JsonTree } from '@/workflow/components/json-visualizer/components/JsonTree';
import { Meta, StoryObj } from '@storybook/react';
import {
expect,
@@ -6,14 +5,18 @@ import {
waitForElementToBeRemoved,
within,
} from '@storybook/test';
-import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
+import { JsonTree } from '@ui/json-visualizer/components/JsonTree';
const meta: Meta = {
- title: 'Modules/Workflow/JsonVisualizer/JsonTree',
+ title: 'UI/JsonVisualizer/JsonTree',
component: JsonTree,
- args: {},
+ args: {
+ emptyArrayLabel: 'Empty Array',
+ emptyObjectLabel: 'Empty Object',
+ arrowButtonCollapsedLabel: 'Expand',
+ arrowButtonExpandedLabel: 'Collapse',
+ },
argTypes: {},
- decorators: [I18nFrontDecorator],
};
export default meta;
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonArrayNode.tsx b/packages/twenty-ui/src/json-visualizer/components/JsonArrayNode.tsx
similarity index 57%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonArrayNode.tsx
rename to packages/twenty-ui/src/json-visualizer/components/JsonArrayNode.tsx
index 9ef496bc3..d17da3ab6 100644
--- a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonArrayNode.tsx
+++ b/packages/twenty-ui/src/json-visualizer/components/JsonArrayNode.tsx
@@ -1,6 +1,6 @@
-import { JsonNestedNode } from '@/workflow/components/json-visualizer/components/JsonNestedNode';
-import { useLingui } from '@lingui/react/macro';
-import { IconBrackets } from 'twenty-ui';
+import { IconBrackets } from '@ui/display';
+import { JsonNestedNode } from '@ui/json-visualizer/components/JsonNestedNode';
+import { useJsonTreeContextOrThrow } from '@ui/json-visualizer/hooks/useJsonTreeContextOrThrow';
import { JsonArray } from 'type-fest';
export const JsonArrayNode = ({
@@ -8,15 +8,13 @@ export const JsonArrayNode = ({
value,
depth,
keyPath,
- shouldHighlightNode,
}: {
label?: string;
value: JsonArray;
depth: number;
keyPath: string;
- shouldHighlightNode?: (keyPath: string) => boolean;
}) => {
- const { t } = useLingui();
+ const { emptyArrayLabel } = useJsonTreeContextOrThrow();
return (
);
};
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonNestedNode.tsx b/packages/twenty-ui/src/json-visualizer/components/JsonNestedNode.tsx
similarity index 80%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonNestedNode.tsx
rename to packages/twenty-ui/src/json-visualizer/components/JsonNestedNode.tsx
index 2ffda032b..29c08d3fa 100644
--- a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonNestedNode.tsx
+++ b/packages/twenty-ui/src/json-visualizer/components/JsonNestedNode.tsx
@@ -1,12 +1,12 @@
-import { JsonArrow } from '@/workflow/components/json-visualizer/components/internal/JsonArrow';
-import { JsonList } from '@/workflow/components/json-visualizer/components/internal/JsonList';
-import { JsonNodeLabel } from '@/workflow/components/json-visualizer/components/internal/JsonNodeLabel';
-import { JsonNode } from '@/workflow/components/json-visualizer/components/JsonNode';
import styled from '@emotion/styled';
import { isNonEmptyString } from '@sniptt/guards';
+import { IconComponent } from '@ui/display';
+import { JsonArrow } from '@ui/json-visualizer/components/internal/JsonArrow';
+import { JsonList } from '@ui/json-visualizer/components/internal/JsonList';
+import { JsonNodeLabel } from '@ui/json-visualizer/components/internal/JsonNodeLabel';
+import { JsonNode } from '@ui/json-visualizer/components/JsonNode';
import { useState } from 'react';
import { isDefined } from 'twenty-shared';
-import { IconComponent } from 'twenty-ui';
import { JsonValue } from 'type-fest';
const StyledContainer = styled.li`
@@ -37,7 +37,6 @@ export const JsonNestedNode = ({
emptyElementsText,
depth,
keyPath,
- shouldHighlightNode,
}: {
label?: string;
Icon: IconComponent;
@@ -46,7 +45,6 @@ export const JsonNestedNode = ({
emptyElementsText: string;
depth: number;
keyPath: string;
- shouldHighlightNode?: (keyPath: string) => boolean;
}) => {
const hideRoot = !isDefined(label);
@@ -69,7 +67,6 @@ export const JsonNestedNode = ({
value={value}
depth={depth + 1}
keyPath={nextKeyPath}
- shouldHighlightNode={shouldHighlightNode}
/>
);
})
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonNode.tsx b/packages/twenty-ui/src/json-visualizer/components/JsonNode.tsx
similarity index 72%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonNode.tsx
rename to packages/twenty-ui/src/json-visualizer/components/JsonNode.tsx
index e326bf4fc..1fae1916b 100644
--- a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonNode.tsx
+++ b/packages/twenty-ui/src/json-visualizer/components/JsonNode.tsx
@@ -1,14 +1,15 @@
-import { JsonArrayNode } from '@/workflow/components/json-visualizer/components/JsonArrayNode';
-import { JsonObjectNode } from '@/workflow/components/json-visualizer/components/JsonObjectNode';
-import { JsonValueNode } from '@/workflow/components/json-visualizer/components/JsonValueNode';
-import { isArray } from '@/workflow/components/json-visualizer/utils/isArray';
import { isBoolean, isNull, isNumber, isString } from '@sniptt/guards';
import {
IconCheckbox,
IconCircleOff,
IconNumber9,
IconTypography,
-} from 'twenty-ui';
+} from '@ui/display';
+import { JsonArrayNode } from '@ui/json-visualizer/components/JsonArrayNode';
+import { JsonObjectNode } from '@ui/json-visualizer/components/JsonObjectNode';
+import { JsonValueNode } from '@ui/json-visualizer/components/JsonValueNode';
+import { useJsonTreeContextOrThrow } from '@ui/json-visualizer/hooks/useJsonTreeContextOrThrow';
+import { isArray } from '@ui/json-visualizer/utils/isArray';
import { JsonValue } from 'type-fest';
export const JsonNode = ({
@@ -16,14 +17,14 @@ export const JsonNode = ({
value,
depth,
keyPath,
- shouldHighlightNode,
}: {
label?: string;
value: JsonValue;
depth: number;
keyPath: string;
- shouldHighlightNode?: (keyPath: string) => boolean;
}) => {
+ const { shouldHighlightNode } = useJsonTreeContextOrThrow();
+
const isHighlighted = shouldHighlightNode?.(keyPath) ?? false;
if (isNull(value)) {
@@ -77,7 +78,6 @@ export const JsonNode = ({
value={value}
depth={depth}
keyPath={keyPath}
- shouldHighlightNode={shouldHighlightNode}
/>
);
}
@@ -88,7 +88,6 @@ export const JsonNode = ({
value={value}
depth={depth}
keyPath={keyPath}
- shouldHighlightNode={shouldHighlightNode}
/>
);
};
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonObjectNode.tsx b/packages/twenty-ui/src/json-visualizer/components/JsonObjectNode.tsx
similarity index 57%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonObjectNode.tsx
rename to packages/twenty-ui/src/json-visualizer/components/JsonObjectNode.tsx
index 57bea7d37..e3f32fd34 100644
--- a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonObjectNode.tsx
+++ b/packages/twenty-ui/src/json-visualizer/components/JsonObjectNode.tsx
@@ -1,6 +1,6 @@
-import { JsonNestedNode } from '@/workflow/components/json-visualizer/components/JsonNestedNode';
-import { useLingui } from '@lingui/react/macro';
-import { IconCube } from 'twenty-ui';
+import { IconCube } from '@ui/display';
+import { JsonNestedNode } from '@ui/json-visualizer/components/JsonNestedNode';
+import { useJsonTreeContextOrThrow } from '@ui/json-visualizer/hooks/useJsonTreeContextOrThrow';
import { JsonObject } from 'type-fest';
export const JsonObjectNode = ({
@@ -8,15 +8,13 @@ export const JsonObjectNode = ({
value,
depth,
keyPath,
- shouldHighlightNode,
}: {
label?: string;
value: JsonObject;
depth: number;
keyPath: string;
- shouldHighlightNode?: (keyPath: string) => boolean;
}) => {
- const { t } = useLingui();
+ const { emptyObjectLabel } = useJsonTreeContextOrThrow();
return (
);
};
diff --git a/packages/twenty-ui/src/json-visualizer/components/JsonTree.tsx b/packages/twenty-ui/src/json-visualizer/components/JsonTree.tsx
new file mode 100644
index 000000000..ef92c44a6
--- /dev/null
+++ b/packages/twenty-ui/src/json-visualizer/components/JsonTree.tsx
@@ -0,0 +1,36 @@
+import { JsonList } from '@ui/json-visualizer/components/internal/JsonList';
+import { JsonNode } from '@ui/json-visualizer/components/JsonNode';
+import { JsonTreeContextProvider } from '@ui/json-visualizer/components/JsonTreeContextProvider';
+import { JsonValue } from 'type-fest';
+
+export const JsonTree = ({
+ value,
+ shouldHighlightNode,
+ emptyArrayLabel,
+ emptyObjectLabel,
+ arrowButtonCollapsedLabel,
+ arrowButtonExpandedLabel,
+}: {
+ value: JsonValue;
+ shouldHighlightNode?: (keyPath: string) => boolean;
+ emptyArrayLabel: string;
+ emptyObjectLabel: string;
+ arrowButtonCollapsedLabel: string;
+ arrowButtonExpandedLabel: string;
+}) => {
+ return (
+
+
+
+
+
+ );
+};
diff --git a/packages/twenty-ui/src/json-visualizer/components/JsonTreeContextProvider.tsx b/packages/twenty-ui/src/json-visualizer/components/JsonTreeContextProvider.tsx
new file mode 100644
index 000000000..6269e7d26
--- /dev/null
+++ b/packages/twenty-ui/src/json-visualizer/components/JsonTreeContextProvider.tsx
@@ -0,0 +1,18 @@
+import {
+ JsonTreeContext,
+ JsonTreeContextType,
+} from '@ui/json-visualizer/contexts/JsonTreeContext';
+
+export const JsonTreeContextProvider = ({
+ value,
+ children,
+}: {
+ value: JsonTreeContextType;
+ children: React.ReactNode;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonValueNode.tsx b/packages/twenty-ui/src/json-visualizer/components/JsonValueNode.tsx
similarity index 67%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonValueNode.tsx
rename to packages/twenty-ui/src/json-visualizer/components/JsonValueNode.tsx
index 10d5cb927..1fe661185 100644
--- a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/JsonValueNode.tsx
+++ b/packages/twenty-ui/src/json-visualizer/components/JsonValueNode.tsx
@@ -1,8 +1,8 @@
-import { JsonListItem } from '@/workflow/components/json-visualizer/components/internal/JsonListItem';
-import { JsonNodeLabel } from '@/workflow/components/json-visualizer/components/internal/JsonNodeLabel';
-import { JsonNodeValue } from '@/workflow/components/json-visualizer/components/internal/JsonNodeValue';
import styled from '@emotion/styled';
-import { IconComponent } from 'twenty-ui';
+import { IconComponent } from '@ui/display';
+import { JsonListItem } from '@ui/json-visualizer/components/internal/JsonListItem';
+import { JsonNodeLabel } from '@ui/json-visualizer/components/internal/JsonNodeLabel';
+import { JsonNodeValue } from '@ui/json-visualizer/components/internal/JsonNodeValue';
const StyledListItem = styled(JsonListItem)`
column-gap: ${({ theme }) => theme.spacing(2)};
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/internal/JsonArrow.tsx b/packages/twenty-ui/src/json-visualizer/components/internal/JsonArrow.tsx
similarity index 71%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/components/internal/JsonArrow.tsx
rename to packages/twenty-ui/src/json-visualizer/components/internal/JsonArrow.tsx
index 60ddf0e13..6b4bf720b 100644
--- a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/internal/JsonArrow.tsx
+++ b/packages/twenty-ui/src/json-visualizer/components/internal/JsonArrow.tsx
@@ -1,8 +1,9 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
-import { useLingui } from '@lingui/react/macro';
+import { VisibilityHidden } from '@ui/accessibility';
+import { IconChevronDown } from '@ui/display';
+import { useJsonTreeContextOrThrow } from '@ui/json-visualizer/hooks/useJsonTreeContextOrThrow';
import { motion } from 'framer-motion';
-import { IconChevronDown, VisibilityHidden } from 'twenty-ui';
const StyledButton = styled(motion.button)`
align-items: center;
@@ -29,13 +30,16 @@ export const JsonArrow = ({
isOpen: boolean;
onClick: () => void;
}) => {
- const { t } = useLingui();
-
const theme = useTheme();
+ const { arrowButtonCollapsedLabel, arrowButtonExpandedLabel } =
+ useJsonTreeContextOrThrow();
+
return (
- {isOpen ? t`Collapse` : t`Expand`}
+
+ {isOpen ? arrowButtonExpandedLabel : arrowButtonCollapsedLabel}
+
`
align-items: center;
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/components/internal/JsonNodeValue.tsx b/packages/twenty-ui/src/json-visualizer/components/internal/JsonNodeValue.tsx
similarity index 100%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/components/internal/JsonNodeValue.tsx
rename to packages/twenty-ui/src/json-visualizer/components/internal/JsonNodeValue.tsx
diff --git a/packages/twenty-ui/src/json-visualizer/contexts/JsonTreeContext.tsx b/packages/twenty-ui/src/json-visualizer/contexts/JsonTreeContext.tsx
new file mode 100644
index 000000000..64bfc49e3
--- /dev/null
+++ b/packages/twenty-ui/src/json-visualizer/contexts/JsonTreeContext.tsx
@@ -0,0 +1,13 @@
+import { createContext } from 'react';
+
+export type JsonTreeContextType = {
+ shouldHighlightNode?: (keyPath: string) => boolean;
+ emptyArrayLabel: string;
+ emptyObjectLabel: string;
+ arrowButtonCollapsedLabel: string;
+ arrowButtonExpandedLabel: string;
+};
+
+export const JsonTreeContext = createContext(
+ undefined,
+);
diff --git a/packages/twenty-ui/src/json-visualizer/hooks/useJsonTreeContextOrThrow.tsx b/packages/twenty-ui/src/json-visualizer/hooks/useJsonTreeContextOrThrow.tsx
new file mode 100644
index 000000000..0bb0d0234
--- /dev/null
+++ b/packages/twenty-ui/src/json-visualizer/hooks/useJsonTreeContextOrThrow.tsx
@@ -0,0 +1,15 @@
+import { JsonTreeContext } from '@ui/json-visualizer/contexts/JsonTreeContext';
+import { useContext } from 'react';
+import { isDefined } from 'twenty-shared';
+
+export const useJsonTreeContextOrThrow = () => {
+ const value = useContext(JsonTreeContext);
+
+ if (!isDefined(value)) {
+ throw new Error(
+ 'useJsonTreeContextOrThrow must be used within a JsonTreeContextProvider',
+ );
+ }
+
+ return value;
+};
diff --git a/packages/twenty-ui/src/json-visualizer/index.ts b/packages/twenty-ui/src/json-visualizer/index.ts
new file mode 100644
index 000000000..649bc8032
--- /dev/null
+++ b/packages/twenty-ui/src/json-visualizer/index.ts
@@ -0,0 +1,10 @@
+export * from './components/JsonArrayNode';
+export * from './components/JsonNestedNode';
+export * from './components/JsonNode';
+export * from './components/JsonObjectNode';
+export * from './components/JsonTree';
+export * from './components/JsonTreeContextProvider';
+export * from './components/JsonValueNode';
+export * from './contexts/JsonTreeContext';
+export * from './hooks/useJsonTreeContextOrThrow';
+export * from './utils/isArray';
diff --git a/packages/twenty-front/src/modules/workflow/components/json-visualizer/utils/isArray.ts b/packages/twenty-ui/src/json-visualizer/utils/isArray.ts
similarity index 100%
rename from packages/twenty-front/src/modules/workflow/components/json-visualizer/utils/isArray.ts
rename to packages/twenty-ui/src/json-visualizer/utils/isArray.ts