Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions packages/jdm-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
},
"dependencies": {
"@ant-design/icons": "6.0.0",
"@ant-design/v5-patch-for-react-19": "1.0.3",
"@codemirror/autocomplete": "^6.18.6",
"@codemirror/commands": "^6.8.1",
"@codemirror/language": "^6.11.0",
Expand All @@ -54,7 +55,7 @@
"@monaco-editor/react": "^4.7.0",
"@tanstack/react-table": "8.21.3",
"@tanstack/react-virtual": "3.13.6",
"antd": "5.21.2",
"antd": "5.27.1",
"clsx": "2.1.1",
"dnd-core": "^16.0.1",
"exceljs": "^4.4.0",
Expand All @@ -73,7 +74,6 @@
"react-resizable-panels": "^2.1.7",
"reactflow": "11.11.4",
"to-json-schema": "^0.2.5",
"transition-hook": "^1.5.2",
"ts-pattern": "^5.7.0",
"use-debounce": "^10.0.4",
"zod": "^3.24.2",
Expand All @@ -96,13 +96,13 @@
"@trivago/prettier-plugin-sort-imports": "5.2.2",
"@types/big.js": "^6.2.2",
"@types/lodash": "^4.17.16",
"@types/react": "18.3.11",
"@types/react-dom": "19.1.2",
"@types/react": "19.1.11",
"@types/react-dom": "19.1.7",
"@types/to-json-schema": "^0.2.4",
"@vitejs/plugin-react-swc": "^3.8.1",
"dayjs": "^1.11.13",
"react": "18.3.1",
"react-dom": "18.3.1",
"react": "19.1.1",
"react-dom": "19.1.1",
"sass": "^1.86.3",
"storybook": "8.6.12",
"storybook-dark-mode": "^4.0.2",
Expand All @@ -123,7 +123,8 @@
]
},
"peerDependencies": {
"react": ">= 18",
"react-dom": ">= 18"
"antd": ">= 5.22.6",
"react": ">= 19",
"react-dom": ">= 19"
}
}
81 changes: 44 additions & 37 deletions packages/jdm-editor/src/components/autosize-text-area.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { composeRefs } from '../helpers/compose-refs';

export type AutosizeTextAreaProps = {
maxRows: number;
ref?: React.Ref<HTMLTextAreaElement>;
} & React.DetailedHTMLProps<React.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>;

const recalculateRows = (node: HTMLTextAreaElement, maxRows: number) => {
Expand All @@ -21,48 +22,54 @@ const recalculateRows = (node: HTMLTextAreaElement, maxRows: number) => {
node.rows = Math.min(Math.max(calculatedRows, 1), maxRows);
};

export const AutosizeTextArea = React.forwardRef<HTMLTextAreaElement, AutosizeTextAreaProps>(
({ maxRows, className, value, ...props }, ref) => {
const textareaRef = useRef<HTMLTextAreaElement>(null);
export const AutosizeTextArea = (
{
maxRows,
className,
value,
ref,
...props
}: AutosizeTextAreaProps
) => {
const textareaRef = useRef<HTMLTextAreaElement>(null);

useEffect(() => {
if (!textareaRef.current) {
return;
}
useEffect(() => {
if (!textareaRef.current) {
return;
}

recalculateRows(textareaRef.current, maxRows);
}, [value, maxRows]);
recalculateRows(textareaRef.current, maxRows);
}, [value, maxRows]);

useEffect(() => {
if (!textareaRef.current) {
return;
}
useEffect(() => {
if (!textareaRef.current) {
return;
}

const observerCallback: ResizeObserverCallback = (entries: ResizeObserverEntry[]) => {
window.requestAnimationFrame((): void | undefined => {
if (!Array.isArray(entries) || entries.length === 0) {
return;
}
const observerCallback: ResizeObserverCallback = (entries: ResizeObserverEntry[]) => {
window.requestAnimationFrame((): void | undefined => {
if (!Array.isArray(entries) || entries.length === 0) {
return;
}

recalculateRows(entries[0].target as HTMLTextAreaElement, maxRows);
});
};
recalculateRows(entries[0].target as HTMLTextAreaElement, maxRows);
});
};

const resizeObserver = new ResizeObserver(observerCallback);
resizeObserver.observe(textareaRef.current);
const resizeObserver = new ResizeObserver(observerCallback);
resizeObserver.observe(textareaRef.current);

return () => {
resizeObserver.disconnect();
};
}, [maxRows]);
return () => {
resizeObserver.disconnect();
};
}, [maxRows]);

return (
<textarea
className={clsx('grl-textarea-input', className)}
ref={composeRefs(textareaRef, ref)}
value={value}
{...props}
/>
);
},
);
return (
<textarea
className={clsx('grl-textarea-input', className)}
ref={composeRefs(textareaRef, ref)}
value={value}
{...props}
/>
);
};
52 changes: 25 additions & 27 deletions packages/jdm-editor/src/components/code-editor/ce.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ type ExtensionParams = {
type?: 'standard' | 'unary' | 'template';
};

export type CodeEditorRef = HTMLDivElement & {
codeMirror: EditorView | null;
};

export type CodeEditorProps = {
maxRows?: number;
value?: string;
Expand All @@ -50,34 +54,29 @@ export type CodeEditorProps = {
livePreview?: { input: unknown; fromSimulation: boolean; result?: unknown };
variableType?: any;
expectedVariableType?: any;
ref?: React.Ref<CodeEditorRef>;
} & Omit<React.HTMLAttributes<HTMLDivElement>, 'disabled' | 'onChange'>;

export type CodeEditorRef = HTMLDivElement & {
codeMirror: EditorView | null;
};

export const CodeEditor = React.forwardRef<CodeEditorRef, CodeEditorProps>(
(
{
noStyle = false,
fullHeight = false,
strict = false,
maxRows,
disabled,
value,
onChange,
placeholder,
className,
onStateChange,
type = 'standard',
extension,
variableType,
expectedVariableType,
lint = true,
...props
},
export const CodeEditor = (
{
noStyle = false,
fullHeight = false,
strict = false,
maxRows,
disabled,
value,
onChange,
placeholder,
className,
onStateChange,
type = 'standard',
extension,
variableType,
expectedVariableType,
lint = true,
ref,
) => {
...props
}: CodeEditorProps) => {
const container = useRef<HTMLDivElement>(null);
const codeMirror = useRef<EditorView>(null);
const { token } = theme.useToken();
Expand Down Expand Up @@ -272,5 +271,4 @@ export const CodeEditor = React.forwardRef<CodeEditorRef, CodeEditorProps>(
{...props}
/>
);
},
);
};
6 changes: 3 additions & 3 deletions packages/jdm-editor/src/components/code-editor/local-ce.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { useDecisionGraphRaw } from '../decision-graph';
import type { CodeEditorRef } from './ce';
import { CodeEditor, type CodeEditorProps } from './ce';

type LocalCodeEditorProps = Omit<CodeEditorProps, 'extension'>;
type LocalCodeEditorProps = Omit<CodeEditorProps, 'extension'> & { ref?: React.Ref<CodeEditorRef> };

export const LocalCodeEditor = React.forwardRef<CodeEditorRef, LocalCodeEditorProps>((props, ref) => {
export const LocalCodeEditor = ({ ref, ...props }: LocalCodeEditorProps) => {
const raw = useDecisionGraphRaw();
const [extension, setExtension] = useState<CodeEditorProps['extension']>(() => {
if (raw?.listenerStore) {
Expand All @@ -25,4 +25,4 @@ export const LocalCodeEditor = React.forwardRef<CodeEditorRef, LocalCodeEditorPr
}, [raw]);

return <CodeEditor ref={ref} {...props} extension={extension} />;
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Monaco } from '@monaco-editor/react';
import equal from 'fast-deep-equal/es6/react';
import type { WritableDraft } from 'immer';
import { produce } from 'immer';
import React, { type MutableRefObject, createRef, useMemo } from 'react';
import React, { type RefObject, createRef, useMemo } from 'react';
import type { EdgeChange, NodeChange, ReactFlowInstance, useEdgesState, useNodesState } from 'reactflow';
import { match } from 'ts-pattern';
import type { StoreApi, UseBoundStore } from 'zustand';
Expand Down Expand Up @@ -78,10 +78,10 @@ export type DecisionGraphStoreType = {
};

references: {
nodesState: MutableRefObject<ReturnType<typeof useNodesState>>;
edgesState: MutableRefObject<ReturnType<typeof useEdgesState>>;
reactFlowInstance: MutableRefObject<ReactFlowInstance | null>;
graphClipboard: MutableRefObject<ReturnType<typeof useGraphClipboard>>;
nodesState: RefObject<ReturnType<typeof useNodesState>>;
edgesState: RefObject<ReturnType<typeof useEdgesState>>;
reactFlowInstance: RefObject<ReactFlowInstance | null>;
graphClipboard: RefObject<ReturnType<typeof useGraphClipboard>>;
};

actions: {
Expand Down Expand Up @@ -182,10 +182,10 @@ export const DecisionGraphProvider: React.FC<React.PropsWithChildren<DecisionGra
const referenceStore = useMemo(
() =>
create<DecisionGraphStoreType['references']>(() => ({
nodesState: createRef() as MutableRefObject<ReturnType<typeof useNodesState>>,
edgesState: createRef() as MutableRefObject<ReturnType<typeof useEdgesState>>,
graphClipboard: createRef() as MutableRefObject<ReturnType<typeof useGraphClipboard>>,
reactFlowInstance: createRef() as MutableRefObject<ReactFlowInstance | null>,
nodesState: createRef() as RefObject<ReturnType<typeof useNodesState>>,
edgesState: createRef() as RefObject<ReturnType<typeof useEdgesState>>,
graphClipboard: createRef() as RefObject<ReturnType<typeof useGraphClipboard>>,
reactFlowInstance: createRef() as RefObject<ReactFlowInstance | null>,
})),
[],
);
Expand Down
11 changes: 5 additions & 6 deletions packages/jdm-editor/src/components/decision-graph/dg-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import clsx from 'clsx';
import { createDragDropManager } from 'dnd-core';
import React, { forwardRef, useMemo, useRef, useState } from 'react';
import React, { useMemo, useRef, useState } from 'react';
import { HTML5Backend } from 'react-dnd-html5-backend';
import type { ProOptions } from 'reactflow';
import 'reactflow/dist/style.css';
Expand All @@ -25,12 +25,12 @@ import { NodeKind } from './nodes/specifications/specification-types';
export type DecisionGraphWrapperProps = {
reactFlowProOptions?: ProOptions;
tabBarExtraContent?: GraphTabsProps['tabBarExtraContent'];
ref?: React.Ref<GraphRef>;
};

export const DecisionGraphWrapper = React.memo(
forwardRef<GraphRef, DecisionGraphWrapperProps>(function DecisionGraphWrapperInner(
{ reactFlowProOptions, tabBarExtraContent },
ref,
function DecisionGraphWrapperInner(
{ reactFlowProOptions, tabBarExtraContent, ref }: DecisionGraphWrapperProps
) {
const [disableTabs, setDisableTabs] = useState(false);
const { hasActiveNode, viewConfig } = useDecisionGraphState(({ decisionGraph, activeTab, viewConfig }) => {
Expand All @@ -55,8 +55,7 @@ export const DecisionGraphWrapper = React.memo(
<GraphPanel />
</>
);
}),
);
});

const TabContents: React.FC = React.memo(() => {
const { openNodes, activeNodeId, components } = useDecisionGraphState(
Expand Down
14 changes: 7 additions & 7 deletions packages/jdm-editor/src/components/decision-graph/dg.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DragDropManager } from 'dnd-core';
import React, { forwardRef } from 'react';
import React from 'react';
import { ReactFlowProvider } from 'reactflow';

import type { DecisionGraphContextProps } from './context/dg-store.context';
Expand All @@ -12,16 +12,17 @@ import { DecisionGraphWrapper } from './dg-wrapper';
import './dg.scss';
import type { GraphRef } from './graph/graph';

export type DecisionGraphRef = GraphRef;

export type DecisionGraphProps = {
manager?: DragDropManager;
ref?: React.Ref<DecisionGraphRef>;
} & DecisionGraphWrapperProps &
DecisionGraphContextProps &
DecisionGraphEmptyType;

export type DecisionGraphRef = GraphRef;

export const DecisionGraph = forwardRef<DecisionGraphRef, DecisionGraphProps>(
({ manager: _, reactFlowProOptions, tabBarExtraContent, ...props }, ref) => {
export const DecisionGraph =
({ manager: _, reactFlowProOptions, tabBarExtraContent, ref, ...props }: DecisionGraphProps) => {
return (
<div className={'grl-dg'}>
<ReactFlowProvider>
Expand All @@ -37,5 +38,4 @@ export const DecisionGraph = forwardRef<DecisionGraphRef, DecisionGraphProps>(
</ReactFlowProvider>
</div>
);
},
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CloudDownloadOutlined, CloudUploadOutlined } from '@ant-design/icons';
import type { MenuProps } from 'antd';
import { Button, Dropdown, Tooltip, message } from 'antd';
import { App, Button, Dropdown, Tooltip } from 'antd';
import React, { useRef } from 'react';

import { decisionModelSchema } from '../../../helpers/schema';
Expand All @@ -16,6 +16,8 @@ export type GraphSideToolbarProps = {
};

export const GraphSideToolbar: React.FC<GraphSideToolbarProps> = () => {
const { message } = App.useApp();

const decisionGraphRaw = useDecisionGraphRaw();
const fileInput = useRef<HTMLInputElement>(null);
const excelFileInput = useRef<HTMLInputElement>(null);
Expand Down
Loading