@eccenca/gui-elements 24.0.0 → 24.1.0-featureimprovepublishingprocesscmem6356.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 (215) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/dist/cjs/cmem/ActivityControl/ActivityControlWidget.js +7 -2
  3. package/dist/cjs/cmem/ActivityControl/ActivityControlWidget.js.map +1 -1
  4. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +3 -3
  5. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  6. package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js +13 -3
  7. package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
  8. package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js +3 -3
  9. package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
  10. package/dist/cjs/components/AutocompleteField/AutoCompleteField.js +4 -2
  11. package/dist/cjs/components/AutocompleteField/AutoCompleteField.js.map +1 -1
  12. package/dist/cjs/components/Card/CardActions.js +2 -1
  13. package/dist/cjs/components/Card/CardActions.js.map +1 -1
  14. package/dist/cjs/components/Card/CardContent.js +4 -6
  15. package/dist/cjs/components/Card/CardContent.js.map +1 -1
  16. package/dist/cjs/components/ContentGroup/ContentGroup.js +95 -0
  17. package/dist/cjs/components/ContentGroup/ContentGroup.js.map +1 -0
  18. package/dist/cjs/components/Dialog/SimpleDialog.js +3 -3
  19. package/dist/cjs/components/Dialog/SimpleDialog.js.map +1 -1
  20. package/dist/cjs/components/Icon/canonicalIconNames.js +12 -0
  21. package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
  22. package/dist/cjs/components/Label/Label.js +8 -3
  23. package/dist/cjs/components/Label/Label.js.map +1 -1
  24. package/dist/cjs/components/Menu/MenuItem.js +3 -2
  25. package/dist/cjs/components/Menu/MenuItem.js.map +1 -1
  26. package/dist/cjs/components/MultiSelect/MultiSelect.js +1 -0
  27. package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
  28. package/dist/cjs/components/OverviewItem/OverviewItem.js +5 -2
  29. package/dist/cjs/components/OverviewItem/OverviewItem.js.map +1 -1
  30. package/dist/cjs/components/OverviewItem/OverviewItemList.js +2 -2
  31. package/dist/cjs/components/OverviewItem/OverviewItemList.js.map +1 -1
  32. package/dist/cjs/components/Switch/Switch.js +6 -4
  33. package/dist/cjs/components/Switch/Switch.js.map +1 -1
  34. package/dist/cjs/components/Tag/TagList.js +1 -1
  35. package/dist/cjs/components/Tag/TagList.js.map +1 -1
  36. package/dist/cjs/components/TextField/SearchField.js +19 -2
  37. package/dist/cjs/components/TextField/SearchField.js.map +1 -1
  38. package/dist/cjs/components/Typography/OverflowText.js +1 -1
  39. package/dist/cjs/components/Typography/OverflowText.js.map +1 -1
  40. package/dist/cjs/components/index.js +1 -0
  41. package/dist/cjs/components/index.js.map +1 -1
  42. package/dist/cjs/extensions/codemirror/CodeMirror.js +93 -11
  43. package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
  44. package/dist/cjs/extensions/codemirror/debouncedLinter.js +18 -0
  45. package/dist/cjs/extensions/codemirror/debouncedLinter.js.map +1 -0
  46. package/dist/cjs/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js +23 -14
  47. package/dist/cjs/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js.map +1 -1
  48. package/dist/cjs/extensions/codemirror/linters/jsLinter.js +36 -0
  49. package/dist/cjs/extensions/codemirror/linters/jsLinter.js.map +1 -0
  50. package/dist/cjs/extensions/codemirror/linters/turtleLinter.js +81 -0
  51. package/dist/cjs/extensions/codemirror/linters/turtleLinter.js.map +1 -0
  52. package/dist/cjs/extensions/codemirror/tests/codemirrorTestHelper.js +4 -1
  53. package/dist/cjs/extensions/codemirror/tests/codemirrorTestHelper.js.map +1 -1
  54. package/dist/cjs/extensions/codemirror/toolbars/commands/markdown.command.js +278 -0
  55. package/dist/cjs/extensions/codemirror/toolbars/commands/markdown.command.js.map +1 -0
  56. package/dist/cjs/extensions/codemirror/toolbars/markdown.toolbar.js +47 -0
  57. package/dist/cjs/extensions/codemirror/toolbars/markdown.toolbar.js.map +1 -0
  58. package/dist/cjs/extensions/codemirror/types.js +3 -0
  59. package/dist/cjs/extensions/codemirror/types.js.map +1 -0
  60. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +140 -41
  61. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  62. package/dist/cjs/extensions/react-flow/nodes/nodeUtils.js +5 -6
  63. package/dist/cjs/extensions/react-flow/nodes/nodeUtils.js.map +1 -1
  64. package/dist/esm/cmem/ActivityControl/ActivityControlWidget.js +7 -2
  65. package/dist/esm/cmem/ActivityControl/ActivityControlWidget.js.map +1 -1
  66. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +4 -4
  67. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  68. package/dist/esm/components/AutoSuggestion/AutoSuggestion.js +13 -3
  69. package/dist/esm/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
  70. package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js +14 -3
  71. package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
  72. package/dist/esm/components/AutocompleteField/AutoCompleteField.js +4 -3
  73. package/dist/esm/components/AutocompleteField/AutoCompleteField.js.map +1 -1
  74. package/dist/esm/components/Card/CardActions.js +2 -1
  75. package/dist/esm/components/Card/CardActions.js.map +1 -1
  76. package/dist/esm/components/Card/CardContent.js +4 -5
  77. package/dist/esm/components/Card/CardContent.js.map +1 -1
  78. package/dist/esm/components/ContentGroup/ContentGroup.js +100 -0
  79. package/dist/esm/components/ContentGroup/ContentGroup.js.map +1 -0
  80. package/dist/esm/components/Dialog/SimpleDialog.js +4 -4
  81. package/dist/esm/components/Dialog/SimpleDialog.js.map +1 -1
  82. package/dist/esm/components/Icon/canonicalIconNames.js +12 -0
  83. package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
  84. package/dist/esm/components/Label/Label.js +8 -3
  85. package/dist/esm/components/Label/Label.js.map +1 -1
  86. package/dist/esm/components/Menu/MenuItem.js +3 -2
  87. package/dist/esm/components/Menu/MenuItem.js.map +1 -1
  88. package/dist/esm/components/MultiSelect/MultiSelect.js +1 -0
  89. package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
  90. package/dist/esm/components/OverviewItem/OverviewItem.js +5 -2
  91. package/dist/esm/components/OverviewItem/OverviewItem.js.map +1 -1
  92. package/dist/esm/components/OverviewItem/OverviewItemList.js +2 -2
  93. package/dist/esm/components/OverviewItem/OverviewItemList.js.map +1 -1
  94. package/dist/esm/components/Switch/Switch.js +7 -5
  95. package/dist/esm/components/Switch/Switch.js.map +1 -1
  96. package/dist/esm/components/Tag/TagList.js +1 -1
  97. package/dist/esm/components/Tag/TagList.js.map +1 -1
  98. package/dist/esm/components/TextField/SearchField.js +35 -2
  99. package/dist/esm/components/TextField/SearchField.js.map +1 -1
  100. package/dist/esm/components/Typography/OverflowText.js +1 -1
  101. package/dist/esm/components/Typography/OverflowText.js.map +1 -1
  102. package/dist/esm/components/index.js +1 -0
  103. package/dist/esm/components/index.js.map +1 -1
  104. package/dist/esm/extensions/codemirror/CodeMirror.js +94 -13
  105. package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
  106. package/dist/esm/extensions/codemirror/debouncedLinter.js +15 -0
  107. package/dist/esm/extensions/codemirror/debouncedLinter.js.map +1 -0
  108. package/dist/esm/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js +20 -11
  109. package/dist/esm/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js.map +1 -1
  110. package/dist/esm/extensions/codemirror/linters/jsLinter.js +32 -0
  111. package/dist/esm/extensions/codemirror/linters/jsLinter.js.map +1 -0
  112. package/dist/esm/extensions/codemirror/linters/turtleLinter.js +77 -0
  113. package/dist/esm/extensions/codemirror/linters/turtleLinter.js.map +1 -0
  114. package/dist/esm/extensions/codemirror/tests/codemirrorTestHelper.js +4 -0
  115. package/dist/esm/extensions/codemirror/tests/codemirrorTestHelper.js.map +1 -1
  116. package/dist/esm/extensions/codemirror/toolbars/commands/markdown.command.js +283 -0
  117. package/dist/esm/extensions/codemirror/toolbars/commands/markdown.command.js.map +1 -0
  118. package/dist/esm/extensions/codemirror/toolbars/markdown.toolbar.js +41 -0
  119. package/dist/esm/extensions/codemirror/toolbars/markdown.toolbar.js.map +1 -0
  120. package/dist/esm/extensions/codemirror/types.js +2 -0
  121. package/dist/esm/extensions/codemirror/types.js.map +1 -0
  122. package/dist/esm/extensions/react-flow/nodes/NodeContent.js +149 -48
  123. package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  124. package/dist/esm/extensions/react-flow/nodes/nodeUtils.js +5 -6
  125. package/dist/esm/extensions/react-flow/nodes/nodeUtils.js.map +1 -1
  126. package/dist/types/cmem/ActivityControl/ActivityControlWidget.d.ts +1 -1
  127. package/dist/types/cmem/react-flow/StickyNoteModal/StickyNoteModal.d.ts +5 -1
  128. package/dist/types/components/AutoSuggestion/ExtendedCodeEditor.d.ts +11 -6
  129. package/dist/types/components/Card/CardActions.d.ts +5 -1
  130. package/dist/types/components/Card/CardContent.d.ts +1 -2
  131. package/dist/types/components/ContentGroup/ContentGroup.d.ts +78 -0
  132. package/dist/types/components/Dialog/SimpleDialog.d.ts +4 -1
  133. package/dist/types/components/Icon/canonicalIconNames.d.ts +12 -0
  134. package/dist/types/components/Label/Label.d.ts +7 -1
  135. package/dist/types/components/Menu/MenuItem.d.ts +8 -1
  136. package/dist/types/components/OverviewItem/OverviewItem.d.ts +13 -1
  137. package/dist/types/components/OverviewItem/OverviewItemList.d.ts +3 -2
  138. package/dist/types/components/ProgressBar/ProgressBar.d.ts +2 -2
  139. package/dist/types/components/Structure/TitleSubsection.d.ts +9 -1
  140. package/dist/types/components/Switch/Switch.d.ts +3 -3
  141. package/dist/types/components/Tabs/Tab.d.ts +20 -4
  142. package/dist/types/components/TextField/SearchField.d.ts +1 -1
  143. package/dist/types/components/Typography/OverflowText.d.ts +23 -2
  144. package/dist/types/components/index.d.ts +1 -0
  145. package/dist/types/extensions/codemirror/CodeMirror.d.ts +32 -5
  146. package/dist/types/extensions/codemirror/debouncedLinter.d.ts +4 -0
  147. package/dist/types/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.d.ts +7 -5
  148. package/dist/types/extensions/codemirror/linters/jsLinter.d.ts +5 -0
  149. package/dist/types/extensions/codemirror/linters/turtleLinter.d.ts +5 -0
  150. package/dist/types/extensions/codemirror/tests/codemirrorTestHelper.d.ts +1 -0
  151. package/dist/types/extensions/codemirror/toolbars/commands/markdown.command.d.ts +55 -0
  152. package/dist/types/extensions/codemirror/toolbars/markdown.toolbar.d.ts +12 -0
  153. package/dist/types/extensions/codemirror/types.d.ts +5 -0
  154. package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +18 -4
  155. package/dist/types/extensions/react-flow/nodes/nodeUtils.d.ts +7 -6
  156. package/dist/types/extensions/react-flow/versionsupport.d.ts +1 -1
  157. package/package.json +59 -47
  158. package/src/cmem/ActivityControl/ActivityControlWidget.tsx +5 -2
  159. package/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx +16 -2
  160. package/src/cmem/react-flow/configuration/_colors-graph.scss +4 -1
  161. package/src/cmem/react-flow/configuration/_colors-workflow.scss +3 -0
  162. package/src/components/AutoSuggestion/AutoSuggestion.tsx +14 -3
  163. package/src/components/AutoSuggestion/ExtendedCodeEditor.tsx +29 -6
  164. package/src/components/AutocompleteField/AutoCompleteField.tsx +5 -3
  165. package/src/components/Card/CardActions.tsx +6 -0
  166. package/src/components/Card/CardContent.tsx +8 -4
  167. package/src/components/Card/card.scss +15 -0
  168. package/src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx +3 -2
  169. package/src/components/ContentGroup/ContentGroup.stories.tsx +47 -0
  170. package/src/components/ContentGroup/ContentGroup.tsx +256 -0
  171. package/src/components/ContentGroup/_contentgroup.scss +56 -0
  172. package/src/components/ContextOverlay/ContextOverlay.stories.tsx +15 -4
  173. package/src/components/Depiction/depiction.scss +7 -0
  174. package/src/components/Dialog/SimpleDialog.tsx +9 -2
  175. package/src/components/Dialog/stories/AlertDialog.stories.tsx +5 -1
  176. package/src/components/Dialog/stories/Modal.stories.tsx +4 -2
  177. package/src/components/Dialog/stories/SimpleDialog.stories.tsx +5 -2
  178. package/src/components/Icon/canonicalIconNames.tsx +12 -0
  179. package/src/components/Label/Label.stories.tsx +2 -1
  180. package/src/components/Label/Label.tsx +17 -1
  181. package/src/components/Label/label.scss +5 -1
  182. package/src/components/Menu/MenuItem.tsx +27 -1
  183. package/src/components/Menu/menu.scss +1 -0
  184. package/src/components/MultiSelect/MultiSelect.tsx +1 -0
  185. package/src/components/OverviewItem/OverviewItem.tsx +24 -1
  186. package/src/components/OverviewItem/OverviewItemList.tsx +3 -2
  187. package/src/components/OverviewItem/overviewitem.scss +4 -1
  188. package/src/components/OverviewItem/stories/OverviewItem.stories.tsx +6 -12
  189. package/src/components/Select/Select.stories.tsx +4 -1
  190. package/src/components/Switch/Switch.tsx +27 -8
  191. package/src/components/Tag/TagList.tsx +2 -2
  192. package/src/components/TextField/SearchField.tsx +37 -9
  193. package/src/components/TextField/stories/SearchField.stories.tsx +15 -1
  194. package/src/components/TextField/stories/TextField.stories.tsx +2 -1
  195. package/src/components/TextField/textfield.scss +17 -3
  196. package/src/components/Typography/OverflowText.tsx +24 -3
  197. package/src/components/Typography/stories/OverflowText.stories.tsx +33 -0
  198. package/src/components/index.scss +1 -0
  199. package/src/components/index.ts +1 -0
  200. package/src/extensions/codemirror/CodeMirror.stories.tsx +19 -1
  201. package/src/extensions/codemirror/CodeMirror.tsx +154 -16
  202. package/src/extensions/codemirror/_codemirror.scss +130 -1
  203. package/src/extensions/codemirror/debouncedLinter.ts +26 -0
  204. package/src/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.ts +21 -12
  205. package/src/extensions/codemirror/linters/jsLinter.ts +38 -0
  206. package/src/extensions/codemirror/linters/turtleLinter.ts +102 -0
  207. package/src/extensions/codemirror/tests/codemirrorTestHelper.ts +4 -0
  208. package/src/extensions/codemirror/toolbars/commands/markdown.command.ts +340 -0
  209. package/src/extensions/codemirror/toolbars/markdown.toolbar.tsx +117 -0
  210. package/src/extensions/codemirror/types.ts +7 -0
  211. package/src/extensions/react-flow/_config.scss +1 -0
  212. package/src/extensions/react-flow/nodes/NodeContent.tsx +170 -52
  213. package/src/extensions/react-flow/nodes/_nodes.scss +71 -35
  214. package/src/extensions/react-flow/nodes/nodeUtils.tsx +16 -14
  215. package/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +51 -12
@@ -22,11 +22,16 @@ type NodeContentHandleNextProps = HandleNextProps;
22
22
 
23
23
  export type NodeContentHandleProps = NodeContentHandleLegacyProps | NodeContentHandleNextProps;
24
24
 
25
- type NodeDimensions = {
26
- width: number;
27
- height: number;
25
+ export type NodeDimensions = {
26
+ width?: number;
27
+ height?: number;
28
28
  };
29
29
 
30
+ type ResizeDirections =
31
+ | { right: true; bottom?: false }
32
+ | { right?: false; bottom: true }
33
+ | { right: true; bottom: true };
34
+
30
35
  type IntroductionTime = {
31
36
  /**
32
37
  * The delay time in ms before the introduction animation is displayed.
@@ -210,6 +215,10 @@ export interface NodeContentProps<NODE_DATA, NODE_CONTENT_PROPS = any>
210
215
  * width and height dimensions of the node (Optional)
211
216
  */
212
217
  nodeDimensions?: NodeDimensions;
218
+ /** if node is resizable, this allows direction of specificity */
219
+ resizeDirections?: ResizeDirections;
220
+ /** determines how much width a node can be resized to */
221
+ resizeMaxDimensions?: Partial<NodeDimensions>;
213
222
  }
214
223
 
215
224
  interface MemoHandlerLegacyProps extends HandleProps {
@@ -317,20 +326,24 @@ export function NodeContent<CONTENT_PROPS = any>({
317
326
  //handles = defaultHandles(),
318
327
  adaptHeightForHandleMinCount,
319
328
  adaptSizeIncrement = 15,
329
+ // FIXME: getMinimalTooltipData is just being ignored, only used in `NodeDefault`
320
330
  getMinimalTooltipData = getDefaultMinimalTooltipData,
321
331
  style = {},
322
332
  showUnconnectableHandles = false,
323
333
  animated = false,
324
334
  introductionTime = 0,
335
+ // resizing
325
336
  onNodeResize,
326
337
  nodeDimensions,
338
+ resizeDirections = { bottom: true, right: true },
339
+ resizeMaxDimensions,
327
340
  // forwarded props
328
341
  targetPosition = Position.Left,
329
342
  sourcePosition = Position.Right,
330
343
  isConnectable = true,
331
344
  selected,
332
345
  letPassWheelEvents = false,
333
- // businessData is just being ignored
346
+ // FIXME: businessData is just being ignored
334
347
  businessData,
335
348
  // other props for DOM element
336
349
  ...otherDomProps
@@ -341,11 +354,16 @@ export function NodeContent<CONTENT_PROPS = any>({
341
354
 
342
355
  const { handles = defaultHandles(flowVersionCheck), ...otherProps } = otherDomProps;
343
356
 
344
- const isResizeable = !!onNodeResize && minimalShape === "none";
345
- const [width, setWidth] = React.useState<number>(nodeDimensions?.width ?? 0);
346
- const [height, setHeight] = React.useState<number>(nodeDimensions?.height ?? 0);
357
+ const hasValidResizeDirection = resizeDirections.bottom || resizeDirections.right;
358
+ const isResizable = typeof onNodeResize === "function" && hasValidResizeDirection && minimalShape === "none";
359
+
360
+ const [width, setWidth] = React.useState<number | undefined>(nodeDimensions?.width ?? undefined);
361
+ const [height, setHeight] = React.useState<number | undefined>(nodeDimensions?.height ?? undefined);
362
+ // Keeps the initial size of the element
363
+ const originalSize = React.useRef<NodeDimensions>({})
364
+
347
365
  let zoom = 1;
348
- if (isResizeable)
366
+ if (isResizable)
349
367
  try {
350
368
  [, , zoom] =
351
369
  flowVersionCheck === "legacy"
@@ -371,28 +389,70 @@ export function NodeContent<CONTENT_PROPS = any>({
371
389
  handleStack[Position.Left] =
372
390
  flowVersionCheck === "legacy" ? ([] as NodeContentHandleLegacyProps[]) : ([] as NodeContentHandleNextProps[]);
373
391
 
374
- // initial dimension before resize
392
+ const saveOriginalSize = () => {
393
+ const currentClassNames = nodeContentRef.current.classList;
394
+ if (currentClassNames.contains("was-resized") && !width && !height) {
395
+ currentClassNames.remove("was-resized");
396
+ }
397
+ originalSize.current.width = nodeContentRef.current.offsetWidth as number;
398
+ originalSize.current.height = nodeContentRef.current.offsetHeight as number;
399
+ }
400
+
375
401
  React.useEffect(() => {
376
- if (!!onNodeResize && minimalShape === "none") {
377
- if (!nodeDimensions) {
378
- setWidth(nodeContentRef.current.offsetWidth);
379
- setHeight(nodeContentRef.current.offsetHeight);
380
- onNodeResize({
381
- height: nodeContentRef.current.offsetHeight,
382
- width: nodeContentRef.current.offsetWidth,
383
- });
402
+ if(nodeContentRef.current && (!(originalSize.current.width || originalSize.current.height) || !(width || height))) {
403
+ saveOriginalSize();
404
+ }
405
+ }, [!!nodeContentRef.current, !(originalSize.current.width || originalSize.current.height), !(width || height)])
406
+
407
+ // Update width and height when node dimensions parameters has changed
408
+ React.useEffect(() => {
409
+ const updateWidth = nodeDimensions?.width ? validateWidth(nodeDimensions?.width) : undefined;
410
+ const updateHeight = nodeDimensions?.height ? validateHeight(nodeDimensions?.height) : undefined;
411
+ setWidth(updateWidth);
412
+ setHeight(updateHeight);
413
+ }, [nodeDimensions]);
414
+
415
+ const isResizingActive = React.useCallback((): boolean => {
416
+ const currentClassNames = nodeContentRef.current.classList;
417
+ return resizeDirections.right === currentClassNames.contains("is-resizable-horizontal") ||
418
+ resizeDirections.bottom === currentClassNames.contains("is-resizable-vertical");
419
+ }, [])
420
+
421
+ // force default size when resizing is activated but no dimensions are set
422
+ React.useEffect(() => {
423
+ const resizingActive = isResizingActive();
424
+
425
+ if (isResizable && !resizingActive) {
426
+ if (!width || !height) {
427
+ const newWidth = validateWidth(width ?? originalSize.current?.width as number);
428
+ const newHeight = validateHeight(height ?? originalSize.current?.height as number);
429
+ setWidth(newWidth);
430
+ setHeight(newHeight);
384
431
  }
385
- nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable";
386
432
  }
387
- }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions]);
433
+ }, [nodeContentRef.current, onNodeResize, minimalShape, resizeDirections?.bottom, resizeDirections?.right, width, height]); // need to be done everytime a property is changed and the element is re-rendered, otherwise the resizing class is lost
388
434
 
389
- // update node dimensions when resized
435
+ // conditional enhancements for activated resizing
390
436
  React.useEffect(() => {
391
- if (nodeDimensions) {
392
- setWidth(nodeDimensions.width);
393
- setHeight(nodeDimensions.height);
437
+ const currentClassNames = nodeContentRef.current.classList;
438
+ const resizingActive = isResizingActive();
439
+
440
+ if (isResizable && !resizingActive) {
441
+ if (currentClassNames.contains("is-resizable-horizontal")) {
442
+ currentClassNames.remove("is-resizable-horizontal");
443
+ }
444
+ if (currentClassNames.contains("is-resizable-vertical")) {
445
+ currentClassNames.remove("is-resizable-vertical");
446
+ }
447
+
448
+ if (resizeDirections.right) {
449
+ currentClassNames.add("is-resizable-horizontal");
450
+ }
451
+ if (resizeDirections.bottom) {
452
+ currentClassNames.add("is-resizable-vertical");
453
+ }
394
454
  }
395
- }, [nodeDimensions]);
455
+ }); // need to be done everytime a property is changed and the element is re-rendered, otherwise the resizing class is lost
396
456
 
397
457
  // remove introduction class
398
458
  React.useEffect(() => {
@@ -460,7 +520,14 @@ export function NodeContent<CONTENT_PROPS = any>({
460
520
  );
461
521
 
462
522
  const resizableStyles =
463
- !!onNodeResize === true && minimalShape === "none" && width + height > 0 ? { width, height } : {};
523
+ isResizable && (width ?? 0) + (height ?? 0) > 0
524
+ ? {
525
+ width,
526
+ height,
527
+ maxWidth: resizeDirections.right ? resizeMaxDimensions?.width ?? undefined : undefined,
528
+ maxHeight: resizeDirections.bottom ? resizeMaxDimensions?.height ?? undefined : undefined,
529
+ }
530
+ : {};
464
531
 
465
532
  const introductionStyles =
466
533
  introductionTime && !introductionDone
@@ -470,6 +537,7 @@ export function NodeContent<CONTENT_PROPS = any>({
470
537
  }ms`,
471
538
  } as React.CSSProperties)
472
539
  : {};
540
+
473
541
  const nodeContent = (
474
542
  <>
475
543
  <section
@@ -590,34 +658,84 @@ export function NodeContent<CONTENT_PROPS = any>({
590
658
  </>
591
659
  );
592
660
 
593
- const resizableNode = () => (
594
- <Resizable
595
- className={`${eccgui}-graphviz__node__resizer`}
596
- handleWrapperClass={`${eccgui}-graphviz__node__resizer--cursorhandles nodrag`}
597
- size={{ height, width }}
598
- enable={{ bottomRight: true }}
599
- scale={zoom}
600
- onResize={(_0, _1, _2, d) => {
601
- if (nodeContentRef.current) {
602
- nodeContentRef.current.style.width = width + d.width + "px";
603
- nodeContentRef.current.style.height = height + d.height + "px";
661
+ const validateWidth = (resizedWidth: number): number | undefined => {
662
+ // only allow value if resize direction is allowed
663
+ if (!resizeDirections.right) {
664
+ return undefined;
665
+ }
666
+ // we need to check because there is probably a min value defined via CSS
667
+ const min = parseFloat(getComputedStyle(nodeContentRef.current).getPropertyValue("min-width"));
668
+ // we need to check for a given max value
669
+ const max = resizeMaxDimensions?.width ?? Infinity;
670
+ const validatedWidth = Math.max(Math.min(resizedWidth, max), min);
671
+ return validatedWidth;
672
+ };
673
+
674
+ const validateHeight = (resizedHeight: number): number | undefined => {
675
+ if (!resizeDirections.bottom) {
676
+ return undefined;
677
+ }
678
+ // we need to check because there is probably a min value defined via CSS
679
+ const min = parseFloat(getComputedStyle(nodeContentRef.current).getPropertyValue("min-height"));
680
+ const max = resizeMaxDimensions?.height ?? Infinity;
681
+ const validatedHeight = Math.max(Math.min(resizedHeight, max), min);
682
+ return validatedHeight;
683
+ };
684
+
685
+ const resizableNode = () => {
686
+ const size = { height: height ?? "auto", width: width ?? "auto" };
687
+ return (
688
+ <Resizable
689
+ className={
690
+ `${eccgui}-graphviz__node__resizer` +
691
+ (resizeDirections.right ? ` ${eccgui}-graphviz__node__resizer--right` : "") +
692
+ (resizeDirections.bottom ? ` ${eccgui}-graphviz__node__resizer--bottom` : "")
604
693
  }
605
- }}
606
- onResizeStop={(_0, _1, _2, d) => {
607
- setWidth(width + d.width);
608
- setHeight(height + d.height);
609
- onNodeResize &&
610
- onNodeResize({
611
- height: height + d.height,
612
- width: width + d.width,
613
- });
614
- }}
615
- >
616
- {nodeContent}
617
- </Resizable>
618
- );
694
+ handleWrapperClass={`${eccgui}-graphviz__node__resizer--cursorhandles` + " nodrag"}
695
+ size={size}
696
+ maxHeight={resizeMaxDimensions?.height ?? undefined}
697
+ maxWidth={resizeMaxDimensions?.width ?? undefined}
698
+ enable={resizeDirections.bottom && resizeDirections.right ? { bottomRight: true } : resizeDirections}
699
+ scale={zoom}
700
+ onResize={(_0, _1, _2, d) => {
701
+ if (nodeContentRef.current) {
702
+ const nextWidth = resizeDirections.right
703
+ ? (width ?? originalSize.current.width ?? 0) + d.width
704
+ : undefined;
705
+ const nextHeight = resizeDirections.bottom
706
+ ? (height ?? originalSize.current.height ?? 0) + d.height
707
+ : undefined;
708
+ if (nextWidth || nextHeight) {
709
+ const currentClassNames = nodeContentRef.current.classList;
710
+ currentClassNames.add("was-resized");
711
+ }
712
+ if (nextWidth) {
713
+ nodeContentRef.current.style.width = `${nextWidth}px`;
714
+ }
715
+ if (nextHeight) {
716
+ nodeContentRef.current.style.height = `${nextHeight}px`;
717
+ }
718
+ }
719
+ }}
720
+ onResizeStop={(_0, _1, _2, d) => {
721
+ const nextWidth = validateWidth((width ?? originalSize.current.width ?? 0) + d.width);
722
+ const nextHeight = validateHeight((height ?? originalSize.current.height ?? 0) + d.height);
723
+ setWidth(nextWidth);
724
+ setHeight(nextHeight);
725
+ if (onNodeResize) {
726
+ onNodeResize({
727
+ height: nextHeight,
728
+ width: nextWidth,
729
+ });
730
+ }
731
+ }}
732
+ >
733
+ {nodeContent}
734
+ </Resizable>
735
+ );
736
+ };
619
737
 
620
- return isResizeable ? resizableNode() : nodeContent;
738
+ return isResizable ? resizableNode() : nodeContent;
621
739
  }
622
740
 
623
741
  const evaluateHighlightColors = (
@@ -644,7 +762,7 @@ const evaluateHighlightColors = (
644
762
  let customColor = Color("#ffffff");
645
763
  try {
646
764
  customColor = Color(color);
647
- } catch (ex) {
765
+ } catch {
648
766
  // eslint-disable-next-line no-console
649
767
  console.warn("Received invalid color for highlight: " + color);
650
768
  }
@@ -49,6 +49,38 @@
49
49
  &:hover {
50
50
  box-shadow: 0 0 0 6 * $reactflow-node-border-width rgba($reactflow-edge-stroke-color-selected, 0.05);
51
51
  }
52
+
53
+ &.was-resized.is-resizable-vertical {
54
+ max-height: unset;
55
+ }
56
+ }
57
+
58
+ .#{$eccgui}-graphviz__node--tiny {
59
+ width: $reactflow-node-basesize * 4;
60
+ min-height: $reactflow-node-basesize;
61
+ max-height: $reactflow-node-basesize * 4;
62
+ }
63
+
64
+ .#{$eccgui}-graphviz__node--small {
65
+ width: $reactflow-node-basesize * 5;
66
+ min-height: $reactflow-node-basesize;
67
+ max-height: $reactflow-node-basesize * 8;
68
+ }
69
+
70
+ .#{$eccgui}-graphviz__node--medium {
71
+ width: $reactflow-node-basesize * 8;
72
+ min-height: $reactflow-node-basesize;
73
+ max-height: $reactflow-node-basesize * 13;
74
+ }
75
+
76
+ .#{$eccgui}-graphviz__node--large {
77
+ width: $reactflow-node-basesize * 13;
78
+ min-height: $reactflow-node-basesize;
79
+ max-height: $reactflow-node-basesize * 13;
80
+ }
81
+
82
+ .#{$eccgui}-graphviz__node--fullwidth {
83
+ width: 100%;
52
84
  }
53
85
 
54
86
  .#{$eccgui}-graphviz__node--minimal-rectangular,
@@ -200,54 +232,58 @@
200
232
  background-color: $reactflow-node-background-color;
201
233
  }
202
234
 
203
- // Node sizes
235
+ // Node Resizer
204
236
 
205
- .#{$eccgui}-graphviz__node__resizer,
206
- .#{$eccgui}-graphviz__node.is-resizeable {
237
+ .#{$eccgui}-graphviz__node.is-resizable-horizontal,
238
+ .#{$eccgui}-graphviz__node.is-resizable-vertical {
207
239
  min-width: 2.5 * $reactflow-node-basesize;
208
240
  min-height: 2.5 * $reactflow-node-basesize;
209
241
  }
210
242
 
243
+ .#{$eccgui}-graphviz__node__resizer--cursorhandles {
244
+ position: absolute;
245
+ height: 0;
246
+ width: 0;
247
+ bottom: 0;
248
+ right: 0;
249
+ overflow: visible;
250
+ display: none;
251
+
252
+ & > div {
253
+ overflow: visible;
254
+ z-index: 0 !important;
255
+ height: $reactflow-cursor-delimiter-offset * 3 !important;
256
+ width: $reactflow-cursor-delimiter-offset * 3 !important;
257
+ top: unset !important;
258
+ left: unset !important;
259
+ bottom: -1 * $reactflow-cursor-delimiter-offset !important;
260
+ right: -1 * $reactflow-cursor-delimiter-offset !important;
261
+ border-bottom: $reactflow-node-border-width solid $reactflow-node-border-color;
262
+ border-right: $reactflow-node-border-width solid $reactflow-node-border-color;
263
+
264
+ .#{$eccgui}-graphviz__node__resizer--right:not(.#{$eccgui}-graphviz__node__resizer--bottom) & {
265
+ bottom: 0 !important;
266
+ border-bottom: none;
267
+ }
268
+ .#{$eccgui}-graphviz__node__resizer--bottom:not(.#{$eccgui}-graphviz__node__resizer--right) & {
269
+ right: 0 !important;
270
+ border-right: none;
271
+ }
272
+ }
273
+ }
274
+
211
275
  .#{$eccgui}-graphviz__node__resizer {
276
+ min-width: 2.5 * $reactflow-node-basesize;
277
+ min-height: 2.5 * $reactflow-node-basesize;
278
+
212
279
  .selected &,
213
280
  &:hover {
214
281
  .#{$eccgui}-graphviz__node__resizer--cursorhandles {
215
- & > div {
216
- overflow: auto;
217
- resize: both;
218
- }
282
+ display: block;
219
283
  }
220
284
  }
221
285
  }
222
286
 
223
- .#{$eccgui}-graphviz__node--tiny:not(.is-resizeable) {
224
- width: $reactflow-node-basesize * 4;
225
- min-height: $reactflow-node-basesize;
226
- max-height: $reactflow-node-basesize * 4;
227
- }
228
-
229
- .#{$eccgui}-graphviz__node--small:not(.is-resizeable) {
230
- width: $reactflow-node-basesize * 5;
231
- min-height: $reactflow-node-basesize;
232
- max-height: $reactflow-node-basesize * 8;
233
- }
234
-
235
- .#{$eccgui}-graphviz__node--medium:not(.is-resizeable) {
236
- width: $reactflow-node-basesize * 8;
237
- min-height: $reactflow-node-basesize;
238
- max-height: $reactflow-node-basesize * 13;
239
- }
240
-
241
- .#{$eccgui}-graphviz__node--large:not(.is-resizeable) {
242
- width: $reactflow-node-basesize * 13;
243
- min-height: $reactflow-node-basesize;
244
- max-height: $reactflow-node-basesize * 13;
245
- }
246
-
247
- .#{$eccgui}-graphviz__node--fullwidth:not(.is-resizeable) {
248
- width: 100%;
249
- }
250
-
251
287
  // Node border overwrites
252
288
 
253
289
  .#{$eccgui}-graphviz__node--border-solid {
@@ -1,28 +1,30 @@
1
1
  import { CSSProperties } from "react";
2
- import { Node } from "react-flow-renderer";
2
+ import {Node, XYPosition} from "react-flow-renderer";
3
3
  import Color from "color";
4
+ import {NodeDimensions} from "./NodeContent";
4
5
 
5
- type IStickyNote = {
6
+ /** A sticky note for display in the UI as returned from the backend. */
7
+ export interface StickyNote {
6
8
  id: string;
7
9
  content: string;
8
10
  color: string;
9
- position: number[];
10
- dimension: number[];
11
- };
11
+ position: XYPosition & NodeDimensions;
12
+ }
12
13
 
13
14
  /**
14
15
  * converts a react-flow node with
15
- * type = "stickynote" to IStickyNote type compatible with the backend
16
+ * type = "stickynote" to StickyNote type compatible with the backend
16
17
  * @param node
17
- * @returns {IStickyNote}
18
+ * @returns {StickyNote}
18
19
  */
19
- const transformNodeToStickyNode = (node: Node<any>): IStickyNote => ({
20
- id: node.id,
21
- content: node.data.businessData.stickyNote!,
22
- position: [node.position.x, node.position.y],
23
- dimension: [node.data.nodeDimensions?.width!, node.data.nodeDimensions?.height!],
24
- color: node.data.style?.borderColor!,
25
- });
20
+ const transformNodeToStickyNode = (node: Node<any>): StickyNote => {
21
+ return {
22
+ id: node.id,
23
+ content: node.data.businessData.stickyNote!,
24
+ position: {x: node.position.x, y: node.position.y, width: node.data.nodeDimensions?.width, height: node.data.nodeDimensions?.height},
25
+ color: node.data.style?.borderColor!,
26
+ }
27
+ };
26
28
 
27
29
  /**
28
30
  * takes in a hex color string and returns
@@ -15,9 +15,9 @@ import {
15
15
  OverflowText,
16
16
  Tag,
17
17
  TagList,
18
+ NodeContent,
19
+ NodeContentExtension,
18
20
  } from "./../../../../index";
19
- import { NodeContent } from "./../NodeContent";
20
- import { NodeContentExtension } from "./../NodeContentExtension";
21
21
  import {
22
22
  Default as ContentExtensionExample,
23
23
  SlideOutOfNode as ContentExtensionExampleSlideOut,
@@ -103,11 +103,12 @@ export default {
103
103
  },
104
104
  intent: {
105
105
  control: "select",
106
- options: { "Not set": undefined, ...Definitions },
106
+ options: [ undefined, ...Object.values(Definitions) ],
107
107
  },
108
108
  highlightColor: {
109
109
  control: "select",
110
- options: {
110
+ options: [ "Not set", "Default", "Alternate", "Default + alternate", "Custom (red)", "Default + Custom (red)", "Custom (green) + alternate", "Custom (purple) + custom (yellow)"],
111
+ mapping: {
111
112
  "Not set": undefined,
112
113
  Default: "default",
113
114
  Alternate: "alternate",
@@ -118,8 +119,8 @@ export default {
118
119
  "Custom (purple) + custom (yellow)": ["purple", "yellow"],
119
120
  },
120
121
  },
121
- content: { control: "none" },
122
- footerContent: { control: "none" },
122
+ content: { control: false },
123
+ footerContent: { control: false },
123
124
  isConnectable: { table: { disable: true } },
124
125
  targetPosition: { table: { disable: true } },
125
126
  sourcePosition: { table: { disable: true } },
@@ -128,18 +129,52 @@ export default {
128
129
  },
129
130
  } as Meta<typeof NodeContent>;
130
131
 
132
+ let forcedUpdateKey = 0; // @see https://github.com/storybookjs/storybook/issues/13375#issuecomment-1291011856
131
133
  const NodeContentExample = (args: any) => {
132
134
  const [reactflowInstance, setReactflowInstance] = useState(null);
133
135
  const [elements, setElements] = useState([] as Elements);
134
- //const [edgeTools, setEdgeTools] = useState<JSX.Element>(<></>);
136
+
137
+ const defaultElement = {
138
+ id: "example-1",
139
+ type: "default",
140
+ data: args,
141
+ position: { x: 50, y: 50 },
142
+ };
135
143
 
136
144
  useEffect(() => {
145
+ const sizeReset = {}
146
+ if (args.resizeMaxDimensions && args.resizeDirections) {
147
+ sizeReset["onNodeResize"] = (dimensions) => {
148
+ // eslint-disable-next-line no-console
149
+ console.log("call onNodeResize method")
150
+ if (args.onNodeResize) {
151
+ args.onNodeResize(dimensions);
152
+ }
153
+ if (dimensions?.width || dimensions?.height) {
154
+ sizeReset["menuButtons"] = <IconButton name="item-reset" onClick={() => {
155
+ // eslint-disable-next-line no-console
156
+ console.log("reset size");
157
+ setElements([
158
+ {
159
+ ...defaultElement,
160
+ data: {...defaultElement.data, ...sizeReset, ...{ nodeDimensions: {} }},
161
+ },
162
+ ] as Elements);
163
+
164
+ }}/>;
165
+ }
166
+ setElements([
167
+ {
168
+ ...defaultElement,
169
+ data: {...defaultElement.data, ...sizeReset, ...{ nodeDimensions: dimensions }},
170
+ },
171
+ ] as Elements);
172
+ }
173
+ }
137
174
  setElements([
138
175
  {
139
- id: "example-1",
140
- type: "default",
141
- data: args,
142
- position: { x: 50, y: 50 },
176
+ ...defaultElement,
177
+ data: {...defaultElement.data, ...sizeReset},
143
178
  },
144
179
  ] as Elements);
145
180
  }, [args]);
@@ -166,7 +201,7 @@ const NodeContentExample = (args: any) => {
166
201
  );
167
202
  };
168
203
 
169
- const Template: StoryFn<typeof NodeContent> = (args) => <NodeContentExample {...args} /*some comment*/ />;
204
+ const Template: StoryFn<typeof NodeContent> = (args) => <NodeContentExample {...args} /*some comment*/ key={++forcedUpdateKey} />;
170
205
 
171
206
  export const Default = Template.bind({});
172
207
  Default.args = {
@@ -206,7 +241,11 @@ Default.args = {
206
241
  export const Resizeable = Template.bind({});
207
242
  Resizeable.args = {
208
243
  ...Default.args,
244
+ resizeMaxDimensions: { width: 1000, height: 500 },
245
+ nodeDimensions: {},
246
+ resizeDirections: { bottom: true, right: true },
209
247
  onNodeResize: (dimensions) => {
248
+ // eslint-disable-next-line no-console
210
249
  console.log("onNodeResize", `new dimensions: ${dimensions.width}x${dimensions.height}`);
211
250
  },
212
251
  };