@eccenca/gui-elements 23.3.0-rc.0 → 23.3.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.
Files changed (79) hide show
  1. package/CHANGELOG.md +39 -19
  2. package/dist/cjs/common/index.js +5 -2
  3. package/dist/cjs/common/index.js.map +1 -1
  4. package/dist/cjs/common/utils/globalVars.js +21 -0
  5. package/dist/cjs/common/utils/globalVars.js.map +1 -0
  6. package/dist/cjs/components/ContextOverlay/ContextOverlay.js +3 -2
  7. package/dist/cjs/components/ContextOverlay/ContextOverlay.js.map +1 -1
  8. package/dist/cjs/components/Dialog/Modal.js +20 -2
  9. package/dist/cjs/components/Dialog/Modal.js.map +1 -1
  10. package/dist/cjs/components/Icon/canonicalIconNames.js +4 -0
  11. package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
  12. package/dist/cjs/components/Table/TableExpandHeader.js +7 -8
  13. package/dist/cjs/components/Table/TableExpandHeader.js.map +1 -1
  14. package/dist/cjs/extensions/react-flow/edges/EdgeLabel.js +10 -9
  15. package/dist/cjs/extensions/react-flow/edges/EdgeLabel.js.map +1 -1
  16. package/dist/cjs/extensions/react-flow/handles/HandleContent.js +4 -4
  17. package/dist/cjs/extensions/react-flow/handles/HandleContent.js.map +1 -1
  18. package/dist/cjs/extensions/react-flow/handles/HandleDefault.js +62 -24
  19. package/dist/cjs/extensions/react-flow/handles/HandleDefault.js.map +1 -1
  20. package/dist/cjs/extensions/react-flow/handles/HandleTools.js +16 -2
  21. package/dist/cjs/extensions/react-flow/handles/HandleTools.js.map +1 -1
  22. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +17 -8
  23. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  24. package/dist/esm/common/index.js +5 -2
  25. package/dist/esm/common/index.js.map +1 -1
  26. package/dist/esm/common/utils/globalVars.js +16 -0
  27. package/dist/esm/common/utils/globalVars.js.map +1 -0
  28. package/dist/esm/components/ContextOverlay/ContextOverlay.js +5 -4
  29. package/dist/esm/components/ContextOverlay/ContextOverlay.js.map +1 -1
  30. package/dist/esm/components/Dialog/Modal.js +20 -2
  31. package/dist/esm/components/Dialog/Modal.js.map +1 -1
  32. package/dist/esm/components/Icon/canonicalIconNames.js +4 -0
  33. package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
  34. package/dist/esm/components/Table/TableExpandHeader.js +7 -8
  35. package/dist/esm/components/Table/TableExpandHeader.js.map +1 -1
  36. package/dist/esm/extensions/react-flow/edges/EdgeLabel.js +10 -9
  37. package/dist/esm/extensions/react-flow/edges/EdgeLabel.js.map +1 -1
  38. package/dist/esm/extensions/react-flow/handles/HandleContent.js +16 -5
  39. package/dist/esm/extensions/react-flow/handles/HandleContent.js.map +1 -1
  40. package/dist/esm/extensions/react-flow/handles/HandleDefault.js +62 -24
  41. package/dist/esm/extensions/react-flow/handles/HandleDefault.js.map +1 -1
  42. package/dist/esm/extensions/react-flow/handles/HandleTools.js +32 -2
  43. package/dist/esm/extensions/react-flow/handles/HandleTools.js.map +1 -1
  44. package/dist/esm/extensions/react-flow/nodes/NodeContent.js +17 -8
  45. package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  46. package/dist/types/common/index.d.ts +4 -0
  47. package/dist/types/common/utils/globalVars.d.ts +2 -0
  48. package/dist/types/components/ContextOverlay/ContextOverlay.d.ts +7 -2
  49. package/dist/types/components/Dialog/Modal.d.ts +11 -3
  50. package/dist/types/components/Icon/canonicalIconNames.d.ts +1 -1
  51. package/dist/types/components/Table/TableExpandHeader.d.ts +5 -1
  52. package/dist/types/extensions/react-flow/edges/EdgeLabel.d.ts +7 -3
  53. package/dist/types/extensions/react-flow/handles/HandleContent.d.ts +7 -2
  54. package/dist/types/extensions/react-flow/handles/HandleDefault.d.ts +13 -4
  55. package/dist/types/extensions/react-flow/handles/HandleTools.d.ts +2 -1
  56. package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +3 -7
  57. package/package.json +8 -7
  58. package/src/common/index.ts +6 -3
  59. package/src/common/utils/globalVars.ts +18 -0
  60. package/src/components/Application/application.scss +7 -9
  61. package/src/components/ContextOverlay/ContextOverlay.tsx +20 -12
  62. package/src/components/ContextOverlay/contextoverlay.scss +8 -0
  63. package/src/components/Dialog/Modal.tsx +35 -3
  64. package/src/components/Dialog/dialog.scss +4 -0
  65. package/src/components/Icon/canonicalIconNames.tsx +9 -0
  66. package/src/components/PropertyValuePair/propertyvalue.scss +1 -0
  67. package/src/components/Table/TableExpandHeader.tsx +21 -18
  68. package/src/configuration/_variables.scss +27 -36
  69. package/src/extensions/react-flow/edges/EdgeLabel.tsx +78 -81
  70. package/src/extensions/react-flow/edges/_edges.scss +62 -67
  71. package/src/extensions/react-flow/handles/HandleContent.tsx +14 -13
  72. package/src/extensions/react-flow/handles/HandleDefault.tsx +127 -44
  73. package/src/extensions/react-flow/handles/HandleTools.tsx +28 -4
  74. package/src/extensions/react-flow/handles/_handles.scss +86 -21
  75. package/src/extensions/react-flow/handles/stories/HandleDefault.stories.tsx +41 -3
  76. package/src/extensions/react-flow/nodes/NodeContent.tsx +35 -30
  77. package/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +75 -52
  78. package/src/extensions/react-flow/nodes/stories/NodeDefault.stories.tsx +4 -4
  79. package/src/extensions/react-flow/nodes/stories/nodeTypes.ts +11 -0
@@ -3,23 +3,31 @@
3
3
  --#{$eccgui}-reactflow-node-color-hover: #{$reactflow-edge-stroke-color-hover};
4
4
  --#{$eccgui}-reactflow-node-color-selected: #{$reactflow-edge-stroke-color-selected};
5
5
 
6
- stroke: var(--#{$eccgui}-reactflow-node-color-default);
7
6
  color: var(--#{$eccgui}-reactflow-node-color-default);
8
7
 
9
- path[class*="react-flow__edge"], rect[class*="react-flow__edge"] {
10
- shape-rendering: optimizeSpeed;
8
+ // stroke: var(--#{$eccgui}-reactflow-node-color-default); // removed, probably not necessary
9
+
10
+ path[class*="react-flow__edge"],
11
+ rect[class*="react-flow__edge"] {
11
12
  stroke-opacity: $reactflow-edge-stroke-opacity-default;
13
+ shape-rendering: optimizespeed;
12
14
  }
13
15
 
14
16
  text[class*="react-flow__edge"] {
15
17
  opacity: $reactflow-edge-stroke-opacity-default;
16
18
  }
17
19
 
20
+ .react-flow__edge-textbg {
21
+ stroke: currentcolor;
22
+ }
23
+
18
24
  &:hover {
19
- stroke: var(--#{$eccgui}-reactflow-node-color-hover);
20
25
  color: var(--#{$eccgui}-reactflow-node-color-hover);
21
26
 
22
- path[class*="react-flow__edge"], rect[class*="react-flow__edge"] {
27
+ // stroke: var(--#{$eccgui}-reactflow-node-color-hover); // removed, probably not necessary
28
+
29
+ path[class*="react-flow__edge"],
30
+ rect[class*="react-flow__edge"] {
23
31
  stroke-opacity: $reactflow-edge-stroke-opacity-hover;
24
32
  }
25
33
 
@@ -29,10 +37,11 @@
29
37
  }
30
38
 
31
39
  &.selected {
32
- stroke: var(--#{$eccgui}-reactflow-node-color-selected);
33
40
  color: var(--#{$eccgui}-reactflow-node-color-selected);
41
+ stroke: var(--#{$eccgui}-reactflow-node-color-selected);
34
42
 
35
- path[class*="react-flow__edge"], rect[class*="react-flow__edge"] {
43
+ path[class*="react-flow__edge"],
44
+ rect[class*="react-flow__edge"] {
36
45
  stroke-opacity: $reactflow-edge-stroke-opacity-selected;
37
46
  }
38
47
 
@@ -43,19 +52,19 @@
43
52
  }
44
53
 
45
54
  path.react-flow__edge-path {
46
- stroke-width: 2;
47
- stroke: currentColor;
55
+ stroke: currentcolor;
48
56
  stroke-opacity: $reactflow-edge-stroke-opacity-default;
57
+ stroke-width: 2;
49
58
 
50
59
  .react-flow__edge.selected & {
60
+ stroke: currentcolor;
51
61
  stroke-width: 2;
52
- stroke: currentColor;
53
62
  }
54
63
  }
55
64
 
56
65
  path.react-flow__edge-path-glow {
57
- stroke: currentColor;
58
66
  fill: none;
67
+ stroke: currentcolor;
59
68
  stroke-linecap: round;
60
69
 
61
70
  .react-flow__edge & {
@@ -77,9 +86,9 @@ path.react-flow__edge-path-glow {
77
86
  }
78
87
 
79
88
  .react-flow__edgeupdater {
80
- stroke: currentColor;
81
- fill: currentColor;
82
89
  opacity: 0;
90
+ fill: currentcolor;
91
+ stroke: currentcolor;
83
92
 
84
93
  &:hover {
85
94
  opacity: 0.05;
@@ -87,13 +96,10 @@ path.react-flow__edge-path-glow {
87
96
  }
88
97
 
89
98
  .react-flow__edge-text {
90
- fill: currentColor;
99
+ fill: currentcolor;
91
100
  stroke: none;
92
101
  }
93
102
 
94
- .react-flow__edge-textbg {
95
- }
96
-
97
103
  // Stroke types
98
104
 
99
105
  path.react-flow__edge-path--stroke-solid {
@@ -111,16 +117,16 @@ path.react-flow__edge-path--stroke-dotted,
111
117
  }
112
118
 
113
119
  path.react-flow__edge-path--stroke-double {
120
+ filter: drop-shadow(1px 1px 1px currentcolor) drop-shadow(-1px -1px 1px currentcolor);
114
121
  stroke: #fff !important;
115
122
  stroke-opacity: 1 !important;
116
- filter: drop-shadow(1px 1px 1px currentColor) drop-shadow(-1px -1px 1px currentColor);
117
123
  }
118
124
 
119
125
  path.react-flow__edge-path--stroke-doubledashed {
126
+ filter: drop-shadow(1px 1px 1px currentcolor) drop-shadow(-1px -1px 1px currentcolor);
120
127
  stroke: #fff !important;
121
- stroke-opacity: 1 !important;
122
- filter: drop-shadow(1px 1px 1px currentColor) drop-shadow(-1px -1px 1px currentColor);
123
128
  stroke-dasharray: 5;
129
+ stroke-opacity: 1 !important;
124
130
  }
125
131
 
126
132
  // Intent states
@@ -165,13 +171,12 @@ g.#{$eccgui}-intent--danger {
165
171
  // Highlightning
166
172
 
167
173
  path.react-flow__edge-path-highlight {
168
- stroke-opacity: 1;
174
+ filter: drop-shadow(2px -2px 1px var(--edge-highlight-default-color))
175
+ drop-shadow(-2px 2px 1px var(--edge-highlight-alternate-color, var(--edge-highlight-default-color)));
169
176
  fill: none;
170
- stroke-linecap: round;
171
177
  stroke: #fff;
172
- filter:
173
- drop-shadow(2px -2px 1px var(--edge-highlight-default-color))
174
- drop-shadow(-2px 2px 1px var(--edge-highlight-alternate-color, var(--edge-highlight-default-color)));
178
+ stroke-linecap: round;
179
+ stroke-opacity: 1;
175
180
  }
176
181
 
177
182
  .#{$eccgui}-graphviz__edge--highlight-default {
@@ -189,16 +194,8 @@ path.react-flow__edge-path-highlight {
189
194
  --edge-highlight-alternate-color: #{$eccgui-color-primary};
190
195
  }
191
196
 
192
-
193
-
194
197
  // Type colors
195
198
 
196
- .react-flow__edge-default,
197
- .react-flow__edge-straight,
198
- .react-flow__edge-smoothstep,
199
- .react-flow__edge-step {
200
- }
201
-
202
199
  .react-flow__edge-success {
203
200
  --#{$eccgui}-reactflow-node-color-default: #{$eccgui-color-success-text};
204
201
  --#{$eccgui}-reactflow-node-color-hover: #{$eccgui-color-success-text};
@@ -221,34 +218,29 @@ path.react-flow__edge-path-highlight {
221
218
 
222
219
  .#{$eccgui}-graphviz__edgetools-target {
223
220
  position: fixed;
221
+ z-index: 1000;
224
222
  width: $eccgui-size-block-whitespace * 2;
225
223
  height: $eccgui-size-block-whitespace * 2;
226
- //margin-left: -1 * $eccgui-size-block-whitespace;
227
224
  margin-top: -1 * $eccgui-size-block-whitespace;
228
- z-index: 1000;
229
- }
230
-
231
- .#{$eccgui}-graphviz__edgetools-overlay {
232
- //transform: translate(#{$eccgui-size-block-whitespace}, #{-1 * $eccgui-size-block-whitespace});
233
225
  }
234
226
 
235
227
  .#{$eccgui}-graphviz__edgetools-content {
236
- padding: $eccgui-size-block-whitespace * 0.5;
237
- max-width: $reactflow-node-basesize * 8;
238
228
  min-width: $reactflow-node-basesize;
239
- max-height: $reactflow-node-basesize * 13;
229
+ max-width: $reactflow-node-basesize * 8;
240
230
  min-height: $reactflow-node-basesize;
231
+ max-height: $reactflow-node-basesize * 13;
232
+ padding: $eccgui-size-block-whitespace * 0.5;
241
233
  }
242
234
 
243
235
  // Arrows
244
236
 
245
237
  .react-flow__arrowhead {
246
238
  polyline {
247
- stroke-width: 1px;
239
+ fill: currentcolor;
240
+ stroke: currentcolor;
248
241
  stroke-linecap: square;
249
242
  stroke-linejoin: miter;
250
- stroke: currentColor;
251
- fill: currentColor;
243
+ stroke-width: 1px;
252
244
  transform: scale(1.75, 0.75);
253
245
  }
254
246
  }
@@ -256,54 +248,57 @@ path.react-flow__edge-path-highlight {
256
248
  // Custom label
257
249
 
258
250
  .#{$eccgui}-graphviz__edge-label {
259
- border: 0.5*$reactflow-node-border-width solid currentColor;
260
- border-radius: $reactflow-node-border-radius;
261
- background: #fff; // TODO color
262
- color: currentColor;
251
+ --#{$eccgui}-reactflow-edge-label-color: currentcolor;
252
+ --#{$eccgui}-reactflow-edge-label-color-background: #{$card-background-color};
253
+
263
254
  display: inline-flex;
264
255
  align-items: center;
265
256
  width: auto;
266
257
  max-width: 20rem;
267
258
  height: 0.5 * $reactflow-node-largesize;
268
259
  font-size: $reactflow-node-font-size;
260
+ color: var(--#{$eccgui}-reactflow-edge-label-color, currentColor);
261
+ background-color: var(--#{$eccgui}-reactflow-edge-label-color-background, #{$card-background-color});
262
+ border: 0.5 * $reactflow-node-border-width solid transparent;
263
+ border-color: var(--#{$eccgui}-reactflow-edge-label-color, currentColor);
264
+ border-radius: $reactflow-node-border-radius;
265
+
266
+ &.#{$eccgui}-graphviz__edge-label--loose {
267
+ background-color: transparent;
268
+ border: none;
269
+ }
269
270
 
270
271
  &.#{$eccgui}-intent--primary {
271
- color: $eccgui-color-primary;
272
- border-color: $eccgui-color-primary;
272
+ --#{$eccgui}-reactflow-edge-label-color: #{$eccgui-color-primary};
273
273
  }
274
274
  &.#{$eccgui}-intent--accent {
275
- color: $eccgui-color-accent;
276
- border-color: $eccgui-color-accent;
275
+ --#{$eccgui}-reactflow-edge-label-color: #{$eccgui-color-accent};
277
276
  }
278
277
  &.#{$eccgui}-intent--success {
279
- color: $eccgui-color-success-text;
280
- border-color: $eccgui-color-success-text;
278
+ --#{$eccgui}-reactflow-edge-label-color: #{$eccgui-color-success-text};
281
279
  }
282
280
  &.#{$eccgui}-intent--info {
283
- color: $eccgui-color-info-text;
284
- border-color: $eccgui-color-info-text;
281
+ --#{$eccgui}-reactflow-edge-label-color: #{$eccgui-color-info-text};
285
282
  }
286
283
  &.#{$eccgui}-intent--warning {
287
- color: $eccgui-color-warning-text;
288
- border-color: $eccgui-color-warning-text;
284
+ --#{$eccgui}-reactflow-edge-label-color: #{$eccgui-color-warning-text};
289
285
  }
290
286
  &.#{$eccgui}-intent--danger {
291
- color: $eccgui-color-danger-text;
292
- border-color: $eccgui-color-danger-text;
287
+ --#{$eccgui}-reactflow-edge-label-color: #{$eccgui-color-danger-text};
293
288
  }
294
289
  }
295
290
  .#{$eccgui}-graphviz__edge-label--large {
296
291
  height: $reactflow-node-largesize;
297
292
  }
298
293
  .#{$eccgui}-graphviz__edge-label--fullwidth {
299
- max-width: none;
300
294
  width: 100%;
295
+ max-width: none;
301
296
  }
302
297
  .#{$eccgui}-graphviz__edge-label__depiction {
303
- margin-left: 2px;
304
298
  display: inline-flex;
305
299
  flex-grow: 0;
306
300
  flex-shrink: 0;
301
+ margin-left: 2px;
307
302
  .#{$eccgui}-depiction__image {
308
303
  height: calc(#{0.5 * $reactflow-node-largesize} - 4px);
309
304
 
@@ -313,20 +308,20 @@ path.react-flow__edge-path-highlight {
313
308
  }
314
309
  }
315
310
  .#{$eccgui}-graphviz__edge-label__text {
316
- margin: 0 $eccgui-size-block-whitespace * 0.25;
317
311
  flex-grow: 1;
318
312
  flex-shrink: 1;
319
- white-space: nowrap;
313
+ margin: 0 $eccgui-size-block-whitespace * 0.25;
320
314
  overflow: hidden;
321
- text-overflow: ellipsis;
322
315
  text-align: center;
316
+ text-overflow: ellipsis;
317
+ white-space: nowrap;
323
318
 
324
319
  .#{$eccgui}-graphviz__edge-label--fullwidth & {
325
320
  text-align: left;
326
321
  }
327
322
  }
328
323
  .#{$eccgui}-graphviz__edge-label__aux {
329
- margin-right: $eccgui-size-block-whitespace * 0.25;
330
324
  flex-grow: 0;
331
325
  flex-shrink: 0;
326
+ margin-right: $eccgui-size-block-whitespace * 0.25;
332
327
  }
@@ -1,6 +1,7 @@
1
- import React, {memo} from 'react';
1
+ import React, { memo } from "react";
2
+
2
3
  import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
3
- import { Tooltip } from "../../../index";
4
+ import { Tooltip, TooltipProps } from "../../../index";
4
5
 
5
6
  export interface HandleContentProps {
6
7
  children?: JSX.Element | string;
@@ -8,31 +9,31 @@ export interface HandleContentProps {
8
9
  * Tooltip displayed as overlay on hover.
9
10
  */
10
11
  extendedTooltip?: JSX.Element | string;
12
+ /**
13
+ * Configure the tooltip and overwrite automatically set options.
14
+ */
15
+ tooltipProps?: Omit<TooltipProps, "content" | "children" | "renderTarget">;
11
16
  }
12
17
 
13
- export const HandleContent = memo(({
14
- children,
15
- extendedTooltip
16
- }: HandleContentProps) => {
17
- const handleContent = !!children ? (
18
- <div className={`${eccgui}-graphviz__handle__content`}>
19
- { children }
20
- </div>
21
- ) : !!extendedTooltip ? (
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
22
  <div className={`${eccgui}-graphviz__handle__content`} />
23
23
  ) : (
24
24
  <></>
25
25
  );
26
26
 
27
- if (!!extendedTooltip) {
27
+ if (extendedTooltip && tooltipProps?.isOpen) {
28
28
  return (
29
29
  <Tooltip
30
30
  content={extendedTooltip}
31
31
  autoFocus={false}
32
32
  enforceFocus={false}
33
33
  openOnTargetFocus={false}
34
+ {...tooltipProps}
34
35
  >
35
- { handleContent }
36
+ {handleContent}
36
37
  </Tooltip>
37
38
  );
38
39
  }
@@ -1,14 +1,23 @@
1
1
  import React, { memo } from "react";
2
2
  import { Handle as HandleLegacy, HandleProps as ReactFlowHandleLegacyProps } from "react-flow-renderer";
3
3
  import { Handle as HandleNext, HandleProps as ReactFlowHandleNextProps } from "react-flow-renderer-lts";
4
- import { PopoverInteractionKind as BlueprintPopoverInteractionKind } from "@blueprintjs/core";
5
4
 
5
+ import { intentClassName, IntentTypes } from "../../../common/Intent";
6
+ import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
7
+ import { TooltipProps } from "../../../index";
6
8
  import { ReacFlowVersionSupportProps, useReactFlowVersion } from "../versionsupport";
7
9
 
8
10
  import { HandleContent, HandleContentProps } from "./HandleContent";
9
- import { HandleTools } from "./HandleTools";
10
11
 
11
- interface HandleExtensionProps extends ReacFlowVersionSupportProps {
12
+ export type HandleCategory = "configuration" | "flexible" | "fixed" | "unknown" | "dependency";
13
+
14
+ interface HandleExtensionProps
15
+ extends ReacFlowVersionSupportProps,
16
+ Omit<React.HTMLAttributes<HTMLDivElement>, "id" | "children"> {
17
+ /**
18
+ * Defines the handle category, mainly used to adjust layout.
19
+ */
20
+ category?: HandleCategory;
12
21
  /**
13
22
  * Extended handle data.
14
23
  */
@@ -17,8 +26,11 @@ interface HandleExtensionProps extends ReacFlowVersionSupportProps {
17
26
  * Simple text tooltip displayed as title on hover.
18
27
  */
19
28
  tooltip?: string;
20
- children?: JSX.Element | string;
21
- onClick?: () => void;
29
+ /**
30
+ * Feedback state of the handle.
31
+ */
32
+ intent?: IntentTypes;
33
+ children?: HandleContentProps["children"];
22
34
  }
23
35
 
24
36
  export interface HandleProps extends HandleExtensionProps, ReactFlowHandleLegacyProps {}
@@ -26,47 +38,118 @@ export interface HandleNextProps extends HandleExtensionProps, ReactFlowHandleNe
26
38
 
27
39
  export type HandleDefaultProps = HandleProps | HandleNextProps;
28
40
 
29
- export const HandleDefault = memo(({ flowVersion, data, tooltip, children, ...handleProps }: HandleDefaultProps) => {
30
- const evaluateFlowVersion = useReactFlowVersion();
31
- const flowVersionCheck = flowVersion || evaluateFlowVersion;
32
- const [toolsDisplayed, setToolsDisplayed] = React.useState<boolean>(false);
41
+ export const HandleDefault = memo(
42
+ ({ flowVersion, data, tooltip, children, category, intent, ...handleProps }: HandleDefaultProps) => {
43
+ const evaluateFlowVersion = useReactFlowVersion();
44
+ const flowVersionCheck = flowVersion || evaluateFlowVersion;
45
+ const handleDefaultRef = React.useRef<any>();
46
+ const [extendedTooltipDisplayed, setExtendedTooltipDisplayed] = React.useState<boolean>(false);
47
+ const [handleToolsDisplayed, setHandleToolsDisplayed] = React.useState<boolean>(false);
33
48
 
34
- const handleClosing = () => {
35
- setToolsDisplayed(false);
36
- };
49
+ const routeClickToTools = React.useCallback(
50
+ (e: Event) => {
51
+ const toolsTarget = handleDefaultRef.current.getElementsByClassName(
52
+ `${eccgui}-graphviz__handletools-target`
53
+ );
54
+ if (toolsTarget.length > 0 && e.target === handleDefaultRef.current) {
55
+ setHandleToolsDisplayed(true);
56
+ setExtendedTooltipDisplayed(false);
57
+ }
58
+ },
59
+ [handleDefaultRef]
60
+ );
37
61
 
38
- const tooltipTitle = tooltip ? { title: tooltip } : {};
39
- const configToolsOn = {
40
- defaultIsOpen: true,
41
- autoFocus: true,
42
- interactionKind: BlueprintPopoverInteractionKind.HOVER,
43
- onClosing: handleClosing,
44
- };
62
+ React.useEffect(() => {
63
+ const toolsTarget = handleDefaultRef.current.getElementsByClassName(
64
+ `${eccgui}-graphviz__handletools-target`
65
+ );
66
+ if (toolsTarget && toolsTarget[0] && handleToolsDisplayed) {
67
+ toolsTarget[0].click();
68
+ }
69
+ }, [handleToolsDisplayed]);
45
70
 
46
- const isToolsContent = children && typeof children !== "string" && children.type === HandleTools;
47
- let handleContent = <HandleContent {...data}>{children}</HandleContent>;
71
+ React.useEffect(() => {
72
+ const toolsTarget = handleDefaultRef.current.getElementsByClassName(
73
+ `${eccgui}-graphviz__handletools-target`
74
+ );
75
+ if (toolsTarget && toolsTarget[0]) {
76
+ // Polyfill for FF that does not support the `:has()` pseudo selector until at least version 119 or 120
77
+ // need to be re-evaluated then
78
+ // @see https://connect.mozilla.org/t5/ideas/when-is-has-css-selector-going-to-be-fully-implemented-in/idi-p/23794
79
+ handleDefaultRef.current.classList.add(`ffpolyfill-has-${eccgui}-graphviz__handletools-target`);
80
+ }
81
+ });
48
82
 
49
- if (isToolsContent && toolsDisplayed) {
50
- handleContent = <HandleContent {...data}>{React.cloneElement(children ?? <></>, configToolsOn)}</HandleContent>;
51
- }
52
- if (isToolsContent && !toolsDisplayed) {
53
- handleContent = <HandleContent {...data}></HandleContent>;
54
- }
55
- const handleClick = React.useCallback(() => setToolsDisplayed(!toolsDisplayed), []);
56
-
57
- const handleConfig = {
58
- ...handleProps,
59
- ...tooltipTitle,
60
- className: isToolsContent ? "clickable" : undefined,
61
- onClick: isToolsContent ? handleClick : undefined,
62
- };
63
-
64
- switch (flowVersionCheck) {
65
- case "legacy":
66
- return <HandleLegacy {...handleConfig}>{handleContent}</HandleLegacy>;
67
- case "next":
68
- return <HandleNext {...handleConfig}>{handleContent}</HandleNext>;
69
- default:
70
- return <></>;
83
+ const tooltipTitle = tooltip ? { title: tooltip } : {};
84
+
85
+ const handleContentTooltipProps = {
86
+ placement:
87
+ handleProps.position === "left" || handleProps.position === "right"
88
+ ? `${handleProps.position}-end`
89
+ : undefined,
90
+ modifiers: {
91
+ offset: {
92
+ enabled: true,
93
+ options: {
94
+ offset: [3, 20],
95
+ },
96
+ },
97
+ },
98
+ intent: intent,
99
+ className: `${eccgui}-graphviz__handle__tooltip-target`,
100
+ isOpen: extendedTooltipDisplayed && !handleToolsDisplayed,
101
+ };
102
+
103
+ const handleContentProps = {
104
+ ...data,
105
+ tooltipProps: {
106
+ ...handleContentTooltipProps,
107
+ ...data?.tooltipProps,
108
+ } as TooltipProps,
109
+ };
110
+
111
+ const handleContent = <HandleContent {...handleContentProps}>{children}</HandleContent>;
112
+
113
+ let switchTooltipTimerOn: ReturnType<typeof setTimeout>;
114
+ const handleConfig = {
115
+ ...handleProps,
116
+ ...tooltipTitle,
117
+ className: intent ? `${intentClassName(intent)} ` : "",
118
+ onClick: (e: any) => {
119
+ if (handleProps.onClick) {
120
+ handleProps.onClick(e);
121
+ }
122
+ routeClickToTools(e);
123
+ },
124
+ "data-category": category,
125
+ onMouseEnter: () => {
126
+ switchTooltipTimerOn = setTimeout(
127
+ () => setExtendedTooltipDisplayed(true),
128
+ data?.tooltipProps?.hoverOpenDelay ?? 500
129
+ );
130
+ setHandleToolsDisplayed(false);
131
+ },
132
+ onMouseLeave: () => {
133
+ if (switchTooltipTimerOn) clearTimeout(switchTooltipTimerOn);
134
+ setExtendedTooltipDisplayed(false);
135
+ },
136
+ };
137
+
138
+ switch (flowVersionCheck) {
139
+ case "legacy":
140
+ return (
141
+ <HandleLegacy ref={handleDefaultRef} {...handleConfig}>
142
+ {handleContent}
143
+ </HandleLegacy>
144
+ );
145
+ case "next":
146
+ return (
147
+ <HandleNext ref={handleDefaultRef} {...handleConfig}>
148
+ {handleContent}
149
+ </HandleNext>
150
+ );
151
+ default:
152
+ return <></>;
153
+ }
71
154
  }
72
- });
155
+ );
@@ -1,22 +1,46 @@
1
1
  import React from "react";
2
+ import { PopoverInteractionKind as BlueprintPopoverInteractionKind } from "@blueprintjs/core";
2
3
 
3
4
  import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
4
- import { ContextOverlay } from "../../../index";
5
+ import { ContextOverlay, TestableComponent } from "../../../index";
5
6
 
6
- import { ContextOverlayProps } from "./../../../components/ContextOverlay/ContextOverlay";
7
+ import {ContextOverlayProps} from "./../../../components/ContextOverlay/ContextOverlay";
7
8
 
8
- export interface HandleToolsProps extends Omit<ContextOverlayProps, "children" | "content" | "popoverClassName"> {
9
+ export interface HandleToolsProps
10
+ extends Omit<ContextOverlayProps, "children" | "content" | "popoverClassName">,
11
+ TestableComponent {
9
12
  children: string | JSX.Element | JSX.Element[];
10
13
  }
11
14
 
12
15
  export const HandleTools = ({ children, ...otherContextOverlayProps }: HandleToolsProps) => {
16
+ const [toolsDisplayed, setToolsDisplayed] = React.useState<boolean>(false);
17
+
18
+ const configToolsDisplayed = toolsDisplayed
19
+ ? {
20
+ defaultIsOpen: true,
21
+ autoFocus: true,
22
+ interactionKind: BlueprintPopoverInteractionKind.HOVER,
23
+ onClosing: () => setToolsDisplayed(false),
24
+ }
25
+ : {
26
+ onOpening: () => {
27
+ setToolsDisplayed(true);
28
+ },
29
+ };
30
+
13
31
  return (
14
32
  <ContextOverlay
33
+ hoverCloseDelay={500}
34
+ {...configToolsDisplayed}
15
35
  {...otherContextOverlayProps}
16
36
  content={<div className={`${eccgui}-graphviz__handletools-content`}>{children}</div>}
37
+ className={`${eccgui}-graphviz__handletools-target`}
17
38
  popoverClassName={`${eccgui}-graphviz__handletools-overlay`}
18
39
  >
19
- <div className={`${eccgui}-graphviz__handletools-target`} />
40
+ <div
41
+ className={`${eccgui}-graphviz__handletools-target`}
42
+ data-test-id={otherContextOverlayProps["data-test-id"]}
43
+ />
20
44
  </ContextOverlay>
21
45
  );
22
46
  };