@eccenca/gui-elements 23.6.0 → 23.7.0-rc.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.
Files changed (107) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cjs/cmem/markdown/Markdown.js +10 -2
  3. package/dist/cjs/cmem/markdown/Markdown.js.map +1 -1
  4. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +4 -4
  5. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  6. package/dist/cjs/common/index.js +2 -0
  7. package/dist/cjs/common/index.js.map +1 -1
  8. package/dist/cjs/common/utils/getScrollParent.js +24 -0
  9. package/dist/cjs/common/utils/getScrollParent.js.map +1 -0
  10. package/dist/cjs/components/AutocompleteField/AutoCompleteField.js +19 -2
  11. package/dist/cjs/components/AutocompleteField/AutoCompleteField.js.map +1 -1
  12. package/dist/cjs/components/MultiSelect/MultiSelect.js +66 -41
  13. package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
  14. package/dist/cjs/components/Sticky/StickyTarget.js +85 -0
  15. package/dist/cjs/components/Sticky/StickyTarget.js.map +1 -0
  16. package/dist/cjs/components/Sticky/index.js +14 -0
  17. package/dist/cjs/components/Sticky/index.js.map +1 -0
  18. package/dist/cjs/components/index.js +1 -0
  19. package/dist/cjs/components/index.js.map +1 -1
  20. package/dist/cjs/extensions/codemirror/CodeMirror.js +1 -1
  21. package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
  22. package/dist/cjs/extensions/react-flow/edges/EdgeDefault.js +7 -7
  23. package/dist/cjs/extensions/react-flow/edges/EdgeDefault.js.map +1 -1
  24. package/dist/cjs/extensions/react-flow/edges/EdgeLabel.js +3 -2
  25. package/dist/cjs/extensions/react-flow/edges/EdgeLabel.js.map +1 -1
  26. package/dist/cjs/extensions/react-flow/handles/HandleContent.js +14 -2
  27. package/dist/cjs/extensions/react-flow/handles/HandleContent.js.map +1 -1
  28. package/dist/cjs/extensions/react-flow/handles/HandleTools.js +1 -1
  29. package/dist/cjs/extensions/react-flow/handles/HandleTools.js.map +1 -1
  30. package/dist/cjs/extensions/react-flow/minimap/MiniMap.js +6 -8
  31. package/dist/cjs/extensions/react-flow/minimap/MiniMap.js.map +1 -1
  32. package/dist/esm/cmem/markdown/Markdown.js +10 -2
  33. package/dist/esm/cmem/markdown/Markdown.js.map +1 -1
  34. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +5 -5
  35. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  36. package/dist/esm/common/index.js +2 -0
  37. package/dist/esm/common/index.js.map +1 -1
  38. package/dist/esm/common/utils/getScrollParent.js +20 -0
  39. package/dist/esm/common/utils/getScrollParent.js.map +1 -0
  40. package/dist/esm/components/AutocompleteField/AutoCompleteField.js +27 -2
  41. package/dist/esm/components/AutocompleteField/AutoCompleteField.js.map +1 -1
  42. package/dist/esm/components/MultiSelect/MultiSelect.js +72 -52
  43. package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
  44. package/dist/esm/components/Sticky/StickyTarget.js +89 -0
  45. package/dist/esm/components/Sticky/StickyTarget.js.map +1 -0
  46. package/dist/esm/components/Sticky/index.js +2 -0
  47. package/dist/esm/components/Sticky/index.js.map +1 -0
  48. package/dist/esm/components/index.js +1 -0
  49. package/dist/esm/components/index.js.map +1 -1
  50. package/dist/esm/extensions/codemirror/CodeMirror.js +1 -1
  51. package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
  52. package/dist/esm/extensions/react-flow/edges/EdgeDefault.js +7 -7
  53. package/dist/esm/extensions/react-flow/edges/EdgeDefault.js.map +1 -1
  54. package/dist/esm/extensions/react-flow/edges/EdgeLabel.js +3 -2
  55. package/dist/esm/extensions/react-flow/edges/EdgeLabel.js.map +1 -1
  56. package/dist/esm/extensions/react-flow/handles/HandleContent.js +13 -2
  57. package/dist/esm/extensions/react-flow/handles/HandleContent.js.map +1 -1
  58. package/dist/esm/extensions/react-flow/handles/HandleTools.js +1 -1
  59. package/dist/esm/extensions/react-flow/handles/HandleTools.js.map +1 -1
  60. package/dist/esm/extensions/react-flow/minimap/MiniMap.js +6 -8
  61. package/dist/esm/extensions/react-flow/minimap/MiniMap.js.map +1 -1
  62. package/dist/types/cmem/react-flow/StickyNoteModal/StickyNoteModal.d.ts +5 -0
  63. package/dist/types/cmem/react-flow/configuration/graph.d.ts +9 -9
  64. package/dist/types/cmem/react-flow/configuration/unspecified.d.ts +2 -2
  65. package/dist/types/common/index.d.ts +2 -0
  66. package/dist/types/common/utils/getScrollParent.d.ts +9 -0
  67. package/dist/types/components/AutocompleteField/AutoCompleteField.d.ts +2 -0
  68. package/dist/types/components/MultiSelect/MultiSelect.d.ts +1 -1
  69. package/dist/types/components/Sticky/StickyTarget.d.ts +32 -0
  70. package/dist/types/components/Sticky/index.d.ts +1 -0
  71. package/dist/types/components/index.d.ts +1 -0
  72. package/dist/types/extensions/react-flow/edges/EdgeDefault.d.ts +6 -1
  73. package/dist/types/extensions/react-flow/edges/EdgeLabel.d.ts +1 -1
  74. package/dist/types/extensions/react-flow/edges/edgeTypes.d.ts +10 -10
  75. package/dist/types/extensions/react-flow/handles/HandleContent.d.ts +2 -3
  76. package/dist/types/extensions/react-flow/minimap/MiniMap.d.ts +12 -1
  77. package/package.json +3 -1
  78. package/src/cmem/markdown/Markdown.stories.tsx +8 -1
  79. package/src/cmem/markdown/Markdown.tsx +22 -1
  80. package/src/cmem/react-flow/ReactFlow/ReactFlow.stories.tsx +10 -4
  81. package/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx +8 -3
  82. package/src/common/index.ts +3 -0
  83. package/src/common/utils/getScrollParent.ts +20 -0
  84. package/src/components/AutocompleteField/AutoCompleteField.tsx +28 -0
  85. package/src/components/AutocompleteField/autocompletefield.scss +1 -1
  86. package/src/components/MultiSelect/MultiSelect.tsx +72 -47
  87. package/src/components/MultiSuggestField/MultiSuggestField.stories.tsx +146 -26
  88. package/src/components/MultiSuggestField/tests/MultiSuggestField.test.tsx +363 -61
  89. package/src/components/Sticky/StickyTarget.tsx +119 -0
  90. package/src/components/Sticky/index.ts +1 -0
  91. package/src/components/Sticky/sticky.scss +69 -0
  92. package/src/components/Sticky/stories/StickyTarget.stories.tsx +63 -0
  93. package/src/components/index.scss +1 -0
  94. package/src/components/index.ts +1 -0
  95. package/src/extensions/codemirror/CodeMirror.tsx +1 -1
  96. package/src/extensions/react-flow/edges/EdgeDefault.tsx +70 -62
  97. package/src/extensions/react-flow/edges/EdgeLabel.tsx +14 -2
  98. package/src/extensions/react-flow/edges/stories/EdgeDefault.stories.tsx +11 -5
  99. package/src/extensions/react-flow/edges/stories/EdgeLabel.stories.tsx +2 -0
  100. package/src/extensions/react-flow/handles/HandleContent.tsx +28 -25
  101. package/src/extensions/react-flow/handles/HandleTools.tsx +1 -0
  102. package/src/extensions/react-flow/handles/stories/HandleDefault.stories.tsx +5 -1
  103. package/src/extensions/react-flow/minimap/MiniMap.stories.tsx +62 -0
  104. package/src/extensions/react-flow/minimap/MiniMap.tsx +23 -7
  105. package/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +2 -0
  106. package/src/extensions/react-flow/nodes/stories/NodeContentExtension.stories.tsx +2 -0
  107. package/src/extensions/react-flow/nodes/stories/NodeDefault.stories.tsx +0 -1
@@ -0,0 +1,63 @@
1
+ import React from "react";
2
+ import { LoremIpsum } from "react-lorem-ipsum";
3
+ import { Meta, Story } from "@storybook/react";
4
+
5
+ import { HtmlContentBlock, StickyTarget } from "../../../../index";
6
+
7
+ export default {
8
+ title: "Components/StickyTarget",
9
+ component: StickyTarget,
10
+ argTypes: {},
11
+ } as Meta<typeof StickyTarget>;
12
+
13
+ const Template: Story<typeof StickyTarget> = (args) => (
14
+ <div style={{ height: "10rem", overflow: "auto", position: "relative" }}>
15
+ <HtmlContentBlock>
16
+ {args.getConnectedElement && args.to !== "bottom" && (
17
+ <p
18
+ id="connected-element"
19
+ style={{ background: "red", color: "white", padding: "0.5rem", position: "fixed", top: "20px" }}
20
+ >
21
+ Top element.
22
+ </p>
23
+ )}
24
+ <LoremIpsum p={3} avgSentencesPerParagraph={5} random={false} />
25
+ <StickyTarget {...args} style={args.to === "bottom" ? { zIndex: 2 } : undefined}>
26
+ <p style={{ color: "red", padding: "0.5rem" }}>First sticky element.</p>
27
+ </StickyTarget>
28
+ <LoremIpsum p={5} avgSentencesPerParagraph={5} random={false} />
29
+ <div>
30
+ <StickyTarget {...args}>
31
+ <p style={{ color: "green", padding: "0.5rem" }}>Sticky element.</p>
32
+ </StickyTarget>
33
+ <LoremIpsum p={5} avgSentencesPerParagraph={5} random={false} />
34
+ </div>
35
+ <StickyTarget {...args}>
36
+ <p style={{ color: "blue", padding: "0.5rem" }}>Another sticky element.</p>
37
+ </StickyTarget>
38
+ <LoremIpsum p={5} avgSentencesPerParagraph={5} random={false} />
39
+ {args.getConnectedElement && args.to === "bottom" && (
40
+ <p
41
+ id="connected-element"
42
+ style={{ background: "red", color: "white", padding: "0.5rem", position: "fixed", bottom: "20px" }}
43
+ >
44
+ Bottom element.
45
+ </p>
46
+ )}
47
+ </HtmlContentBlock>
48
+ </div>
49
+ );
50
+
51
+ export const Default = Template.bind({});
52
+ Default.args = {
53
+ className: "stickytarget-extraclass",
54
+ "data-test-id": "stickytarget-test-id",
55
+ "data-testid": "stickytarget-testid",
56
+ };
57
+
58
+ export const ConnectedElement = Template.bind({});
59
+ ConnectedElement.args = {
60
+ getConnectedElement: () => {
61
+ return window.document.getElementById("connected-element") || false;
62
+ },
63
+ };
@@ -24,6 +24,7 @@
24
24
  @import "./Separation/separation";
25
25
  @import "./Skeleton/skeleton";
26
26
  @import "./Spinner/spinner";
27
+ @import "./Sticky/sticky";
27
28
  @import "./Structure/titles";
28
29
  @import "./Table/table";
29
30
  @import "./Tabs/tabs";
@@ -36,6 +36,7 @@ export * from "./Separation/Divider";
36
36
  export * from "./Separation/Spacing";
37
37
  export * from "./Skeleton/Skeleton";
38
38
  export * from "./Spinner/Spinner";
39
+ export * from "./Sticky";
39
40
  export * from "./Structure";
40
41
  export * from "./Switch/Switch";
41
42
  export * from "./Table";
@@ -114,7 +114,7 @@ export const CodeEditor = ({
114
114
  id,
115
115
  mode = "undefined",
116
116
  preventLineNumbers = false,
117
- defaultValue,
117
+ defaultValue = "",
118
118
  readOnly = false,
119
119
  height,
120
120
  wrapLines = false,
@@ -39,6 +39,11 @@ export interface EdgeDefaultDataProps {
39
39
  * Callback handler that returns a React element used as edge title.
40
40
  */
41
41
  renderLabel?: (edgeCenter: [number, number, number, number]) => React.ReactNode;
42
+ /**
43
+ * Properties are forwarded to the internally used SVG `g` element.
44
+ * Data attributes for test ids coud be included here.
45
+ */
46
+ edgeSvgProps?: React.SVGProps<SVGGElement>;
42
47
  }
43
48
 
44
49
  export interface EdgeDefaultProps extends ReactFlowEdgeProps {
@@ -52,75 +57,78 @@ export interface EdgeDefaultProps extends ReactFlowEdgeProps {
52
57
  drawSvgPath?: (edge: ReactFlowEdgeProps) => string;
53
58
  }
54
59
 
55
- export const EdgeDefault = memo((edge: EdgeDefaultProps) => {
56
- const { data = {}, drawSvgPath = drawEdgeStraight, ...edgeOriginalProperties } = edge;
57
- const { pathGlowWidth = 10, markerStart, strokeType, intent, highlightColor } = data;
60
+ export const EdgeDefault = memo(
61
+ ({ data = {}, drawSvgPath = drawEdgeStraight, ...edgeOriginalProperties }: EdgeDefaultProps) => {
62
+ const { pathGlowWidth = 10, markerStart, strokeType, intent, highlightColor, edgeSvgProps } = data;
58
63
 
59
- const pathDisplay = drawSvgPath({ ...edgeOriginalProperties, data });
60
- const markerEnd = getMarkerEnd(edgeOriginalProperties.arrowHeadType, edgeOriginalProperties.markerEndId);
61
- const edgeCenter = getEdgeCenter({
62
- sourceX: edgeOriginalProperties.sourceX,
63
- sourceY: edgeOriginalProperties.sourceY,
64
- targetX: edgeOriginalProperties.targetX,
65
- targetY: edgeOriginalProperties.targetY,
66
- });
64
+ const pathDisplay = drawSvgPath({ ...edgeOriginalProperties, data });
65
+ const markerEnd = getMarkerEnd(edgeOriginalProperties.arrowHeadType, edgeOriginalProperties.markerEndId);
66
+ const edgeCenter = getEdgeCenter({
67
+ sourceX: edgeOriginalProperties.sourceX,
68
+ sourceY: edgeOriginalProperties.sourceY,
69
+ targetX: edgeOriginalProperties.targetX,
70
+ targetY: edgeOriginalProperties.targetY,
71
+ });
67
72
 
68
- const edgeLabel =
69
- data.renderLabel?.(edgeCenter) ??
70
- (edgeOriginalProperties.label ? (
71
- <EdgeText
72
- x={edgeCenter[0]}
73
- y={edgeCenter[1]}
74
- label={edgeOriginalProperties.label}
75
- labelStyle={edgeOriginalProperties.labelStyle}
76
- labelShowBg={edgeOriginalProperties.labelShowBg}
77
- labelBgStyle={edgeOriginalProperties.labelBgStyle}
78
- labelBgPadding={edgeOriginalProperties.labelBgPadding || [5, 5]}
79
- labelBgBorderRadius={edgeOriginalProperties.labelBgBorderRadius || 3}
80
- />
81
- ) : null);
73
+ const edgeLabel =
74
+ data.renderLabel?.(edgeCenter) ??
75
+ (edgeOriginalProperties.label ? (
76
+ <EdgeText
77
+ x={edgeCenter[0]}
78
+ y={edgeCenter[1]}
79
+ label={edgeOriginalProperties.label}
80
+ labelStyle={edgeOriginalProperties.labelStyle}
81
+ labelShowBg={edgeOriginalProperties.labelShowBg}
82
+ labelBgStyle={edgeOriginalProperties.labelBgStyle}
83
+ labelBgPadding={edgeOriginalProperties.labelBgPadding || [5, 5]}
84
+ labelBgBorderRadius={edgeOriginalProperties.labelBgBorderRadius || 3}
85
+ />
86
+ ) : null);
82
87
 
83
- const edgeStyle = edgeOriginalProperties.style ?? {};
84
- const { highlightCustomPropertySettings } = nodeContentUtils.evaluateHighlightColors(
85
- "--edge-highlight",
86
- highlightColor
87
- );
88
+ const edgeStyle = edgeOriginalProperties.style ?? {};
89
+ const { highlightCustomPropertySettings } = nodeContentUtils.evaluateHighlightColors(
90
+ "--edge-highlight",
91
+ highlightColor
92
+ );
88
93
 
89
- return (
90
- <g
91
- className={createEdgeDefaultClassName({ intent }, "")}
92
- style={{
93
- ...edgeStyle,
94
- color: edgeStyle.color || edgeStyle.stroke,
95
- }}
96
- >
97
- {highlightColor && (
94
+ return (
95
+ <g
96
+ {...edgeSvgProps}
97
+ className={createEdgeDefaultClassName({ intent }, edgeSvgProps?.className ?? "")}
98
+ style={{
99
+ ...edgeSvgProps?.style,
100
+ ...edgeStyle,
101
+ color: edgeStyle.color || edgeStyle.stroke,
102
+ }}
103
+ >
104
+ {highlightColor && (
105
+ <path
106
+ d={pathDisplay}
107
+ className={createEdgeDefaultClassName({ highlightColor }, "react-flow__edge-path-highlight")}
108
+ strokeWidth={pathGlowWidth}
109
+ style={{
110
+ ...highlightCustomPropertySettings,
111
+ }}
112
+ />
113
+ )}
114
+ {pathGlowWidth && (
115
+ <path
116
+ d={pathDisplay}
117
+ className={createEdgeDefaultClassName({}, "react-flow__edge-path-glow")}
118
+ strokeWidth={pathGlowWidth}
119
+ />
120
+ )}
98
121
  <path
99
122
  d={pathDisplay}
100
- className={createEdgeDefaultClassName({ highlightColor }, "react-flow__edge-path-highlight")}
101
- strokeWidth={pathGlowWidth}
102
- style={{
103
- ...highlightCustomPropertySettings,
104
- }}
123
+ className={createEdgeDefaultClassName({ strokeType })}
124
+ markerStart={markerStart}
125
+ markerEnd={markerEnd}
105
126
  />
106
- )}
107
- {pathGlowWidth && (
108
- <path
109
- d={pathDisplay}
110
- className={createEdgeDefaultClassName({}, "react-flow__edge-path-glow")}
111
- strokeWidth={pathGlowWidth}
112
- />
113
- )}
114
- <path
115
- d={pathDisplay}
116
- className={createEdgeDefaultClassName({ strokeType })}
117
- markerStart={markerStart}
118
- markerEnd={markerEnd}
119
- />
120
- {edgeLabel}
121
- </g>
122
- );
123
- });
127
+ {edgeLabel}
128
+ </g>
129
+ );
130
+ }
131
+ );
124
132
 
125
133
  const createEdgeDefaultClassName = (
126
134
  { strokeType, intent, highlightColor }: EdgeDefaultDataProps,
@@ -38,7 +38,18 @@ export interface EdgeLabelProps extends React.HTMLAttributes<HTMLDivElement> {
38
38
  }
39
39
 
40
40
  export const EdgeLabel = memo(
41
- ({ depiction, text, actions, large, fullWidth, loose, intent, title, ...otherDivProps }: EdgeLabelProps) => {
41
+ ({
42
+ depiction,
43
+ text,
44
+ actions,
45
+ large,
46
+ fullWidth,
47
+ loose,
48
+ intent,
49
+ title,
50
+ className,
51
+ ...otherDivProps
52
+ }: EdgeLabelProps) => {
42
53
  const depEl =
43
54
  !!depiction && typeof depiction === "string" ? (
44
55
  <Depiction image={<Icon name={depiction as ValidIconName} />} />
@@ -53,7 +64,8 @@ export const EdgeLabel = memo(
53
64
  (large ? ` ${eccgui}-graphviz__edge-label--large` : "") +
54
65
  (fullWidth ? ` ${eccgui}-graphviz__edge-label--fullwidth` : "") +
55
66
  (loose ? ` ${eccgui}-graphviz__edge-label--loose` : "") +
56
- (intent ? ` ${intentClassName(intent)}` : "")
67
+ (intent ? ` ${intentClassName(intent)}` : "") +
68
+ (className ? ` ${className}` : "")
57
69
  }
58
70
  {...otherDivProps}
59
71
  >
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback, useEffect, useState } from "react";
2
2
  import { ArrowHeadType, Elements, getMarkerEnd, ReactFlowProvider } from "react-flow-renderer";
3
- import { ComponentMeta, ComponentStory } from "@storybook/react";
3
+ import { Meta, StoryFn } from "@storybook/react";
4
4
 
5
5
  import { EdgeLabel, EdgeLabelObject, ReactFlow } from "./../../../../../index";
6
6
  import { EdgeDefault, EdgeDefaultDataProps as EdgeData } from "./../EdgeDefault";
@@ -21,7 +21,7 @@ export default {
21
21
  options: [...Object.keys(edgeTypes)],
22
22
  },
23
23
  },
24
- } as ComponentMeta<typeof EdgeDefault>;
24
+ } as Meta<typeof EdgeDefault>;
25
25
 
26
26
  const EdgeDefaultExample = (args: any) => {
27
27
  const [reactflowInstance, setReactflowInstance] = useState(null);
@@ -77,17 +77,23 @@ const EdgeDefaultExample = (args: any) => {
77
77
  );
78
78
  };
79
79
 
80
- const Template: ComponentStory<typeof EdgeDefault> = (args) => <EdgeDefaultExample {...args} />;
80
+ const Template: StoryFn<typeof EdgeDefault> = (args) => <EdgeDefaultExample {...args} />;
81
81
 
82
82
  export const Default = Template.bind({});
83
83
  Default.args = {
84
84
  id: "default",
85
- type: "dangerStep",
85
+ type: "storybook",
86
86
  label: "edge",
87
87
  arrowHeadType: "arrowclosed",
88
88
  source: "node-1",
89
89
  target: "node-2",
90
- data: {},
90
+ data: {
91
+ edgeSvgProps: {
92
+ "data-testid": "storybook-testid",
93
+ "data-test-id": "storybook-test-id",
94
+ className: "storybook__test__classname",
95
+ },
96
+ },
91
97
  };
92
98
 
93
99
  export const CustomLabel = Template.bind({});
@@ -45,6 +45,8 @@ const labelText = loremIpsum({ p: 1, avgSentencesPerParagraph: 1, avgWordsPerSen
45
45
  export const Default = Template.bind({});
46
46
  Default.args = {
47
47
  text: labelText,
48
+ "data-testid": "storybook-testid",
49
+ "data-test-id": "storybook-test-id",
48
50
  };
49
51
 
50
52
  export const ReverseEllipsisLabel = Template.bind({});
@@ -3,8 +3,7 @@ import React, { memo } from "react";
3
3
  import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
4
4
  import { Tooltip, TooltipProps } from "../../../index";
5
5
 
6
- export interface HandleContentProps {
7
- children?: JSX.Element | string;
6
+ export interface HandleContentProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "className"> {
8
7
  /**
9
8
  * Tooltip displayed as overlay on hover.
10
9
  */
@@ -15,28 +14,32 @@ export interface HandleContentProps {
15
14
  tooltipProps?: Omit<TooltipProps, "content" | "children" | "renderTarget">;
16
15
  }
17
16
 
18
- export const HandleContent = memo(({ children, extendedTooltip, tooltipProps }: HandleContentProps) => {
19
- const handleContent = children ? (
20
- <div className={`${eccgui}-graphviz__handle__content`}>{children}</div>
21
- ) : extendedTooltip ? (
22
- <div className={`${eccgui}-graphviz__handle__content`} />
23
- ) : (
24
- <></>
25
- );
26
-
27
- if (extendedTooltip && tooltipProps?.isOpen) {
28
- return (
29
- <Tooltip
30
- content={extendedTooltip}
31
- autoFocus={false}
32
- enforceFocus={false}
33
- openOnTargetFocus={false}
34
- {...tooltipProps}
35
- >
36
- {handleContent}
37
- </Tooltip>
17
+ export const HandleContent = memo(
18
+ ({ children, extendedTooltip, tooltipProps, ...otherDivProps }: HandleContentProps) => {
19
+ const handleContent = children ? (
20
+ <div className={`${eccgui}-graphviz__handle__content`} {...otherDivProps}>
21
+ {children}
22
+ </div>
23
+ ) : extendedTooltip ? (
24
+ <div className={`${eccgui}-graphviz__handle__content`} {...otherDivProps} />
25
+ ) : (
26
+ <></>
38
27
  );
39
- }
40
28
 
41
- return handleContent;
42
- });
29
+ if (extendedTooltip && tooltipProps?.isOpen) {
30
+ return (
31
+ <Tooltip
32
+ content={extendedTooltip}
33
+ autoFocus={false}
34
+ enforceFocus={false}
35
+ openOnTargetFocus={false}
36
+ {...tooltipProps}
37
+ >
38
+ {handleContent}
39
+ </Tooltip>
40
+ );
41
+ }
42
+
43
+ return handleContent;
44
+ }
45
+ );
@@ -40,6 +40,7 @@ export const HandleTools = ({ children, ...otherContextOverlayProps }: HandleToo
40
40
  <div
41
41
  className={`${eccgui}-graphviz__handletools-target`}
42
42
  data-test-id={otherContextOverlayProps["data-test-id"]}
43
+ data-testid={otherContextOverlayProps["data-testid"]}
43
44
  />
44
45
  </ContextOverlay>
45
46
  );
@@ -18,7 +18,7 @@ import { edgeTypes } from "./../../edges/edgeTypes";
18
18
 
19
19
  const HandleDefaultDataProps = (data: HandleProps["data"]) => {
20
20
  // this is only a mock to get it as sub element in the table
21
- return <>{data.extendedTooltip}</>;
21
+ return <>{data?.extendedTooltip}</>;
22
22
  };
23
23
 
24
24
  export default {
@@ -101,6 +101,8 @@ Default.args = {
101
101
  tooltip: "this is a target handle",
102
102
  isConnectable: true,
103
103
  onClick: () => alert("Clicked handle."),
104
+ "data-test-id": "handle-test-id",
105
+ "data-testid": "handle-testid",
104
106
  };
105
107
 
106
108
  export const UsingHandleTools = Template.bind({});
@@ -111,5 +113,7 @@ UsingHandleTools.args = {
111
113
  children: <HandleTestMenu />,
112
114
  data: {
113
115
  extendedTooltip: "This is another Tooltip",
116
+ "data-test-id": "handlecontent-test-id",
117
+ "data-testid": "handlecontent-testid",
114
118
  },
115
119
  };
@@ -0,0 +1,62 @@
1
+ import React, { FC, useCallback, useEffect, useState } from "react";
2
+ import { Background, BackgroundVariant, Elements, FlowElement } from "react-flow-renderer";
3
+ import { OverlaysProvider } from "@blueprintjs/core";
4
+ import { Meta, StoryFn } from "@storybook/react";
5
+
6
+ import { Default as ReactFlowExample } from "../../../cmem/react-flow/ReactFlow/ReactFlow.stories";
7
+
8
+ import { MiniMap as MiniMapElement, MiniMapProps, ReactFlow, ReactFlowProps } from "./../../../../index";
9
+
10
+ export default {
11
+ title: "Extensions/React Flow/MiniMap",
12
+ component: MiniMapElement,
13
+ argTypes: {},
14
+ } as Meta<typeof MiniMapElement>;
15
+
16
+ const MiniMapExample: FC<MiniMapProps> = (args) => {
17
+ const [reactflowInstance, setReactflowInstance] = useState(undefined);
18
+ const [elements, setElements] = useState([] as Elements);
19
+ const [edgeTools, setEdgeTools] = useState<JSX.Element>(<></>);
20
+ const nodeExamples = ReactFlowExample.nodeExamples.workflow;
21
+
22
+ useEffect(() => {
23
+ setElements(nodeExamples as Elements);
24
+ }, [args]);
25
+
26
+ // Helper methods for nodes and edges
27
+ const isNode = (element: FlowElement & { source?: string }): boolean => !element.source;
28
+ const isEdge = (element: FlowElement & { source?: string }): boolean => !isNode(element);
29
+
30
+ const onLoad = useCallback((rfi) => {
31
+ if (!reactflowInstance) {
32
+ setReactflowInstance(rfi);
33
+ }
34
+ }, []);
35
+
36
+ return (
37
+ <OverlaysProvider>
38
+ <ReactFlow
39
+ configuration={"workflow"}
40
+ elements={elements}
41
+ style={{ height: "400px" }}
42
+ onLoad={onLoad}
43
+ defaultZoom={1}
44
+ >
45
+ <MiniMapElement flowInstance={reactflowInstance} {...args} />
46
+ <Background variant={BackgroundVariant.Lines} gap={16} />
47
+ </ReactFlow>
48
+ {edgeTools}
49
+ </OverlaysProvider>
50
+ );
51
+ };
52
+
53
+ const Template: StoryFn<typeof MiniMapExample> = (args) => <MiniMapExample {...args} />;
54
+
55
+ export const Default = Template.bind({});
56
+ Default.args = {
57
+ enableNavigation: true,
58
+ wrapperProps: {
59
+ "data-test-id": "minimap-test-id",
60
+ "data-testid": "minimap-testid",
61
+ },
62
+ };
@@ -5,8 +5,22 @@ import { FlowTransform } from "react-flow-renderer/dist/types";
5
5
  import { miniMapUtils } from "../minimap/utils";
6
6
 
7
7
  export interface MiniMapProps extends ReactFlowMiniMapProps {
8
+ /**
9
+ * React-Flow instance
10
+ */
8
11
  flowInstance?: OnLoadParams;
12
+ /**
13
+ * Enable navigating the react-flow canvas by dragging and clicking on the mini-map.
14
+ */
9
15
  enableNavigation?: boolean;
16
+ /**
17
+ * Properties are forwarded to the HTML `div` element used as minimap wrapper.
18
+ * Data attributes for test ids coud be included here.
19
+ */
20
+ wrapperProps?: Omit<
21
+ React.HTMLAttributes<HTMLDivElement>,
22
+ "onMouseDown" | "onMouseUp" | "onMouseMove" | "onMouseLeave"
23
+ >;
10
24
  }
11
25
 
12
26
  interface configParams {
@@ -33,6 +47,7 @@ export const MiniMap = memo(
33
47
  nodeClassName = miniMapUtils.nodeClassName,
34
48
  nodeColor = miniMapUtils.nodeColor,
35
49
  nodeStrokeColor = miniMapUtils.borderColor,
50
+ wrapperProps,
36
51
  ...minimapProps
37
52
  }: MiniMapProps) => {
38
53
  const minimapWrapper = React.useRef<HTMLDivElement | null>(null);
@@ -88,17 +103,13 @@ export const MiniMap = memo(
88
103
  }
89
104
  };
90
105
 
91
- /**
92
- sets the view for the user when clicked and finish navigation
93
- **/
106
+ // sets the view for the user when clicked and finish navigation
94
107
  const handleMiniMapMouseUp = (event: any) => {
95
108
  handleMiniMapMouseMove(event);
96
109
  minimapCalcConf.navigationOn = false;
97
110
  };
98
111
 
99
- /**
100
- enables the mini-map fake drag effect see "handleMiniMapMouseMove" above.
101
- **/
112
+ // enables the mini-map fake drag effect see "handleMiniMapMouseMove" above.
102
113
  const handleMiniMapMouseDown = () => {
103
114
  if (enableNavigation && flowInstance) {
104
115
  minimapCalcConf.navigationOn = true;
@@ -112,7 +123,12 @@ export const MiniMap = memo(
112
123
  onMouseUp={handleMiniMapMouseUp}
113
124
  onMouseMove={handleMiniMapMouseMove}
114
125
  onMouseLeave={handleMiniMapMouseUp}
115
- style={flowInstance ? { cursor: "grab" } : {}}
126
+ {...wrapperProps}
127
+ style={
128
+ flowInstance && enableNavigation
129
+ ? { ...(wrapperProps?.style ?? {}), cursor: "grab" }
130
+ : wrapperProps?.style
131
+ }
116
132
  >
117
133
  <ReactFlowMiniMap
118
134
  maskColor={maskColor}
@@ -199,6 +199,8 @@ Default.args = {
199
199
  },
200
200
  ],
201
201
  onNodeResize: false, // workaround that storybook do not automatically include empty handle function
202
+ "data-test-id": "nodecontent-test-id",
203
+ "data-testid": "nodecontent-testid",
202
204
  };
203
205
 
204
206
  export const Resizeable = Template.bind({});
@@ -41,6 +41,8 @@ Default.args = {
41
41
  <LoremIpsum p={2} avgSentencesPerParagraph={4} random={false} />
42
42
  </HtmlContentBlock>
43
43
  ),
44
+ "data-test-id": "contentextension-test-id",
45
+ "data-testid": "contentextension-testid",
44
46
  } as NodeContentExtensionProps;
45
47
 
46
48
  export const SlideOutOfNode = Template.bind({});
@@ -11,7 +11,6 @@ import { nodeTypes } from "./nodeTypes";
11
11
  export default {
12
12
  title: "Extensions/React Flow/Node",
13
13
  component: NodeDefault,
14
- subcomponents: { NodeContent },
15
14
  argTypes: {
16
15
  id: {
17
16
  control: "text",