@eccenca/gui-elements 23.1.0-easynav.0 → 23.1.0-easynav.1
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/dist/cjs/extensions/react-flow/edges/EdgeLabel.js +58 -0
- package/dist/cjs/extensions/react-flow/edges/EdgeLabel.js.map +1 -0
- package/dist/cjs/extensions/react-flow/handles/HandleDefault.js +10 -2
- package/dist/cjs/extensions/react-flow/handles/HandleDefault.js.map +1 -1
- package/dist/cjs/extensions/react-flow/index.js +11 -0
- package/dist/cjs/extensions/react-flow/index.js.map +1 -1
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +35 -12
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/cjs/extensions/react-flow/nodes/NodeDefault.js +2 -1
- package/dist/cjs/extensions/react-flow/nodes/NodeDefault.js.map +1 -1
- package/dist/cjs/extensions/react-flow/versionsupport.js +17 -0
- package/dist/cjs/extensions/react-flow/versionsupport.js.map +1 -1
- package/dist/esm/extensions/react-flow/edges/EdgeLabel.js +47 -0
- package/dist/esm/extensions/react-flow/edges/EdgeLabel.js.map +1 -0
- package/dist/esm/extensions/react-flow/handles/HandleDefault.js +10 -2
- package/dist/esm/extensions/react-flow/handles/HandleDefault.js.map +1 -1
- package/dist/esm/extensions/react-flow/index.js +1 -0
- package/dist/esm/extensions/react-flow/index.js.map +1 -1
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js +43 -19
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/esm/extensions/react-flow/nodes/NodeDefault.js +2 -1
- package/dist/esm/extensions/react-flow/nodes/NodeDefault.js.map +1 -1
- package/dist/esm/extensions/react-flow/versionsupport.js +31 -1
- package/dist/esm/extensions/react-flow/versionsupport.js.map +1 -1
- package/dist/types/extensions/react-flow/edges/EdgeLabel.d.ts +32 -0
- package/dist/types/extensions/react-flow/index.d.ts +1 -0
- package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +16 -2
- package/dist/types/extensions/react-flow/versionsupport.d.ts +2 -1
- package/package.json +1 -1
- package/src/extensions/react-flow/_config.scss +1 -0
- package/src/extensions/react-flow/edges/EdgeLabel.tsx +83 -0
- package/src/extensions/react-flow/edges/_edges.scss +77 -0
- package/src/extensions/react-flow/edges/stories/EdgeLabel.stories.tsx +39 -0
- package/src/extensions/react-flow/handles/HandleDefault.tsx +18 -11
- package/src/extensions/react-flow/index.ts +1 -0
- package/src/extensions/react-flow/nodes/NodeContent.tsx +71 -22
- package/src/extensions/react-flow/nodes/NodeDefault.tsx +2 -2
- package/src/extensions/react-flow/nodes/_nodes.scss +43 -10
- package/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +32 -1
- package/src/extensions/react-flow/versionsupport.ts +17 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Position, useStoreState as useStoreStateFlowLegacy } from "react-flow-renderer";
|
|
3
3
|
import { useStore as useStoreStateFlowNext } from "react-flow-renderer-lts";
|
|
4
|
-
import { Icon, Depiction } from "../../../index";
|
|
4
|
+
import { Icon, Depiction, OverflowText } from "../../../index";
|
|
5
5
|
import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
|
|
6
6
|
import { ValidIconName } from "../../../components/Icon/canonicalIconNames";
|
|
7
7
|
import { DepictionProps } from "../../../components/Depiction/Depiction";
|
|
8
|
-
import { ReacFlowVersionSupportProps } from "../versionsupport";
|
|
8
|
+
import { ReacFlowVersionSupportProps, useReactFlowVersion } from "../versionsupport";
|
|
9
9
|
import { HandleDefault, HandleProps, HandleNextProps } from "./../handles/HandleDefault";
|
|
10
10
|
import { NodeProps } from "./NodeDefault";
|
|
11
11
|
import { NodeContentExtensionProps } from "./NodeContentExtension";
|
|
@@ -44,7 +44,11 @@ interface NodeContentData<CONTENT_PROPS = any> {
|
|
|
44
44
|
/**
|
|
45
45
|
* Label that is displayed in the node header.
|
|
46
46
|
*/
|
|
47
|
-
label: string;
|
|
47
|
+
label: string | JSX.Element;
|
|
48
|
+
/**
|
|
49
|
+
* Element that is displayed as subline under the label in the header.
|
|
50
|
+
*/
|
|
51
|
+
labelSubline?: JSX.Element;
|
|
48
52
|
/**
|
|
49
53
|
* Content element, displayed in the node body.
|
|
50
54
|
*/
|
|
@@ -72,6 +76,16 @@ export interface NodeContentProps<NODE_DATA, NODE_CONTENT_PROPS = any>
|
|
|
72
76
|
* If not set to `none` then the node is only displayed in normal size when it is selected.
|
|
73
77
|
*/
|
|
74
78
|
minimalShape?: "none" | "circular" | "rectangular";
|
|
79
|
+
/**
|
|
80
|
+
* Stretches the node to the full available width.
|
|
81
|
+
*/
|
|
82
|
+
fullWidth?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Increase the hight of the node header.
|
|
85
|
+
* Use this for example if you need more space for a label subline.
|
|
86
|
+
* Also the depiction is displayed larger.
|
|
87
|
+
*/
|
|
88
|
+
increadeHeader?: boolean;
|
|
75
89
|
/**
|
|
76
90
|
* Set the type of used highlights to mark the node.
|
|
77
91
|
*/
|
|
@@ -181,7 +195,17 @@ interface MemoHandlerNextProps extends HandleNextProps {
|
|
|
181
195
|
|
|
182
196
|
type MemoHandlerProps = MemoHandlerLegacyProps | MemoHandlerNextProps;
|
|
183
197
|
|
|
184
|
-
const defaultHandles =
|
|
198
|
+
const defaultHandles = () => {
|
|
199
|
+
const flowVersion = useReactFlowVersion();
|
|
200
|
+
switch (flowVersion) {
|
|
201
|
+
case "legacy":
|
|
202
|
+
return [{ type: "target" }, { type: "source" }] as IHandleProps[];
|
|
203
|
+
case "next":
|
|
204
|
+
return [{ type: "target" }, { type: "source" }] as NodeContentHandleNextProps[];
|
|
205
|
+
default:
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
185
209
|
|
|
186
210
|
const getDefaultMinimalTooltipData = (node: any) => {
|
|
187
211
|
return {
|
|
@@ -235,22 +259,25 @@ const MemoHandler = React.memo(
|
|
|
235
259
|
* This element cannot be used directly, all properties must be routed through the `data` property of an `elements` property item inside the `ReactFlow` container.
|
|
236
260
|
*/
|
|
237
261
|
export function NodeContent<CONTENT_PROPS = any>({
|
|
238
|
-
flowVersion =
|
|
262
|
+
flowVersion = useReactFlowVersion(),
|
|
239
263
|
iconName,
|
|
240
264
|
depiction,
|
|
241
265
|
leftElement,
|
|
242
266
|
typeLabel,
|
|
243
267
|
label,
|
|
268
|
+
labelSubline,
|
|
269
|
+
increadeHeader,
|
|
270
|
+
fullWidth,
|
|
244
271
|
showExecutionButtons = true,
|
|
245
272
|
executionButtons,
|
|
246
273
|
menuButtons,
|
|
247
274
|
content,
|
|
248
275
|
contentExtension,
|
|
249
|
-
|
|
276
|
+
footerContent,
|
|
250
277
|
size = "small",
|
|
251
278
|
minimalShape = "circular",
|
|
252
279
|
highlightedState,
|
|
253
|
-
handles = defaultHandles,
|
|
280
|
+
handles = defaultHandles(),
|
|
254
281
|
adaptHeightForHandleMinCount,
|
|
255
282
|
adaptSizeIncrement = 15,
|
|
256
283
|
getMinimalTooltipData = getDefaultMinimalTooltipData,
|
|
@@ -270,11 +297,15 @@ export function NodeContent<CONTENT_PROPS = any>({
|
|
|
270
297
|
// other props for DOM element
|
|
271
298
|
...otherProps
|
|
272
299
|
}: NodeContentProps<any>) {
|
|
300
|
+
const isResizeable = (!!onNodeResize && minimalShape === "none");
|
|
273
301
|
const [width, setWidth] = React.useState<number>(nodeDimensions?.width ?? 0);
|
|
274
302
|
const [height, setHeight] = React.useState<number>(nodeDimensions?.height ?? 0);
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
303
|
+
let zoom = 1;
|
|
304
|
+
if (isResizeable) try {
|
|
305
|
+
[, , zoom] = flowVersion === "legacy"
|
|
306
|
+
? useStoreStateFlowLegacy((state) => state.transform)
|
|
307
|
+
: useStoreStateFlowNext((state) => state.transform);
|
|
308
|
+
} catch {}
|
|
278
309
|
const [adjustedContentProps, setAdjustedContentProps] = React.useState<Partial<CONTENT_PROPS>>({});
|
|
279
310
|
const nodeContentRef = React.useRef<any>();
|
|
280
311
|
const handleStack = flowVersion==="legacy" ? {} as { [key: string]: IHandleProps[] } : {} as { [key: string]: NodeContentHandleNextProps[] };
|
|
@@ -346,6 +377,7 @@ export function NodeContent<CONTENT_PROPS = any>({
|
|
|
346
377
|
`${eccgui}-graphviz__node` +
|
|
347
378
|
` ${eccgui}-graphviz__node--${size}` +
|
|
348
379
|
` ${eccgui}-graphviz__node--minimal-${minimalShape}` +
|
|
380
|
+
(fullWidth ? ` ${eccgui}-graphviz__node--fullwidth` : "") +
|
|
349
381
|
(!!highlightedState
|
|
350
382
|
? " " + gethighlightedStateClasses(highlightedState, `${eccgui}-graphviz__node`)
|
|
351
383
|
: "") +
|
|
@@ -354,9 +386,12 @@ export function NodeContent<CONTENT_PROPS = any>({
|
|
|
354
386
|
(letPassWheelEvents === false ? ` nowheel` : "")
|
|
355
387
|
}
|
|
356
388
|
>
|
|
357
|
-
<header className={
|
|
389
|
+
<header className={
|
|
390
|
+
`${eccgui}-graphviz__node__header` +
|
|
391
|
+
((increadeHeader && minimalShape==="none") ? ` ${eccgui}-graphviz__node__header--large` : "")
|
|
392
|
+
}>
|
|
358
393
|
{(!!iconName || !!depiction || !!leftElement) && (
|
|
359
|
-
<
|
|
394
|
+
<div className={`${eccgui}-graphviz__node__header-depiction`}>
|
|
360
395
|
{ leftElement }
|
|
361
396
|
{!!depiction && !leftElement && typeof depiction === "string" && (
|
|
362
397
|
<Depiction
|
|
@@ -380,23 +415,37 @@ export function NodeContent<CONTENT_PROPS = any>({
|
|
|
380
415
|
})
|
|
381
416
|
)}
|
|
382
417
|
{!!iconName && !leftElement && !depiction && (
|
|
383
|
-
<
|
|
384
|
-
name={iconName}
|
|
385
|
-
|
|
418
|
+
<Depiction
|
|
419
|
+
image={<Icon name={iconName} />}
|
|
420
|
+
caption={minimalShape === "none" || selected ? typeLabel : undefined}
|
|
421
|
+
captionPosition="tooltip"
|
|
422
|
+
padding="tiny"
|
|
423
|
+
ratio="1:1"
|
|
424
|
+
resizing="contain"
|
|
425
|
+
forceInlineSvg
|
|
386
426
|
/>
|
|
387
427
|
)}
|
|
388
|
-
</
|
|
428
|
+
</div>
|
|
389
429
|
)}
|
|
390
|
-
<
|
|
391
|
-
{
|
|
392
|
-
|
|
430
|
+
<div className={`${eccgui}-graphviz__node__header-label`} title={typeof label==="string" ? label : undefined}>
|
|
431
|
+
{
|
|
432
|
+
typeof label === "string"
|
|
433
|
+
? <OverflowText className={`${eccgui}-graphviz__node__header-label__mainline`}>{label}</OverflowText>
|
|
434
|
+
: <div className={`${eccgui}-graphviz__node__header-label__mainline`}>{label}</div>
|
|
435
|
+
}
|
|
436
|
+
{!!labelSubline && (
|
|
437
|
+
<div className={`${eccgui}-graphviz__node__header-label__subline`}>
|
|
438
|
+
{ labelSubline }
|
|
439
|
+
</div>
|
|
440
|
+
)}
|
|
441
|
+
</div>
|
|
393
442
|
{(menuButtons || (showExecutionButtons && executionButtons)) && (
|
|
394
|
-
<
|
|
443
|
+
<div className={`${eccgui}-graphviz__node__header-menu`}>
|
|
395
444
|
{showExecutionButtons && typeof executionButtons === "function"
|
|
396
445
|
? executionButtons(adjustedContentProps, setAdjustedContentProps)
|
|
397
446
|
: null}
|
|
398
447
|
{menuButtons ?? null}
|
|
399
|
-
</
|
|
448
|
+
</div>
|
|
400
449
|
)}
|
|
401
450
|
</header>
|
|
402
451
|
{content && (
|
|
@@ -449,5 +498,5 @@ export function NodeContent<CONTENT_PROPS = any>({
|
|
|
449
498
|
</Resizable>
|
|
450
499
|
);
|
|
451
500
|
|
|
452
|
-
return (
|
|
501
|
+
return (isResizeable) ? resizableNode() : nodeContent;
|
|
453
502
|
}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "react-flow-renderer";
|
|
6
6
|
import { Tooltip } from "../../../index";
|
|
7
7
|
import { NodeContent, NodeContentProps } from "./NodeContent";
|
|
8
|
-
import { ReacFlowVersionSupportProps } from "../versionsupport";
|
|
8
|
+
import { ReacFlowVersionSupportProps, useReactFlowVersion } from "../versionsupport";
|
|
9
9
|
|
|
10
10
|
export interface NodeProps<NODE_DATA, NODE_CONTENT_PROPS = any> extends ReacFlowVersionSupportProps, ReactFlowNodeProps {
|
|
11
11
|
/**
|
|
@@ -23,7 +23,7 @@ export interface NodeProps<NODE_DATA, NODE_CONTENT_PROPS = any> extends ReacFlow
|
|
|
23
23
|
export const NodeDefault = memo(
|
|
24
24
|
(node: NodeProps<any>) => {
|
|
25
25
|
const {
|
|
26
|
-
flowVersion,
|
|
26
|
+
flowVersion = useReactFlowVersion(),
|
|
27
27
|
data,
|
|
28
28
|
targetPosition = Position.Left,
|
|
29
29
|
sourcePosition = Position.Right,
|
|
@@ -120,22 +120,20 @@
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
.#{$eccgui}-graphviz__node__header--large {
|
|
124
|
+
min-height: $reactflow-node-largesize;
|
|
125
|
+
}
|
|
126
|
+
|
|
123
127
|
.#{$eccgui}-graphviz__node__header-depiction,
|
|
124
128
|
.#{$eccgui}-graphviz__node__header-menu {
|
|
125
129
|
flex-grow: 0;
|
|
126
130
|
flex-shrink: 0;
|
|
127
131
|
max-height: calc(#{$reactflow-node-basesize} - #{2 * $reactflow-node-border-width});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.#{$eccgui}-graphviz__node__header-label {
|
|
131
132
|
margin: 0 $eccgui-size-block-whitespace * 0.25;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
flex-shrink: 1;
|
|
137
|
-
display: inline-block;
|
|
138
|
-
text-align: left;
|
|
133
|
+
|
|
134
|
+
.#{$eccgui}-graphviz__node__header--large & {
|
|
135
|
+
max-height: calc(#{$reactflow-node-largesize} - #{2 * $reactflow-node-border-width});
|
|
136
|
+
}
|
|
139
137
|
}
|
|
140
138
|
|
|
141
139
|
.#{$eccgui}-graphviz__node__header-depiction {
|
|
@@ -165,6 +163,37 @@
|
|
|
165
163
|
height: calc(#{$reactflow-node-basesize} - #{2 * $reactflow-node-border-width});
|
|
166
164
|
}
|
|
167
165
|
}
|
|
166
|
+
|
|
167
|
+
.#{$eccgui}-graphviz__node__header--large & {
|
|
168
|
+
min-width: calc(#{$reactflow-node-largesize} - #{2 * $reactflow-node-border-width});
|
|
169
|
+
min-height: calc(#{$reactflow-node-largesize} - #{2 * $reactflow-node-border-width});
|
|
170
|
+
max-width: calc(2 * (#{$reactflow-node-largesize} - #{2 * $reactflow-node-border-width}));
|
|
171
|
+
|
|
172
|
+
.#{$eccgui}-depiction__image {
|
|
173
|
+
height: calc(#{$reactflow-node-largesize} - #{2 * $reactflow-node-border-width});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.#{$eccgui}-graphviz__node__header-label {
|
|
179
|
+
margin: 0 $eccgui-size-block-whitespace * 0.25;
|
|
180
|
+
white-space: nowrap;
|
|
181
|
+
overflow: hidden;
|
|
182
|
+
text-overflow: ellipsis;
|
|
183
|
+
flex-grow: 1;
|
|
184
|
+
flex-shrink: 1;
|
|
185
|
+
display: inline-flex;
|
|
186
|
+
flex-direction: column;
|
|
187
|
+
text-align: left;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.#{$eccgui}-graphviz__node__header-label__mainline,
|
|
191
|
+
.#{$eccgui}-graphviz__node__header-label__subline {
|
|
192
|
+
overflow: hidden;
|
|
193
|
+
text-overflow: ellipsis;
|
|
194
|
+
white-space: nowrap;
|
|
195
|
+
flex-grow: 0;
|
|
196
|
+
flex-shrink: 0;
|
|
168
197
|
}
|
|
169
198
|
|
|
170
199
|
.#{$eccgui}-graphviz__node__content {
|
|
@@ -231,6 +260,10 @@
|
|
|
231
260
|
max-height: $reactflow-node-basesize * 13;
|
|
232
261
|
}
|
|
233
262
|
|
|
263
|
+
.#{$eccgui}-graphviz__node--fullwidth:not(.is-resizeable) {
|
|
264
|
+
width: 100%;
|
|
265
|
+
}
|
|
266
|
+
|
|
234
267
|
// Node highlights
|
|
235
268
|
|
|
236
269
|
.#{$eccgui}-graphviz__node--highlight-success,
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import React, { useState, useEffect, useCallback } from "react";
|
|
2
2
|
import { ComponentStory, ComponentMeta } from "@storybook/react";
|
|
3
|
-
import { LoremIpsum } from 'react-lorem-ipsum';
|
|
3
|
+
import { LoremIpsum, loremIpsum } from 'react-lorem-ipsum';
|
|
4
4
|
import ReactFlow, { Elements, ReactFlowProvider } from 'react-flow-renderer';
|
|
5
5
|
import {
|
|
6
|
+
Badge,
|
|
7
|
+
ContextMenu,
|
|
8
|
+
MenuItem,
|
|
6
9
|
OverflowText,
|
|
7
10
|
HtmlContentBlock,
|
|
11
|
+
IconButton,
|
|
12
|
+
Tag,
|
|
13
|
+
TagList,
|
|
8
14
|
} from "./../../../../index";
|
|
9
15
|
import canonicalIcons from "./../../../../components/Icon/canonicalIconNames";
|
|
10
16
|
|
|
@@ -30,6 +36,31 @@ export default {
|
|
|
30
36
|
"Slide out example": <NodeContentExtension {...ContentExtensionExampleSlideOut.args} />,
|
|
31
37
|
},
|
|
32
38
|
},
|
|
39
|
+
labelSubline: {
|
|
40
|
+
control: "select",
|
|
41
|
+
options: ["Not set", "Text string", "OverflowText element", "Tag list"],
|
|
42
|
+
mapping: {
|
|
43
|
+
"Not set": undefined,
|
|
44
|
+
"Text string": loremIpsum({ p: 1, avgSentencesPerParagraph: 1, avgWordsPerSentence: 8, random: false }).toString(),
|
|
45
|
+
"OverflowText element": <OverflowText>{loremIpsum({ p: 1, avgSentencesPerParagraph: 2, avgWordsPerSentence: 4, random: false }).toString()}</OverflowText>,
|
|
46
|
+
"Tag list": <TagList>{
|
|
47
|
+
loremIpsum({ p: 1, avgSentencesPerParagraph: 1, avgWordsPerSentence: 5, random: false })
|
|
48
|
+
.toString()
|
|
49
|
+
.split(" ")
|
|
50
|
+
.map((term) => <Tag small>{term}</Tag>)
|
|
51
|
+
}</TagList>
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
menuButtons: {
|
|
55
|
+
control: "select",
|
|
56
|
+
options: ["Not set", "Icon button", "Context Menu", "Info badge"],
|
|
57
|
+
mapping: {
|
|
58
|
+
"Not set": undefined,
|
|
59
|
+
"Icon button": <IconButton name="item-info" text="Icon button" onClick={()=>alert("Click info")} />,
|
|
60
|
+
"Context Menu": <ContextMenu><MenuItem text="Context menu" /></ContextMenu>,
|
|
61
|
+
"Info badge": <Badge intent="info">Info</Badge>,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
33
64
|
iconName: {
|
|
34
65
|
control: "select",
|
|
35
66
|
options: [...(Object.keys(canonicalIcons))],
|
|
@@ -1,6 +1,22 @@
|
|
|
1
|
+
import { useStoreState as useStoreStateFlowLegacy } from "react-flow-renderer";
|
|
2
|
+
import { useStore as useStoreStateFlowNext } from "react-flow-renderer-lts";
|
|
3
|
+
|
|
1
4
|
export interface ReacFlowVersionSupportProps {
|
|
2
5
|
/**
|
|
3
6
|
* Spevifies the context of the react flow renderer version that is used for the component.
|
|
4
7
|
*/
|
|
5
|
-
flowVersion?: "legacy" | "next";
|
|
8
|
+
flowVersion?: "legacy" | "next" | "none";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const useReactFlowVersion = () => {
|
|
12
|
+
try {
|
|
13
|
+
const [, , zoom] = useStoreStateFlowLegacy((state) => state.transform);
|
|
14
|
+
return !!zoom ? "legacy" : "none";
|
|
15
|
+
} catch {}
|
|
16
|
+
try {
|
|
17
|
+
const [, , zoom] = useStoreStateFlowNext((state) => state.transform);
|
|
18
|
+
return !!zoom ? "next" : "none";
|
|
19
|
+
} catch {}
|
|
20
|
+
|
|
21
|
+
return "none";
|
|
6
22
|
}
|