@eccenca/gui-elements 23.0.0-rc.2 → 23.0.0-rc.3-unofficial.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 (165) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/dist/cjs/cmem/index.js +3 -1
  3. package/dist/cjs/cmem/index.js.map +1 -1
  4. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +64 -0
  5. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -0
  6. package/dist/cjs/cmem/react-flow/configuration/graph.js.map +1 -1
  7. package/dist/cjs/cmem/react-flow/configuration/linking.js +2 -0
  8. package/dist/cjs/cmem/react-flow/configuration/linking.js.map +1 -1
  9. package/dist/cjs/cmem/react-flow/configuration/typing.js +35 -0
  10. package/dist/cjs/cmem/react-flow/configuration/typing.js.map +1 -0
  11. package/dist/cjs/cmem/react-flow/configuration/workflow.js +2 -0
  12. package/dist/cjs/cmem/react-flow/configuration/workflow.js.map +1 -1
  13. package/dist/cjs/cmem/react-flow/nodes/StickyNoteNode.js +42 -0
  14. package/dist/cjs/cmem/react-flow/nodes/StickyNoteNode.js.map +1 -0
  15. package/dist/cjs/common/utils/CssCustomProperties.js +114 -0
  16. package/dist/cjs/common/utils/CssCustomProperties.js.map +1 -0
  17. package/dist/cjs/common/utils/getColorConfiguration.js +21 -0
  18. package/dist/cjs/common/utils/getColorConfiguration.js.map +1 -0
  19. package/dist/cjs/components/Icon/canonicalIconNames.js +124 -114
  20. package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
  21. package/dist/cjs/components/Tag/Tag.js +2 -1
  22. package/dist/cjs/components/Tag/Tag.js.map +1 -1
  23. package/dist/cjs/extensions/codemirror/CodeMirror.js +3 -3
  24. package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
  25. package/dist/cjs/extensions/react-flow/index.js +6 -1
  26. package/dist/cjs/extensions/react-flow/index.js.map +1 -1
  27. package/dist/cjs/extensions/react-flow/minimap/MiniMap.js +3 -2
  28. package/dist/cjs/extensions/react-flow/minimap/MiniMap.js.map +1 -1
  29. package/dist/cjs/extensions/react-flow/minimap/utils.js +12 -6
  30. package/dist/cjs/extensions/react-flow/minimap/utils.js.map +1 -1
  31. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +74 -25
  32. package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  33. package/dist/cjs/extensions/react-flow/nodes/NodeContentExtension.js +10 -6
  34. package/dist/cjs/extensions/react-flow/nodes/NodeContentExtension.js.map +1 -1
  35. package/dist/cjs/extensions/react-flow/nodes/nodeUtils.js +49 -0
  36. package/dist/cjs/extensions/react-flow/nodes/nodeUtils.js.map +1 -0
  37. package/dist/cjs/legacy-replacements/Tabs/Tabs.js +1 -1
  38. package/dist/cjs/legacy-replacements/Tabs/Tabs.js.map +1 -1
  39. package/dist/cjs/legacy-replacements/TextField/TextField.js +5 -8
  40. package/dist/cjs/legacy-replacements/TextField/TextField.js.map +1 -1
  41. package/dist/esm/cmem/index.js +1 -0
  42. package/dist/esm/cmem/index.js.map +1 -1
  43. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +89 -0
  44. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -0
  45. package/dist/esm/cmem/react-flow/configuration/graph.js +1 -1
  46. package/dist/esm/cmem/react-flow/configuration/graph.js.map +1 -1
  47. package/dist/esm/cmem/react-flow/configuration/linking.js +3 -1
  48. package/dist/esm/cmem/react-flow/configuration/linking.js.map +1 -1
  49. package/dist/esm/cmem/react-flow/configuration/typing.js +32 -0
  50. package/dist/esm/cmem/react-flow/configuration/typing.js.map +1 -0
  51. package/dist/esm/cmem/react-flow/configuration/workflow.js +3 -1
  52. package/dist/esm/cmem/react-flow/configuration/workflow.js.map +1 -1
  53. package/dist/esm/cmem/react-flow/nodes/StickyNoteNode.js +31 -0
  54. package/dist/esm/cmem/react-flow/nodes/StickyNoteNode.js.map +1 -0
  55. package/dist/esm/common/utils/CssCustomProperties.js +154 -0
  56. package/dist/esm/common/utils/CssCustomProperties.js.map +1 -0
  57. package/dist/esm/common/utils/getColorConfiguration.js +16 -0
  58. package/dist/esm/common/utils/getColorConfiguration.js.map +1 -0
  59. package/dist/esm/components/Icon/canonicalIconNames.js +124 -114
  60. package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
  61. package/dist/esm/components/Tag/Tag.js +2 -1
  62. package/dist/esm/components/Tag/Tag.js.map +1 -1
  63. package/dist/esm/extensions/codemirror/CodeMirror.js +3 -3
  64. package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
  65. package/dist/esm/extensions/react-flow/index.js +1 -0
  66. package/dist/esm/extensions/react-flow/index.js.map +1 -1
  67. package/dist/esm/extensions/react-flow/minimap/MiniMap.js +3 -2
  68. package/dist/esm/extensions/react-flow/minimap/MiniMap.js.map +1 -1
  69. package/dist/esm/extensions/react-flow/minimap/utils.js +10 -5
  70. package/dist/esm/extensions/react-flow/minimap/utils.js.map +1 -1
  71. package/dist/esm/extensions/react-flow/nodes/NodeContent.js +76 -27
  72. package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
  73. package/dist/esm/extensions/react-flow/nodes/NodeContentExtension.js +26 -6
  74. package/dist/esm/extensions/react-flow/nodes/NodeContentExtension.js.map +1 -1
  75. package/dist/esm/extensions/react-flow/nodes/nodeUtils.js +44 -0
  76. package/dist/esm/extensions/react-flow/nodes/nodeUtils.js.map +1 -0
  77. package/dist/esm/index.js +1 -1
  78. package/dist/esm/index.js.map +1 -1
  79. package/dist/esm/legacy-replacements/Tabs/Tabs.js +1 -1
  80. package/dist/esm/legacy-replacements/Tabs/Tabs.js.map +1 -1
  81. package/dist/esm/legacy-replacements/TextField/TextField.js +2 -5
  82. package/dist/esm/legacy-replacements/TextField/TextField.js.map +1 -1
  83. package/dist/types/cmem/index.d.ts +1 -0
  84. package/dist/types/cmem/react-flow/StickyNoteModal/StickyNoteModal.d.ts +26 -0
  85. package/dist/types/cmem/react-flow/configuration/graph.d.ts +3 -8
  86. package/dist/types/cmem/react-flow/configuration/linking.d.ts +3 -9
  87. package/dist/types/cmem/react-flow/configuration/typing.d.ts +28 -0
  88. package/dist/types/cmem/react-flow/configuration/workflow.d.ts +3 -9
  89. package/dist/types/cmem/react-flow/nodes/StickyNoteNode.d.ts +3 -0
  90. package/dist/types/common/utils/CssCustomProperties.d.ts +28 -0
  91. package/dist/types/common/utils/getColorConfiguration.d.ts +8 -0
  92. package/dist/types/components/Icon/canonicalIconNames.d.ts +1 -1
  93. package/dist/types/components/Tag/Tag.d.ts +5 -1
  94. package/dist/types/extensions/codemirror/CodeMirror.d.ts +5 -1
  95. package/dist/types/extensions/react-flow/index.d.ts +1 -0
  96. package/dist/types/extensions/react-flow/minimap/MiniMap.d.ts +1 -1
  97. package/dist/types/extensions/react-flow/minimap/utils.d.ts +1 -0
  98. package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +17 -1
  99. package/dist/types/extensions/react-flow/nodes/NodeContentExtension.d.ts +2 -2
  100. package/dist/types/extensions/react-flow/nodes/nodeUtils.d.ts +14 -0
  101. package/dist/types/index.d.ts +1 -1
  102. package/dist/types/legacy-replacements/Tabs/Tabs.d.ts +1 -1
  103. package/package.json +14 -13
  104. package/scripts/compile-sass.ts +9 -0
  105. package/scripts/fix-cjs-dist +5 -0
  106. package/scripts/fix-esm-dist +6 -0
  107. package/scripts/sassConfig.js +13 -0
  108. package/src/_shame.scss +17 -0
  109. package/src/cmem/index.ts +1 -0
  110. package/src/cmem/markdown/markdown.scss +1 -1
  111. package/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx +134 -0
  112. package/src/cmem/react-flow/_index.scss +1 -1
  113. package/src/cmem/react-flow/_minimap.scss +6 -2
  114. package/src/cmem/react-flow/configuration/graph.ts +3 -5
  115. package/src/cmem/react-flow/configuration/linking.ts +5 -6
  116. package/src/cmem/react-flow/configuration/typing.ts +30 -0
  117. package/src/cmem/react-flow/configuration/workflow.ts +5 -5
  118. package/src/cmem/react-flow/nodes/StickyNoteNode.tsx +13 -0
  119. package/src/cmem/react-flow/{_nodes.scss → nodes/_colors.scss} +0 -0
  120. package/src/cmem/react-flow/nodes/_index.scss +2 -0
  121. package/src/cmem/react-flow/nodes/_stickynote.scss +72 -0
  122. package/src/common/utils/CssCustomProperties.ts +2 -2
  123. package/src/common/utils/getColorConfiguration.ts +1 -2
  124. package/src/components/Accordion/accordion.scss +11 -11
  125. package/src/components/Application/_header.scss +4 -3
  126. package/src/components/Button/button.scss +43 -6
  127. package/src/components/Card/card.scss +5 -5
  128. package/src/components/ContextOverlay/ContextMenu.stories.tsx +4 -1
  129. package/src/components/ContextOverlay/contextoverlay.scss +14 -2
  130. package/src/components/Dialog/dialog.scss +10 -8
  131. package/src/components/Form/form.scss +6 -6
  132. package/src/components/Icon/canonicalIconNames.tsx +134 -121
  133. package/src/components/Icon/icon.scss +1 -1
  134. package/src/components/Label/label.scss +2 -2
  135. package/src/components/Menu/menu.scss +6 -6
  136. package/src/components/Notification/notification.scss +3 -1
  137. package/src/components/OverviewItem/overviewitem.scss +8 -8
  138. package/src/components/PropertyValuePair/propertyvalue.scss +9 -7
  139. package/src/components/Separation/separation.scss +6 -6
  140. package/src/components/SimpleTable/simpletable.scss +5 -5
  141. package/src/components/Tabs/tabs.scss +2 -2
  142. package/src/components/Tag/Tag.tsx +6 -0
  143. package/src/components/Tag/tag.scss +36 -11
  144. package/src/components/TextField/textfield.scss +6 -4
  145. package/src/components/Tooltip/tooltip.scss +3 -3
  146. package/src/components/Typography/typography.scss +4 -4
  147. package/src/configuration/_variables.scss +11 -9
  148. package/src/extensions/codemirror/CodeMirror.tsx +9 -4
  149. package/src/extensions/react-flow/edges/_edges.scss +3 -3
  150. package/src/extensions/react-flow/handles/_handles.scss +13 -13
  151. package/src/extensions/react-flow/index.ts +1 -0
  152. package/src/extensions/react-flow/minimap/MiniMap.tsx +16 -1
  153. package/src/extensions/react-flow/minimap/_minimap.scss +6 -6
  154. package/src/extensions/react-flow/minimap/utils.ts +8 -3
  155. package/src/extensions/react-flow/nodes/NodeContent.tsx +253 -166
  156. package/src/extensions/react-flow/nodes/NodeContentExtension.tsx +17 -11
  157. package/src/extensions/react-flow/nodes/_nodes.scss +44 -12
  158. package/src/extensions/react-flow/nodes/nodeUtils.tsx +53 -0
  159. package/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +24 -13
  160. package/src/extensions/react-flow/nodes/stories/NodeContentExtension.stories.tsx +39 -47
  161. package/src/includes/blueprintjs/_variables.scss +3 -1
  162. package/src/includes/carbon-components/_variables.scss +7 -5
  163. package/src/index.ts +1 -1
  164. package/src/legacy-replacements/Tabs/Tabs.tsx +3 -1
  165. package/src/legacy-replacements/TextField/TextField.tsx +7 -5
@@ -1,13 +1,12 @@
1
1
  import React from "react";
2
- import {
3
- Position
4
- } from "react-flow-renderer";
2
+ import { Position, useStoreState } from "react-flow-renderer";
5
3
  import { Icon, Tooltip } from "../../../index";
6
4
  import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
7
- import {ValidIconName} from "../../../components/Icon/canonicalIconNames";
5
+ import { ValidIconName } from "../../../components/Icon/canonicalIconNames";
8
6
  import { HandleDefault, HandleProps } from "./../handles/HandleDefault";
9
7
  import { NodeProps } from "./NodeDefault";
10
8
  import { NodeContentExtensionProps } from "./NodeContentExtension";
9
+ import { Resizable } from "re-resizable";
11
10
 
12
11
  export type HighlightingState = "success" | "warning" | "danger" | "match" | "altmatch";
13
12
 
@@ -15,6 +14,11 @@ export interface IHandleProps extends HandleProps {
15
14
  category?: "configuration";
16
15
  }
17
16
 
17
+ export type NodeDimensions = {
18
+ width: number;
19
+ height: number;
20
+ };
21
+
18
22
  interface NodeContentData<CONTENT_PROPS = any> {
19
23
  /**
20
24
  * Name of icon that should be displayed before the node label.
@@ -37,9 +41,15 @@ interface NodeContentData<CONTENT_PROPS = any> {
37
41
  * Content extension, displayed at the bottom side of a node.
38
42
  */
39
43
  contentExtension?: React.ReactElement<NodeContentExtensionProps>;
44
+ /**
45
+ * If submitted then the node will display footer element.
46
+ */
47
+ footerContent?: React.ReactNode;
40
48
  }
41
49
 
42
- export interface NodeContentProps<NODE_DATA, NODE_CONTENT_PROPS = any> extends NodeContentData, React.HTMLAttributes<HTMLDivElement> {
50
+ export interface NodeContentProps<NODE_DATA, NODE_CONTENT_PROPS = any>
51
+ extends NodeContentData,
52
+ React.HTMLAttributes<HTMLDivElement> {
43
53
  /**
44
54
  * Size of the node.
45
55
  * If `minimalShape` is not set to `none`then the configured size definition is only used for the selected node state.
@@ -67,7 +77,10 @@ export interface NodeContentProps<NODE_DATA, NODE_CONTENT_PROPS = any> extends N
67
77
  /**
68
78
  * Set of defined buttons and icons that can be displayed.
69
79
  */
70
- executionButtons?: (adjustedContentProps: Partial<NODE_CONTENT_PROPS>, setAdjustedContentProps: React.Dispatch<React.SetStateAction<Partial<NODE_CONTENT_PROPS>>>) => React.ReactElement<NODE_CONTENT_PROPS>;
80
+ executionButtons?: (
81
+ adjustedContentProps: Partial<NODE_CONTENT_PROPS>,
82
+ setAdjustedContentProps: React.Dispatch<React.SetStateAction<Partial<NODE_CONTENT_PROPS>>>
83
+ ) => React.ReactElement<NODE_CONTENT_PROPS>;
71
84
  /**
72
85
  * Can be used for permanent action button or context menu.
73
86
  * It is displayed at the node header right to the label.
@@ -98,7 +111,7 @@ export interface NodeContentProps<NODE_DATA, NODE_CONTENT_PROPS = any> extends N
98
111
  /**
99
112
  * The node is displayed with some animated shadow for highlighting purposes.
100
113
  */
101
- animated?:boolean;
114
+ animated?: boolean;
102
115
 
103
116
  /** Additional data stored in the node. */
104
117
  businessData?: NODE_DATA;
@@ -130,19 +143,24 @@ export interface NodeContentProps<NODE_DATA, NODE_CONTENT_PROPS = any> extends N
130
143
  * If this is allowed scrolling inside a node is not possible.
131
144
  */
132
145
  letPassWheelEvents?: boolean;
146
+ /**
147
+ * When set to true, allows nodes to be resized by dragging edges and sides
148
+ */
149
+ onNodeResize?: (data: NodeDimensions) => void;
150
+ /**
151
+ * width and height dimensions of the node (Optional)
152
+ */
153
+ nodeDimensions?: NodeDimensions;
133
154
  }
134
155
 
135
156
  interface MemoHandlerProps extends HandleProps {
136
- posdirection: string;
137
- style: {
138
- [key:string]: string | undefined
139
- }
157
+ posdirection: string;
158
+ style: {
159
+ [key: string]: string | undefined;
160
+ };
140
161
  }
141
162
 
142
- const defaultHandles = [
143
- { type: "target" },
144
- { type: "source" },
145
- ] as IHandleProps[];
163
+ const defaultHandles = [{ type: "target" }, { type: "source" }] as IHandleProps[];
146
164
 
147
165
  const getDefaultMinimalTooltipData = (node: any) => {
148
166
  return {
@@ -150,56 +168,56 @@ const getDefaultMinimalTooltipData = (node: any) => {
150
168
  content: node.data?.content,
151
169
  iconName: node.data?.iconName,
152
170
  depiction: node.data?.depiction,
153
- }
154
- }
171
+ };
172
+ };
155
173
 
156
174
  const addHandles = (handles: any, position: any, posDirection: any, isConnectable: any, nodeStyle: any) => {
157
175
  return handles[position].map((handle: any, idx: any) => {
158
- const {
159
- className,
160
- style = {},
161
- category,
162
- } = handle;
163
- const styleAdditions : {[key: string]: string}= {
164
- color: nodeStyle.borderColor ?? undefined
165
- }
166
- styleAdditions[posDirection] = (100 / (handles[position].length + 1) * (idx + 1)) + "%";
176
+ const { className, style = {}, category } = handle;
177
+ const styleAdditions: { [key: string]: string } = {
178
+ color: nodeStyle.borderColor ?? undefined,
179
+ };
180
+ styleAdditions[posDirection] = (100 / (handles[position].length + 1)) * (idx + 1) + "%";
167
181
  const handleProperties = {
168
182
  ...handle,
169
183
  ...{
170
184
  position: handle.position ?? position,
171
- style: { ...style, ...styleAdditions},
185
+ style: { ...style, ...styleAdditions },
172
186
  posdirection: posDirection,
173
187
  isConnectable: typeof handle.isConnectable !== "undefined" ? handle.isConnectable : isConnectable,
174
- className: !!category ? (className?className+" ":"") + gethighlightedStateClasses(category, `${eccgui}-graphviz__handle`) : className,
175
- }
188
+ className: !!category
189
+ ? (className ? className + " " : "") +
190
+ gethighlightedStateClasses(category, `${eccgui}-graphviz__handle`)
191
+ : className,
192
+ },
176
193
  };
177
- return (
178
- <MemoHandler {...handleProperties} key={"handle" + idx} />
179
- );
194
+ return <MemoHandler {...handleProperties} key={"handle" + idx} />;
180
195
  });
181
- }
196
+ };
182
197
 
183
198
  const imgWithTooltip = (imgEl: any, tooltipText: any) => {
184
199
  if (!!tooltipText) {
185
- return <Tooltip content={tooltipText}><span>{imgEl}</span></Tooltip>;
200
+ return (
201
+ <Tooltip content={tooltipText}>
202
+ <span>{imgEl}</span>
203
+ </Tooltip>
204
+ );
186
205
  }
187
206
 
188
207
  return imgEl;
189
- }
208
+ };
190
209
 
191
210
  export const gethighlightedStateClasses = (state: any, baseClassName: any) => {
192
211
  let hightlights = typeof state === "string" ? [state] : state;
193
212
  //@ts-ignore
194
- return hightlights.map(item => `${baseClassName}--highlight-${item}`).join(' ');
195
- }
213
+ return hightlights.map((item) => `${baseClassName}--highlight-${item}`).join(" ");
214
+ };
196
215
 
197
216
  const MemoHandler = React.memo(
198
217
  (props: MemoHandlerProps) => <HandleDefault {...props} />,
199
218
  (prev, next) => {
200
- const styleHasChanged =
201
- prev.style[prev.posdirection] === next.style[next.posdirection];
202
- return styleHasChanged;
219
+ const styleHasChanged = prev.style[prev.posdirection] === next.style[next.posdirection];
220
+ return styleHasChanged;
203
221
  }
204
222
  );
205
223
 
@@ -207,130 +225,199 @@ const MemoHandler = React.memo(
207
225
  * The `NodeContent` element manages the main view of how a node is displaying which content.
208
226
  * This element cannot be used directly, all properties must be routed through the `data` property of an `elements` property item inside the `ReactFlow` container.
209
227
  */
210
- export function NodeContent <CONTENT_PROPS = any>({
211
- iconName,
212
- depiction,
213
- typeLabel,
214
- label,
215
- showExecutionButtons = true,
216
- executionButtons,
217
- menuButtons,
218
- content,
219
- contentExtension,
220
- size = "small",
221
- minimalShape = "circular",
222
- highlightedState,
223
- handles = defaultHandles,
224
- adaptHeightForHandleMinCount,
225
- adaptSizeIncrement = 15,
226
- getMinimalTooltipData = getDefaultMinimalTooltipData,
227
- style = {},
228
- showUnconnectableHandles = false,
229
- animated = false,
230
- // forwarded props
231
- targetPosition = Position.Left,
232
- sourcePosition = Position.Right,
233
- isConnectable = true,
234
- selected,
235
- letPassWheelEvents = false,
236
- // businessData is just being ignored
237
- businessData,
238
- // other props for DOM element
239
- ...otherProps
240
- }: NodeContentProps<any>) {
241
- const [adjustedContentProps, setAdjustedContentProps] = React.useState<Partial<CONTENT_PROPS>>({})
242
- const handleStack: { [key: string]: IHandleProps[] } = {};
243
- handleStack[Position.Top] = [] as IHandleProps[];
244
- handleStack[Position.Right] = [] as IHandleProps[];
245
- handleStack[Position.Bottom] = [] as IHandleProps[];
246
- handleStack[Position.Left] = [] as IHandleProps[];
247
- if (handles.length > 0) {
248
- handles.forEach(handle => {
249
- if (!!handle.position) {
250
- handleStack[handle.position].push(handle);
251
- }
252
- else if (handle.category === "configuration") {
253
- handleStack[Position.Top].push(handle);
254
- }
255
- else {
256
- if (handle.type === "target") {
257
- handleStack[targetPosition].push(handle);
258
- }
259
- if (handle.type === "source") {
260
- handleStack[sourcePosition].push(handle);
261
- }
262
- }
263
- });
264
- }
265
- const styleExpandDimensions: { [key: string]: string | number } = {};
266
- if (
267
- typeof adaptHeightForHandleMinCount !== "undefined" &&
268
- (minimalShape === "none" || !!selected) &&
269
- adaptSizeIncrement && (
270
- handleStack[Position.Left].length >= adaptHeightForHandleMinCount ||
271
- handleStack[Position.Right].length >= adaptHeightForHandleMinCount
272
- )
273
- ) {
274
- const minHeightLeft = handleStack[Position.Left].length * adaptSizeIncrement;
275
- const minHeightRight = handleStack[Position.Right].length * adaptSizeIncrement;
276
- styleExpandDimensions["minHeight"] = Math.max(minHeightLeft, minHeightRight);
277
- }
278
- return (
279
- <>
280
- <section
281
- {...otherProps}
282
- style={{...style, ...styleExpandDimensions}}
283
- className={
284
- `${eccgui}-graphviz__node` +
285
- ` ${eccgui}-graphviz__node--${size}` +
286
- ` ${eccgui}-graphviz__node--minimal-${minimalShape}` +
287
- (!!highlightedState ? " " + gethighlightedStateClasses(highlightedState, `${eccgui}-graphviz__node`) : "") +
288
- (animated ? ` ${eccgui}-graphviz__node--animated` : "") +
289
- (showUnconnectableHandles === false ? ` ${eccgui}-graphviz__node--hidehandles` : "") +
290
- (letPassWheelEvents === false ? ` nowheel` : "")
291
- }
292
- >
293
- <header className={`${eccgui}-graphviz__node__header`}>
294
- {(!!iconName || !!depiction) && (
295
- <span
296
- className={`${eccgui}-graphviz__node__header-depiction`}
297
- >
298
- {!!depiction && imgWithTooltip(<img src={depiction} alt="" />, (minimalShape === "none" || selected) ? typeLabel : undefined)}
299
- {(!!iconName && !depiction) && <Icon name={iconName} tooltipText={(minimalShape === "none" || selected) ? typeLabel : undefined} />}
300
- </span>
301
- )}
302
- <span
303
- className={`${eccgui}-graphviz__node__header-label`}
304
- title={label}
305
- >
306
- {label}
307
- </span>
308
- {(menuButtons || (showExecutionButtons && executionButtons)) && (
309
- <span
310
- className={`${eccgui}-graphviz__node__header-menu`}
311
- >
312
- {(showExecutionButtons && typeof executionButtons === "function") ? executionButtons(adjustedContentProps, setAdjustedContentProps) : null}
313
- {menuButtons??null}
314
- </span>
315
- )}
316
- </header>
317
- {content && (
318
- <div className={`${eccgui}-graphviz__node__content`}>
319
- {typeof content === "function" ? content(adjustedContentProps) : content}
320
- </div>
228
+ export function NodeContent<CONTENT_PROPS = any>({
229
+ iconName,
230
+ depiction,
231
+ typeLabel,
232
+ label,
233
+ showExecutionButtons = true,
234
+ executionButtons,
235
+ menuButtons,
236
+ content,
237
+ contentExtension,
238
+ footerContent,
239
+ size = "small",
240
+ minimalShape = "circular",
241
+ highlightedState,
242
+ handles = defaultHandles,
243
+ adaptHeightForHandleMinCount,
244
+ adaptSizeIncrement = 15,
245
+ getMinimalTooltipData = getDefaultMinimalTooltipData,
246
+ style = {},
247
+ showUnconnectableHandles = false,
248
+ animated = false,
249
+ onNodeResize,
250
+ nodeDimensions,
251
+ // forwarded props
252
+ targetPosition = Position.Left,
253
+ sourcePosition = Position.Right,
254
+ isConnectable = true,
255
+ selected,
256
+ letPassWheelEvents = false,
257
+ // businessData is just being ignored
258
+ businessData,
259
+ // other props for DOM element
260
+ ...otherProps
261
+ }: NodeContentProps<any>) {
262
+ const [width, setWidth] = React.useState<number>(nodeDimensions?.width ?? 0);
263
+ const [height, setHeight] = React.useState<number>(nodeDimensions?.height ?? 0);
264
+ const [, , zoom] = useStoreState((state) => state.transform);
265
+ const [adjustedContentProps, setAdjustedContentProps] = React.useState<Partial<CONTENT_PROPS>>({});
266
+ const nodeContentRef = React.useRef<any>();
267
+ const handleStack: { [key: string]: IHandleProps[] } = {};
268
+ handleStack[Position.Top] = [] as IHandleProps[];
269
+ handleStack[Position.Right] = [] as IHandleProps[];
270
+ handleStack[Position.Bottom] = [] as IHandleProps[];
271
+ handleStack[Position.Left] = [] as IHandleProps[];
272
+
273
+ // initial dimension before resize
274
+ React.useEffect(() => {
275
+ if (!!onNodeResize && minimalShape === "none") {
276
+ if (!nodeDimensions) {
277
+ setWidth(nodeContentRef.current.offsetWidth);
278
+ setHeight(nodeContentRef.current.offsetHeight);
279
+ onNodeResize({
280
+ height: nodeContentRef.current.offsetHeight,
281
+ width: nodeContentRef.current.offsetWidth,
282
+ });
283
+ }
284
+ nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable";
285
+ }
286
+ }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions]);
287
+
288
+ //update node dimensions when resized
289
+ React.useEffect(() => {
290
+ if (nodeDimensions) {
291
+ setWidth(nodeDimensions.width);
292
+ setHeight(nodeDimensions.height);
293
+ }
294
+ }, [nodeDimensions]);
295
+
296
+ if (handles.length > 0) {
297
+ handles.forEach((handle) => {
298
+ if (!!handle.position) {
299
+ handleStack[handle.position].push(handle);
300
+ } else if (handle.category === "configuration") {
301
+ handleStack[Position.Top].push(handle);
302
+ } else {
303
+ if (handle.type === "target") {
304
+ handleStack[targetPosition].push(handle);
305
+ }
306
+ if (handle.type === "source") {
307
+ handleStack[sourcePosition].push(handle);
308
+ }
309
+ }
310
+ });
311
+ }
312
+ const styleExpandDimensions: { [key: string]: string | number } = {};
313
+ if (
314
+ typeof adaptHeightForHandleMinCount !== "undefined" &&
315
+ (minimalShape === "none" || !!selected) &&
316
+ adaptSizeIncrement &&
317
+ (handleStack[Position.Left].length >= adaptHeightForHandleMinCount ||
318
+ handleStack[Position.Right].length >= adaptHeightForHandleMinCount)
319
+ ) {
320
+ const minHeightLeft = handleStack[Position.Left].length * adaptSizeIncrement;
321
+ const minHeightRight = handleStack[Position.Right].length * adaptSizeIncrement;
322
+ styleExpandDimensions["minHeight"] = Math.max(minHeightLeft, minHeightRight);
323
+ }
324
+
325
+ const resizableStyles = (!!onNodeResize === true && minimalShape === "none" && (width + height > 0)) ? { width, height } : {};
326
+ const nodeContent = (
327
+ <>
328
+ <section
329
+ ref={nodeContentRef}
330
+ {...otherProps}
331
+ style={{ ...style, ...styleExpandDimensions, ...resizableStyles }}
332
+ className={
333
+ `${eccgui}-graphviz__node` +
334
+ ` ${eccgui}-graphviz__node--${size}` +
335
+ ` ${eccgui}-graphviz__node--minimal-${minimalShape}` +
336
+ (!!highlightedState
337
+ ? " " + gethighlightedStateClasses(highlightedState, `${eccgui}-graphviz__node`)
338
+ : "") +
339
+ (animated ? ` ${eccgui}-graphviz__node--animated` : "") +
340
+ (showUnconnectableHandles === false ? ` ${eccgui}-graphviz__node--hidehandles` : "") +
341
+ (letPassWheelEvents === false ? ` nowheel` : "")
342
+ }
343
+ >
344
+ <header className={`${eccgui}-graphviz__node__header`}>
345
+ {(!!iconName || !!depiction) && (
346
+ <span className={`${eccgui}-graphviz__node__header-depiction`}>
347
+ {!!depiction &&
348
+ imgWithTooltip(
349
+ <img src={depiction} alt="" />,
350
+ minimalShape === "none" || selected ? typeLabel : undefined
351
+ )}
352
+ {!!iconName && !depiction && (
353
+ <Icon
354
+ name={iconName}
355
+ tooltipText={minimalShape === "none" || selected ? typeLabel : undefined}
356
+ />
357
+ )}
358
+ </span>
359
+ )}
360
+ <span className={`${eccgui}-graphviz__node__header-label`} title={label}>
361
+ {label}
362
+ </span>
363
+ {(menuButtons || (showExecutionButtons && executionButtons)) && (
364
+ <span className={`${eccgui}-graphviz__node__header-menu`}>
365
+ {showExecutionButtons && typeof executionButtons === "function"
366
+ ? executionButtons(adjustedContentProps, setAdjustedContentProps)
367
+ : null}
368
+ {menuButtons ?? null}
369
+ </span>
370
+ )}
371
+ </header>
372
+ {content && (
373
+ <div className={`${eccgui}-graphviz__node__content`}>
374
+ {typeof content === "function" ? content(adjustedContentProps) : content}
375
+ </div>
376
+ )}
377
+ {contentExtension}
378
+ {footerContent && (
379
+ <footer className={`${eccgui}-graphviz__node__footer`}>
380
+ { footerContent }
381
+ </footer>
321
382
  )}
322
- <div className={`${eccgui}-graphviz__node__footer`}>
323
- </div>
324
- {contentExtension}
325
- </section>
326
- {!!handles && (
327
- <>
328
- { addHandles(handleStack, Position.Top, "left", isConnectable, style) }
329
- { addHandles(handleStack, Position.Right, "top", isConnectable, style) }
330
- { addHandles(handleStack, Position.Bottom, "left", isConnectable, style) }
331
- { addHandles(handleStack, Position.Left, "top", isConnectable, style) }
332
- </>
333
- )}
334
- </>
335
- );
336
- }
383
+ </section>
384
+ {!!handles && (
385
+ <>
386
+ {addHandles(handleStack, Position.Top, "left", isConnectable, style)}
387
+ {addHandles(handleStack, Position.Right, "top", isConnectable, style)}
388
+ {addHandles(handleStack, Position.Bottom, "left", isConnectable, style)}
389
+ {addHandles(handleStack, Position.Left, "top", isConnectable, style)}
390
+ </>
391
+ )}
392
+ </>
393
+ );
394
+
395
+ const resizableNode = () => (
396
+ <Resizable
397
+ className={`${eccgui}-graphviz__node__resizer`}
398
+ handleWrapperClass={`${eccgui}-graphviz__node__resizer--cursorhandles nodrag`}
399
+ size={{ height, width }}
400
+ enable={{ bottomRight: true }}
401
+ scale={zoom}
402
+ onResize={(_0, _1, _2, d) => {
403
+ if (nodeContentRef.current) {
404
+ nodeContentRef.current.style.width = width + d.width + "px";
405
+ nodeContentRef.current.style.height = height + d.height + "px";
406
+ }
407
+ }}
408
+ onResizeStop={(_0, _1, _2, d) => {
409
+ setWidth(width + d.width);
410
+ setHeight(height + d.height);
411
+ onNodeResize &&
412
+ onNodeResize({
413
+ height: height + d.height,
414
+ width: width + d.width,
415
+ });
416
+ }}
417
+ >
418
+ {nodeContent}
419
+ </Resizable>
420
+ );
421
+
422
+ return (!!onNodeResize && minimalShape === "none") ? resizableNode() : nodeContent;
423
+ }
@@ -16,7 +16,7 @@ export interface NodeContentExtensionProps extends React.HTMLAttributes<HTMLDivE
16
16
  * Click handler to manage the expanded state from outside the the element.
17
17
  * This state is not managed automatically by the element itself.
18
18
  */
19
- onToggle?: (event: React.MouseEvent<HTMLElement>, isExpanded: boolean) => void;
19
+ setExpanded?: (event: React.MouseEvent<HTMLElement>, isCurrentlyExpanded: boolean) => boolean;
20
20
  /**
21
21
  * Single element or aray of `IconButton` and `Button` elements.
22
22
  * They will be displayed beside the closing button under the element content body.
@@ -39,7 +39,7 @@ export const NodeContentExtension = ({
39
39
  children,
40
40
  slideOutOfNode = false,
41
41
  isExpanded = false,
42
- onToggle = undefined,
42
+ setExpanded = undefined,
43
43
  actionButtons,
44
44
  tooltipExpand = "Show more",
45
45
  tooltipReduce = "Show less",
@@ -47,8 +47,12 @@ export const NodeContentExtension = ({
47
47
  ...otherProps
48
48
  }: NodeContentExtensionProps) => {
49
49
 
50
- // always expand element if there is no handler to manage it
51
- const expanded = onToggle ? isExpanded : true;
50
+ // display always exapanded if there is no handler to control it
51
+ const [expanded, expand] = React.useState<boolean>(setExpanded ? isExpanded : true);
52
+ const onToggle = (event: React.MouseEvent<HTMLElement>, isCurrentlyExpanded: boolean) => {
53
+ const willBeExpanded = setExpanded ? setExpanded(event, isCurrentlyExpanded) : isCurrentlyExpanded;
54
+ expand(willBeExpanded);
55
+ }
52
56
 
53
57
  return (
54
58
  <div
@@ -75,14 +79,16 @@ export const NodeContentExtension = ({
75
79
  <div className={`${eccgui}-graphviz__node__extension-body`}>
76
80
  {children}
77
81
  </div>
78
- {(!!actionButtons || !!onToggle) && (
82
+ {(!!actionButtons || !!setExpanded) && (
79
83
  <div className={`${eccgui}-graphviz__node__extension-actions`}>
80
- <IconButton
81
- className={`${eccgui}-graphviz__node__extension-reducebutton`}
82
- name="toggler-showless"
83
- text={tooltipReduce}
84
- onClick={onToggle ? (e) => { onToggle(e, expanded); } : undefined}
85
- />
84
+ {!!setExpanded && (
85
+ <IconButton
86
+ className={`${eccgui}-graphviz__node__extension-reducebutton`}
87
+ name="toggler-showless"
88
+ text={tooltipReduce}
89
+ onClick={(e) => { onToggle(e, expanded); }}
90
+ />
91
+ )}
86
92
  {actionButtons}
87
93
  </div>
88
94
  )}