@eccenca/gui-elements 24.2.0 → 24.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/dist/cjs/cmem/ActivityControl/ActivityControlWidget.js +12 -9
- package/dist/cjs/cmem/ActivityControl/ActivityControlWidget.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js +10 -9
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js +2 -2
- package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
- package/dist/cjs/components/Icon/IconButton.js +1 -0
- package/dist/cjs/components/Icon/IconButton.js.map +1 -1
- package/dist/cjs/components/Tooltip/Tooltip.js +12 -7
- package/dist/cjs/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/cjs/extensions/codemirror/CodeMirror.js +83 -21
- package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
- package/dist/cjs/extensions/codemirror/tests/codemirrorTestHelper.js +22 -1
- package/dist/cjs/extensions/codemirror/tests/codemirrorTestHelper.js.map +1 -1
- package/dist/cjs/extensions/react-flow/edges/EdgeDefaultV12.js +56 -0
- package/dist/cjs/extensions/react-flow/edges/EdgeDefaultV12.js.map +1 -0
- package/dist/cjs/extensions/react-flow/edges/EdgeDefs.js +14 -0
- package/dist/cjs/extensions/react-flow/edges/EdgeDefs.js.map +1 -0
- package/dist/cjs/extensions/react-flow/handles/HandleDefault.js +3 -0
- package/dist/cjs/extensions/react-flow/handles/HandleDefault.js.map +1 -1
- package/dist/cjs/extensions/react-flow/index.js +3 -0
- package/dist/cjs/extensions/react-flow/index.js.map +1 -1
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +49 -28
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/cjs/extensions/react-flow/versionsupport.js +6 -0
- package/dist/cjs/extensions/react-flow/versionsupport.js.map +1 -1
- package/dist/esm/cmem/ActivityControl/ActivityControlWidget.js +12 -9
- package/dist/esm/cmem/ActivityControl/ActivityControlWidget.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js +10 -9
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js +2 -2
- package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
- package/dist/esm/components/Icon/IconButton.js +1 -0
- package/dist/esm/components/Icon/IconButton.js.map +1 -1
- package/dist/esm/components/Tooltip/Tooltip.js +14 -9
- package/dist/esm/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/esm/extensions/codemirror/CodeMirror.js +84 -22
- package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
- package/dist/esm/extensions/codemirror/tests/codemirrorTestHelper.js +20 -0
- package/dist/esm/extensions/codemirror/tests/codemirrorTestHelper.js.map +1 -1
- package/dist/esm/extensions/react-flow/edges/EdgeDefaultV12.js +77 -0
- package/dist/esm/extensions/react-flow/edges/EdgeDefaultV12.js.map +1 -0
- package/dist/esm/extensions/react-flow/edges/EdgeDefs.js +8 -0
- package/dist/esm/extensions/react-flow/edges/EdgeDefs.js.map +1 -0
- package/dist/esm/extensions/react-flow/handles/HandleDefault.js +3 -0
- package/dist/esm/extensions/react-flow/handles/HandleDefault.js.map +1 -1
- package/dist/esm/extensions/react-flow/index.js +3 -0
- package/dist/esm/extensions/react-flow/index.js.map +1 -1
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js +66 -44
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/esm/extensions/react-flow/versionsupport.js +6 -0
- package/dist/esm/extensions/react-flow/versionsupport.js.map +1 -1
- package/dist/types/cmem/ActivityControl/ActivityControlWidget.d.ts +4 -0
- package/dist/types/components/AutoSuggestion/AutoSuggestion.d.ts +7 -1
- package/dist/types/components/AutoSuggestion/ExtendedCodeEditor.d.ts +5 -1
- package/dist/types/components/Tooltip/Tooltip.d.ts +7 -1
- package/dist/types/extensions/codemirror/CodeMirror.d.ts +3 -2
- package/dist/types/extensions/codemirror/tests/codemirrorTestHelper.d.ts +3 -1
- package/dist/types/extensions/react-flow/edges/EdgeDefaultV12.d.ts +38 -0
- package/dist/types/extensions/react-flow/edges/EdgeDefs.d.ts +2 -0
- package/dist/types/extensions/react-flow/handles/HandleDefault.d.ts +4 -1
- package/dist/types/extensions/react-flow/index.d.ts +3 -0
- package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +5 -4
- package/dist/types/extensions/react-flow/versionsupport.d.ts +3 -2
- package/package.json +6 -3
- package/src/cmem/ActivityControl/ActivityControlWidget.stories.tsx +45 -5
- package/src/cmem/ActivityControl/ActivityControlWidget.tsx +47 -9
- package/src/cmem/ActivityControl/tests/ActivityControlWidget.test.tsx +99 -0
- package/src/components/AutoSuggestion/AutoSuggestion.tsx +30 -16
- package/src/components/AutoSuggestion/ExtendedCodeEditor.tsx +8 -0
- package/src/components/Icon/IconButton.tsx +1 -0
- package/src/components/Tooltip/Tooltip.tsx +24 -13
- package/src/extensions/codemirror/CodeMirror.tsx +102 -26
- package/src/extensions/codemirror/tests/codemirrorTestHelper.ts +20 -1
- package/src/extensions/react-flow/_react-flow.scss +1 -0
- package/src/extensions/react-flow/_react-flow_v12.scss +5 -0
- package/src/extensions/react-flow/edges/EdgeDefaultV12.tsx +154 -0
- package/src/extensions/react-flow/edges/EdgeDefs.tsx +30 -0
- package/src/extensions/react-flow/edges/_edges.scss +18 -0
- package/src/extensions/react-flow/edges/stories/EdgeDefaultV12.stories.tsx +183 -0
- package/src/extensions/react-flow/handles/HandleDefault.tsx +12 -4
- package/src/extensions/react-flow/index.ts +3 -0
- package/src/extensions/react-flow/nodes/NodeContent.tsx +85 -48
- package/src/extensions/react-flow/nodes/NodeDefaultV12.tsx +53 -0
- package/src/extensions/react-flow/nodes/stories/NodeContentV12.stories.tsx +270 -0
- package/src/extensions/react-flow/versionsupport.ts +7 -2
|
@@ -50,6 +50,7 @@ export const IconButton = ({
|
|
|
50
50
|
const defaultIconTooltipProps = {
|
|
51
51
|
hoverOpenDelay: 1000,
|
|
52
52
|
openOnTargetFocus: restProps.disabled || (restProps.tabIndex ?? 0) < 0 ? false : undefined,
|
|
53
|
+
swapPlaceholderDelay: 1,
|
|
53
54
|
};
|
|
54
55
|
const iconProps = {
|
|
55
56
|
small: restProps.small,
|
|
@@ -42,6 +42,12 @@ export interface TooltipProps extends Omit<BlueprintTooltipProps, "position"> {
|
|
|
42
42
|
* You can prevent it in any case by setting it to `false`.
|
|
43
43
|
*/
|
|
44
44
|
usePlaceholder?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Time after the placeholder element is replaced by the actual tooltip component.
|
|
47
|
+
* Must be greater than 0.
|
|
48
|
+
* For the first display of the tooltip this time adds up to `hoverOpenDelay`.
|
|
49
|
+
*/
|
|
50
|
+
swapPlaceholderDelay?: number;
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
export const Tooltip = ({
|
|
@@ -53,18 +59,21 @@ export const Tooltip = ({
|
|
|
53
59
|
markdownEnabler = "\n\n",
|
|
54
60
|
markdownProps,
|
|
55
61
|
usePlaceholder,
|
|
56
|
-
|
|
62
|
+
swapPlaceholderDelay = 100,
|
|
63
|
+
hoverOpenDelay = 450,
|
|
57
64
|
...otherTooltipProps
|
|
58
65
|
}: TooltipProps) => {
|
|
59
66
|
const placeholderRef = React.useRef(null);
|
|
60
67
|
const eventMemory = React.useRef<null | "afterhover" | "afterfocus">(null);
|
|
61
68
|
const searchId = React.useRef<null | string>(null);
|
|
62
|
-
const
|
|
69
|
+
const swapDelay = React.useRef<null | NodeJS.Timeout>(null);
|
|
70
|
+
const swapDelayTime = swapPlaceholderDelay;
|
|
63
71
|
const [placeholder, setPlaceholder] = React.useState<boolean>(
|
|
64
72
|
!otherTooltipProps.disabled &&
|
|
65
73
|
!otherTooltipProps.defaultIsOpen &&
|
|
66
74
|
!otherTooltipProps.isOpen &&
|
|
67
75
|
otherTooltipProps.renderTarget === undefined &&
|
|
76
|
+
swapDelayTime > 0 &&
|
|
68
77
|
hoverOpenDelay > swapDelayTime &&
|
|
69
78
|
(usePlaceholder === true || (typeof content === "string" && usePlaceholder !== false))
|
|
70
79
|
);
|
|
@@ -77,7 +86,10 @@ export const Tooltip = ({
|
|
|
77
86
|
React.useEffect(() => {
|
|
78
87
|
if (placeholderRef.current !== null) {
|
|
79
88
|
const swap = (ev: MouseEvent | globalThis.FocusEvent) => {
|
|
80
|
-
|
|
89
|
+
if (swapDelay.current) {
|
|
90
|
+
clearTimeout(swapDelay.current);
|
|
91
|
+
}
|
|
92
|
+
swapDelay.current = setTimeout(() => {
|
|
81
93
|
// we delay the swap to prevent unwanted effects
|
|
82
94
|
// (e.g. forced mouseover after the swap but the cursor is already somewhere else)
|
|
83
95
|
eventMemory.current = ev.type === "focusin" ? "afterfocus" : "afterhover";
|
|
@@ -86,16 +98,15 @@ export const Tooltip = ({
|
|
|
86
98
|
}, swapDelayTime);
|
|
87
99
|
if (placeholderRef.current !== null) {
|
|
88
100
|
const eventType = ev.type === "focusin" ? "focusout" : "mouseleave";
|
|
89
|
-
(placeholderRef.current as HTMLElement).addEventListener(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
clearTimeout(swapDelay)
|
|
101
|
+
(placeholderRef.current as HTMLElement).addEventListener(eventType, () => {
|
|
102
|
+
if (
|
|
103
|
+
(eventType === "focusout" && eventMemory.current === "afterfocus") ||
|
|
104
|
+
(eventType === "mouseleave" && eventMemory.current === "afterhover")
|
|
105
|
+
) {
|
|
106
|
+
eventMemory.current = null;
|
|
97
107
|
}
|
|
98
|
-
|
|
108
|
+
clearTimeout(swapDelay.current as NodeJS.Timeout);
|
|
109
|
+
});
|
|
99
110
|
}
|
|
100
111
|
};
|
|
101
112
|
(placeholderRef.current as HTMLElement).addEventListener("mouseenter", swap);
|
|
@@ -167,7 +178,7 @@ export const Tooltip = ({
|
|
|
167
178
|
) : (
|
|
168
179
|
<BlueprintTooltip
|
|
169
180
|
lazy={true}
|
|
170
|
-
hoverOpenDelay={hoverOpenDelay
|
|
181
|
+
hoverOpenDelay={hoverOpenDelay}
|
|
171
182
|
{...otherTooltipProps}
|
|
172
183
|
content={tooltipContent}
|
|
173
184
|
className={targetClassName}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useMemo, useRef } from "react";
|
|
2
2
|
import { defaultKeymap, indentWithTab } from "@codemirror/commands";
|
|
3
3
|
import { foldKeymap } from "@codemirror/language";
|
|
4
|
-
import { EditorState, Extension } from "@codemirror/state";
|
|
4
|
+
import { EditorState, Extension, Compartment } from "@codemirror/state";
|
|
5
5
|
import { DOMEventHandlers, EditorView, KeyBinding, keymap, Rect, ViewUpdate } from "@codemirror/view";
|
|
6
6
|
import { minimalSetup } from "codemirror";
|
|
7
7
|
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
adaptedHighlightSpecialChars,
|
|
31
31
|
adaptedLineNumbers,
|
|
32
32
|
adaptedLintGutter,
|
|
33
|
-
adaptedPlaceholder,
|
|
33
|
+
adaptedPlaceholder, compartment,
|
|
34
34
|
} from "./tests/codemirrorTestHelper";
|
|
35
35
|
import { ExtensionCreator } from "./types";
|
|
36
36
|
|
|
@@ -53,6 +53,7 @@ export interface CodeEditorProps extends TestableComponent {
|
|
|
53
53
|
/**
|
|
54
54
|
* Handler method to receive onChange events.
|
|
55
55
|
* As input the new value is given.
|
|
56
|
+
* @deprecated (v25) use `(v: string) => void` in future
|
|
56
57
|
*/
|
|
57
58
|
onChange?: (v: any) => void;
|
|
58
59
|
/**
|
|
@@ -74,7 +75,7 @@ export interface CodeEditorProps extends TestableComponent {
|
|
|
74
75
|
/**
|
|
75
76
|
* Called when the cursor position changes
|
|
76
77
|
*/
|
|
77
|
-
onCursorChange?: (pos: number, coords: Rect, scrollinfo: HTMLElement, cm: EditorView) =>
|
|
78
|
+
onCursorChange?: (pos: number, coords: Rect, scrollinfo: HTMLElement, cm: EditorView) => void;
|
|
78
79
|
|
|
79
80
|
/**
|
|
80
81
|
* Syntax mode of the code editor.
|
|
@@ -83,7 +84,7 @@ export interface CodeEditorProps extends TestableComponent {
|
|
|
83
84
|
/**
|
|
84
85
|
* Default value used first when the editor is instanciated.
|
|
85
86
|
*/
|
|
86
|
-
defaultValue?:
|
|
87
|
+
defaultValue?: string;
|
|
87
88
|
/**
|
|
88
89
|
* If enabled the code editor won't show numbers before each line.
|
|
89
90
|
*/
|
|
@@ -169,7 +170,7 @@ export interface CodeEditorProps extends TestableComponent {
|
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
const addExtensionsFor = (flag: boolean, ...extensions: Extension[]) => (flag ? [...extensions] : []);
|
|
172
|
-
const addToKeyMapConfigFor = (flag: boolean, ...keys:
|
|
173
|
+
const addToKeyMapConfigFor = (flag: boolean, ...keys: KeyBinding[]) => (flag ? [...keys] : []);
|
|
173
174
|
const addHandlersFor = (flag: boolean, handlerName: string, handler: any) =>
|
|
174
175
|
flag ? ({ [handlerName]: handler } as DOMEventHandlers<any>) : {};
|
|
175
176
|
|
|
@@ -221,7 +222,24 @@ export const CodeEditor = ({
|
|
|
221
222
|
}: CodeEditorProps) => {
|
|
222
223
|
const parent = useRef<any>(undefined);
|
|
223
224
|
const [view, setView] = React.useState<EditorView | undefined>();
|
|
225
|
+
const currentView = React.useRef<EditorView>()
|
|
226
|
+
currentView.current = view
|
|
227
|
+
const currentReadOnly = React.useRef(readOnly)
|
|
228
|
+
currentReadOnly.current = readOnly
|
|
224
229
|
const [showPreview, setShowPreview] = React.useState<boolean>(false);
|
|
230
|
+
// CodeMirror Compartments in order to allow for re-configuration after initialization
|
|
231
|
+
const readOnlyCompartment = React.useRef<Compartment>(compartment())
|
|
232
|
+
const wrapLinesCompartment = React.useRef<Compartment>(compartment())
|
|
233
|
+
const preventLineNumbersCompartment = React.useRef<Compartment>(compartment())
|
|
234
|
+
const shouldHaveMinimalSetupCompartment = React.useRef<Compartment>(compartment())
|
|
235
|
+
const placeholderCompartment = React.useRef<Compartment>(compartment())
|
|
236
|
+
const modeCompartment = React.useRef<Compartment>(compartment())
|
|
237
|
+
const keyMapConfigsCompartment = React.useRef<Compartment>(compartment())
|
|
238
|
+
const tabIntentSizeCompartment = React.useRef<Compartment>(compartment())
|
|
239
|
+
const disabledCompartment = React.useRef<Compartment>(compartment())
|
|
240
|
+
const supportCodeFoldingCompartment = React.useRef<Compartment>(compartment())
|
|
241
|
+
const useLintingCompartment = React.useRef<Compartment>(compartment())
|
|
242
|
+
const shouldHighlightActiveLineCompartment = React.useRef<Compartment>(compartment())
|
|
225
243
|
|
|
226
244
|
const linters = useMemo(() => {
|
|
227
245
|
if (!mode) {
|
|
@@ -240,17 +258,15 @@ export const CodeEditor = ({
|
|
|
240
258
|
|
|
241
259
|
const onKeyDownHandler = (event: KeyboardEvent, view: EditorView) => {
|
|
242
260
|
if (onKeyDown && !onKeyDown(event)) {
|
|
243
|
-
if (event.key === "Enter") {
|
|
261
|
+
if (event.key === "Enter" && !currentReadOnly.current) {
|
|
244
262
|
const cursor = view.state.selection.main.head;
|
|
245
|
-
const cursorLine = view.state.doc.lineAt(cursor).number;
|
|
246
|
-
const offsetFromFirstLine = view.state.doc.line(cursorLine).to;
|
|
247
263
|
view.dispatch({
|
|
248
264
|
changes: {
|
|
249
|
-
from:
|
|
265
|
+
from: cursor,
|
|
250
266
|
insert: "\n",
|
|
251
267
|
},
|
|
252
268
|
selection: {
|
|
253
|
-
anchor:
|
|
269
|
+
anchor: cursor + 1,
|
|
254
270
|
},
|
|
255
271
|
});
|
|
256
272
|
}
|
|
@@ -265,14 +281,17 @@ export const CodeEditor = ({
|
|
|
265
281
|
return false;
|
|
266
282
|
};
|
|
267
283
|
|
|
268
|
-
|
|
284
|
+
const createKeyMapConfigs = () => {
|
|
269
285
|
const tabIndent =
|
|
270
286
|
!!(tabIntentStyle === "tab" && mode && !(tabForceSpaceForModes ?? []).includes(mode)) || enableTab;
|
|
271
|
-
|
|
287
|
+
return [
|
|
272
288
|
defaultKeymap as KeyBinding,
|
|
273
|
-
...addToKeyMapConfigFor(supportCodeFolding, foldKeymap),
|
|
289
|
+
...addToKeyMapConfigFor(supportCodeFolding, ...foldKeymap),
|
|
274
290
|
...addToKeyMapConfigFor(tabIndent, indentWithTab),
|
|
275
291
|
];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
React.useEffect(() => {
|
|
276
295
|
const domEventHandlers = {
|
|
277
296
|
...addHandlersFor(!!onScroll, "scroll", onScroll),
|
|
278
297
|
...addHandlersFor(
|
|
@@ -286,13 +305,13 @@ export const CodeEditor = ({
|
|
|
286
305
|
} as DOMEventHandlers<any>;
|
|
287
306
|
const extensions = [
|
|
288
307
|
markField,
|
|
289
|
-
adaptedPlaceholder(placeholder),
|
|
308
|
+
placeholderCompartment.current.of(adaptedPlaceholder(placeholder)),
|
|
290
309
|
adaptedHighlightSpecialChars(),
|
|
291
|
-
useCodeMirrorModeExtension(mode),
|
|
292
|
-
keymap?.of(
|
|
293
|
-
EditorState?.tabSize.of(tabIntentSize),
|
|
294
|
-
EditorState?.readOnly.of(readOnly),
|
|
295
|
-
EditorView?.editable.of(!disabled),
|
|
310
|
+
modeCompartment.current.of(useCodeMirrorModeExtension(mode)),
|
|
311
|
+
keyMapConfigsCompartment.current.of(keymap?.of(createKeyMapConfigs())),
|
|
312
|
+
tabIntentSizeCompartment.current.of(EditorState?.tabSize.of(tabIntentSize)),
|
|
313
|
+
readOnlyCompartment.current.of(EditorState?.readOnly.of(readOnly)),
|
|
314
|
+
disabledCompartment.current.of(EditorView?.editable.of(!disabled)),
|
|
296
315
|
AdaptedEditorViewDomEventHandlers(domEventHandlers) as Extension,
|
|
297
316
|
EditorView?.updateListener.of((v: ViewUpdate) => {
|
|
298
317
|
if (disabled) return;
|
|
@@ -328,12 +347,12 @@ export const CodeEditor = ({
|
|
|
328
347
|
}
|
|
329
348
|
}
|
|
330
349
|
}),
|
|
331
|
-
addExtensionsFor(shouldHaveMinimalSetup, minimalSetup),
|
|
332
|
-
addExtensionsFor(!preventLineNumbers, adaptedLineNumbers()),
|
|
333
|
-
addExtensionsFor(shouldHighlightActiveLine, adaptedHighlightActiveLine()),
|
|
334
|
-
addExtensionsFor(wrapLines, EditorView?.lineWrapping),
|
|
335
|
-
addExtensionsFor(supportCodeFolding, adaptedFoldGutter(), adaptedCodeFolding()),
|
|
336
|
-
addExtensionsFor(useLinting, ...linters),
|
|
350
|
+
shouldHaveMinimalSetupCompartment.current.of(addExtensionsFor(shouldHaveMinimalSetup, minimalSetup)),
|
|
351
|
+
preventLineNumbersCompartment.current.of(addExtensionsFor(!preventLineNumbers, adaptedLineNumbers())),
|
|
352
|
+
shouldHighlightActiveLineCompartment.current.of(addExtensionsFor(shouldHighlightActiveLine, adaptedHighlightActiveLine())),
|
|
353
|
+
wrapLinesCompartment.current.of(addExtensionsFor(wrapLines, EditorView?.lineWrapping)),
|
|
354
|
+
supportCodeFoldingCompartment.current.of(addExtensionsFor(supportCodeFolding, adaptedFoldGutter(), adaptedCodeFolding())),
|
|
355
|
+
useLintingCompartment.current.of(addExtensionsFor(useLinting, ...linters)),
|
|
337
356
|
additionalExtensions,
|
|
338
357
|
];
|
|
339
358
|
|
|
@@ -375,7 +394,64 @@ export const CodeEditor = ({
|
|
|
375
394
|
setView(undefined);
|
|
376
395
|
}
|
|
377
396
|
};
|
|
378
|
-
}, [parent.current
|
|
397
|
+
}, [parent.current]);
|
|
398
|
+
|
|
399
|
+
// Updates an extension for a specific parameter that has changed after the initialization
|
|
400
|
+
const updateExtension = (extension: Extension | undefined, parameterCompartment: Compartment): void => {
|
|
401
|
+
if(extension) {
|
|
402
|
+
currentView.current?.dispatch({
|
|
403
|
+
effects: parameterCompartment.reconfigure(extension)
|
|
404
|
+
})
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
React.useEffect(() => {
|
|
409
|
+
updateExtension(EditorState?.readOnly.of(readOnly!), readOnlyCompartment.current)
|
|
410
|
+
}, [readOnly])
|
|
411
|
+
|
|
412
|
+
React.useEffect(() => {
|
|
413
|
+
updateExtension(adaptedPlaceholder(placeholder), placeholderCompartment.current)
|
|
414
|
+
}, [placeholder])
|
|
415
|
+
|
|
416
|
+
React.useEffect(() => {
|
|
417
|
+
updateExtension(useCodeMirrorModeExtension(mode), modeCompartment.current)
|
|
418
|
+
}, [mode])
|
|
419
|
+
|
|
420
|
+
React.useEffect(() => {
|
|
421
|
+
updateExtension(keymap?.of(createKeyMapConfigs()), keyMapConfigsCompartment.current)
|
|
422
|
+
}, [supportCodeFolding, mode, tabIntentStyle, (tabForceSpaceForModes ?? []).join(", "), enableTab])
|
|
423
|
+
|
|
424
|
+
React.useEffect(() => {
|
|
425
|
+
updateExtension(EditorState?.tabSize.of(tabIntentSize ?? 2), tabIntentSizeCompartment.current)
|
|
426
|
+
}, [tabIntentSize])
|
|
427
|
+
|
|
428
|
+
React.useEffect(() => {
|
|
429
|
+
updateExtension(EditorView?.editable.of(!disabled), disabledCompartment.current)
|
|
430
|
+
}, [disabled])
|
|
431
|
+
|
|
432
|
+
React.useEffect(() => {
|
|
433
|
+
updateExtension(addExtensionsFor(shouldHaveMinimalSetup ?? true, minimalSetup), shouldHaveMinimalSetupCompartment.current)
|
|
434
|
+
}, [shouldHaveMinimalSetup])
|
|
435
|
+
|
|
436
|
+
React.useEffect(() => {
|
|
437
|
+
updateExtension(addExtensionsFor(!preventLineNumbers, adaptedLineNumbers()), preventLineNumbersCompartment.current)
|
|
438
|
+
}, [preventLineNumbers])
|
|
439
|
+
|
|
440
|
+
React.useEffect(() => {
|
|
441
|
+
updateExtension(addExtensionsFor(shouldHighlightActiveLine ?? false, adaptedHighlightActiveLine()), shouldHighlightActiveLineCompartment.current)
|
|
442
|
+
}, [shouldHighlightActiveLine])
|
|
443
|
+
|
|
444
|
+
React.useEffect(() => {
|
|
445
|
+
updateExtension(addExtensionsFor(wrapLines ?? false, EditorView?.lineWrapping), wrapLinesCompartment.current)
|
|
446
|
+
}, [wrapLines])
|
|
447
|
+
|
|
448
|
+
React.useEffect(() => {
|
|
449
|
+
updateExtension(addExtensionsFor(supportCodeFolding ?? false, adaptedFoldGutter(), adaptedCodeFolding()), supportCodeFoldingCompartment.current)
|
|
450
|
+
}, [supportCodeFolding])
|
|
451
|
+
|
|
452
|
+
React.useEffect(() => {
|
|
453
|
+
updateExtension(addExtensionsFor(useLinting ?? false, ...linters), useLintingCompartment.current)
|
|
454
|
+
}, [mode, useLinting])
|
|
379
455
|
|
|
380
456
|
const hasToolbarSupport = mode && ModeToolbarSupport.indexOf(mode) > -1 && useToolbar;
|
|
381
457
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { EditorView, placeholder, highlightSpecialChars, lineNumbers, highlightActiveLine } from "@codemirror/view";
|
|
11
11
|
import { syntaxHighlighting, foldGutter, codeFolding } from "@codemirror/language";
|
|
12
|
-
import {
|
|
12
|
+
import {Extension, Compartment, StateEffect, EditorState} from "@codemirror/state";
|
|
13
13
|
import { lintGutter } from "@codemirror/lint";
|
|
14
14
|
|
|
15
15
|
/** placeholder extension, current error '_view.placeholder is not a function' */
|
|
@@ -34,6 +34,25 @@ export const AdaptedEditorView = isConstructor(EditorView)
|
|
|
34
34
|
destroy() {}
|
|
35
35
|
} as any);
|
|
36
36
|
|
|
37
|
+
/** Creates a new compartment or a mock of a compartment. */
|
|
38
|
+
export const compartment = () => {
|
|
39
|
+
if(isConstructor(Compartment)) {
|
|
40
|
+
return new Compartment()
|
|
41
|
+
} else {
|
|
42
|
+
let extension: Extension | undefined = undefined
|
|
43
|
+
return {
|
|
44
|
+
of: (ext: Extension): Extension => {
|
|
45
|
+
extension = ext
|
|
46
|
+
return ext
|
|
47
|
+
},
|
|
48
|
+
reconfigure: (_content: Extension): StateEffect<unknown> => {
|
|
49
|
+
return {} as StateEffect<any>
|
|
50
|
+
},
|
|
51
|
+
get: (_state: EditorState): Extension | undefined => extension
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
37
56
|
const emptyExtension = (() => {}) as any;
|
|
38
57
|
/** extension adding event handlers, current error '(view, domEventHandlers) is not a function' */
|
|
39
58
|
export const AdaptedEditorViewDomEventHandlers =
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { memo } from "react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { BaseEdge, Edge, EdgeProps, EdgeText, getBezierPath, getEdgeCenter } from "@xyflow/react";
|
|
4
|
+
|
|
5
|
+
import { IntentTypes } from "../../../common/Intent";
|
|
6
|
+
import { nodeContentUtils } from "../nodes/NodeContent";
|
|
7
|
+
import { NodeHighlightColor } from "../nodes/sharedTypes";
|
|
8
|
+
|
|
9
|
+
import { edgeDefaultUtils } from "./EdgeDefault";
|
|
10
|
+
|
|
11
|
+
export type EdgeDefaultV12DataProps = Record<string, unknown> & {
|
|
12
|
+
/**
|
|
13
|
+
* Overwrites the default style how the edge stroke is displayed.
|
|
14
|
+
*/
|
|
15
|
+
strokeType?: "solid" | "dashed" | "dotted" | "double" | "doubledashed";
|
|
16
|
+
/**
|
|
17
|
+
* Feedback state of the node.
|
|
18
|
+
*/
|
|
19
|
+
intent?: IntentTypes;
|
|
20
|
+
/**
|
|
21
|
+
* Set the color of used highlights to mark the edge.
|
|
22
|
+
*/
|
|
23
|
+
highlightColor?: NodeHighlightColor | [NodeHighlightColor, NodeHighlightColor];
|
|
24
|
+
/**
|
|
25
|
+
* Size of the "glow" effect when the edge is hovered.
|
|
26
|
+
*/
|
|
27
|
+
pathGlowWidth?: number;
|
|
28
|
+
/*
|
|
29
|
+
* Direction of the SVG path is inversed.
|
|
30
|
+
* This is important for the placement of the markers and the animation movement.
|
|
31
|
+
*/
|
|
32
|
+
inversePath?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Callback handler that returns a React element used as edge title.
|
|
35
|
+
*/
|
|
36
|
+
renderLabel?: (edgeCenter: [number, number, number, number]) => React.ReactNode;
|
|
37
|
+
/**
|
|
38
|
+
* Properties are forwarded to the internally used SVG `g` element.
|
|
39
|
+
* Data attributes for test ids coud be included here.
|
|
40
|
+
*/
|
|
41
|
+
edgeSvgProps?: React.SVGProps<SVGGElement>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* This element cannot be used directly, it must be connected via a `edgeTypes` definition.
|
|
46
|
+
* @see https://reactflow.dev/docs/api/nodes/
|
|
47
|
+
* @deprecated (v26) will be removed when `EdgeDefault` supports v12 directly
|
|
48
|
+
*/
|
|
49
|
+
export const EdgeDefaultV12 = memo(
|
|
50
|
+
({
|
|
51
|
+
id,
|
|
52
|
+
sourceX,
|
|
53
|
+
sourceY,
|
|
54
|
+
targetX,
|
|
55
|
+
targetY,
|
|
56
|
+
sourcePosition,
|
|
57
|
+
targetPosition,
|
|
58
|
+
label,
|
|
59
|
+
labelStyle,
|
|
60
|
+
labelShowBg,
|
|
61
|
+
labelBgStyle,
|
|
62
|
+
labelBgPadding = [5, 5],
|
|
63
|
+
labelBgBorderRadius = 3,
|
|
64
|
+
data = {},
|
|
65
|
+
...edgeOriginalProperties
|
|
66
|
+
}: EdgeProps<Edge<EdgeDefaultV12DataProps>>) => {
|
|
67
|
+
const { pathGlowWidth = 10, highlightColor, renderLabel, edgeSvgProps, intent, inversePath, strokeType } = data;
|
|
68
|
+
|
|
69
|
+
const [edgePath, labelX, labelY] = getBezierPath({
|
|
70
|
+
sourceX,
|
|
71
|
+
sourceY,
|
|
72
|
+
sourcePosition,
|
|
73
|
+
targetX,
|
|
74
|
+
targetY,
|
|
75
|
+
targetPosition,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const edgeStyle = edgeOriginalProperties.style ?? {};
|
|
79
|
+
const { highlightCustomPropertySettings } = nodeContentUtils.evaluateHighlightColors(
|
|
80
|
+
"--edge-highlight",
|
|
81
|
+
highlightColor
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const edgeCenter = getEdgeCenter({
|
|
85
|
+
sourceX,
|
|
86
|
+
sourceY,
|
|
87
|
+
targetX,
|
|
88
|
+
targetY,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const renderedLabel =
|
|
92
|
+
renderLabel?.([labelX, labelY, sourceX, targetX]) ??
|
|
93
|
+
(label ? (
|
|
94
|
+
<EdgeText
|
|
95
|
+
x={edgeCenter[0]}
|
|
96
|
+
y={edgeCenter[1]}
|
|
97
|
+
label={label}
|
|
98
|
+
labelStyle={labelStyle}
|
|
99
|
+
labelShowBg={labelShowBg}
|
|
100
|
+
labelBgStyle={labelBgStyle}
|
|
101
|
+
labelBgPadding={labelBgPadding || [5, 5]}
|
|
102
|
+
labelBgBorderRadius={labelBgBorderRadius || 3}
|
|
103
|
+
/>
|
|
104
|
+
) : null);
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<g
|
|
108
|
+
className={
|
|
109
|
+
"react-flow__edge " +
|
|
110
|
+
edgeDefaultUtils.createEdgeDefaultClassName(
|
|
111
|
+
{ intent },
|
|
112
|
+
`${edgeOriginalProperties.selected ? "selected" : ""}`
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
tabIndex={0}
|
|
116
|
+
role="button"
|
|
117
|
+
data-id={id}
|
|
118
|
+
aria-label={`Edge from ${edgeOriginalProperties.source} to ${edgeOriginalProperties.target}`}
|
|
119
|
+
aria-describedby={`react-flow__edge-desc-${id}`}
|
|
120
|
+
>
|
|
121
|
+
<g className={edgeSvgProps?.className ?? ""}>
|
|
122
|
+
{highlightColor && (
|
|
123
|
+
<path
|
|
124
|
+
d={edgePath}
|
|
125
|
+
className={edgeDefaultUtils.createEdgeDefaultClassName(
|
|
126
|
+
{ highlightColor },
|
|
127
|
+
"react-flow__edge-path-highlight"
|
|
128
|
+
)}
|
|
129
|
+
strokeWidth={10}
|
|
130
|
+
style={{
|
|
131
|
+
...highlightCustomPropertySettings,
|
|
132
|
+
}}
|
|
133
|
+
/>
|
|
134
|
+
)}
|
|
135
|
+
|
|
136
|
+
<BaseEdge
|
|
137
|
+
id={id}
|
|
138
|
+
path={edgePath}
|
|
139
|
+
markerStart={inversePath ? "url(#arrow-closed-reverse)" : undefined}
|
|
140
|
+
markerEnd={!inversePath ? "url(#arrow-closed)" : undefined}
|
|
141
|
+
className={edgeDefaultUtils.createEdgeDefaultClassName({ strokeType })}
|
|
142
|
+
interactionWidth={pathGlowWidth}
|
|
143
|
+
style={{
|
|
144
|
+
...edgeSvgProps?.style,
|
|
145
|
+
...edgeStyle,
|
|
146
|
+
color: edgeStyle.color || edgeStyle.stroke,
|
|
147
|
+
}}
|
|
148
|
+
/>
|
|
149
|
+
</g>
|
|
150
|
+
{renderedLabel}
|
|
151
|
+
</g>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export const EdgeDefs = React.memo(() => (
|
|
4
|
+
<svg style={{ position: "absolute", top: 0, left: 0 }}>
|
|
5
|
+
<defs>
|
|
6
|
+
<marker
|
|
7
|
+
id="arrow-closed"
|
|
8
|
+
viewBox="-10 -10 20 20"
|
|
9
|
+
markerWidth="10"
|
|
10
|
+
markerHeight="10"
|
|
11
|
+
refX="0"
|
|
12
|
+
refY="0"
|
|
13
|
+
orient="auto"
|
|
14
|
+
>
|
|
15
|
+
<path d="M-4,-4 L4,0 L-4,4 Z" fill="currentColor" />
|
|
16
|
+
</marker>
|
|
17
|
+
<marker
|
|
18
|
+
id="arrow-closed-reverse"
|
|
19
|
+
viewBox="-10 -10 20 20"
|
|
20
|
+
markerWidth="10"
|
|
21
|
+
markerHeight="10"
|
|
22
|
+
refX="0"
|
|
23
|
+
refY="0"
|
|
24
|
+
orient="auto-start-reverse"
|
|
25
|
+
>
|
|
26
|
+
<path d="M-4,-4 L4,0 L-4,4 Z" fill="currentColor" />
|
|
27
|
+
</marker>
|
|
28
|
+
</defs>
|
|
29
|
+
</svg>
|
|
30
|
+
));
|
|
@@ -62,6 +62,24 @@ path.react-flow__edge-path {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
path.react-flow__edge-interaction {
|
|
66
|
+
fill: none;
|
|
67
|
+
stroke: currentcolor;
|
|
68
|
+
stroke-linecap: round;
|
|
69
|
+
|
|
70
|
+
.react-flow__edge & {
|
|
71
|
+
stroke-opacity: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.react-flow__edge:hover & {
|
|
75
|
+
stroke-opacity: $reactflow-edge-stroke-opacity-hover * 0.2;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.react-flow__edge.selected & {
|
|
79
|
+
stroke-opacity: $reactflow-edge-stroke-opacity-selected * 0.2;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
65
83
|
path.react-flow__edge-path-glow {
|
|
66
84
|
fill: none;
|
|
67
85
|
stroke: currentcolor;
|