@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.
- package/CHANGELOG.md +95 -0
- package/dist/cjs/cmem/ActivityControl/ActivityControlWidget.js +7 -2
- package/dist/cjs/cmem/ActivityControl/ActivityControlWidget.js.map +1 -1
- package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +3 -3
- package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js +13 -3
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js +3 -3
- package/dist/cjs/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js +4 -2
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/cjs/components/Card/CardActions.js +2 -1
- package/dist/cjs/components/Card/CardActions.js.map +1 -1
- package/dist/cjs/components/Card/CardContent.js +4 -6
- package/dist/cjs/components/Card/CardContent.js.map +1 -1
- package/dist/cjs/components/ContentGroup/ContentGroup.js +95 -0
- package/dist/cjs/components/ContentGroup/ContentGroup.js.map +1 -0
- package/dist/cjs/components/Dialog/SimpleDialog.js +3 -3
- package/dist/cjs/components/Dialog/SimpleDialog.js.map +1 -1
- package/dist/cjs/components/Icon/canonicalIconNames.js +12 -0
- package/dist/cjs/components/Icon/canonicalIconNames.js.map +1 -1
- package/dist/cjs/components/Label/Label.js +8 -3
- package/dist/cjs/components/Label/Label.js.map +1 -1
- package/dist/cjs/components/Menu/MenuItem.js +3 -2
- package/dist/cjs/components/Menu/MenuItem.js.map +1 -1
- package/dist/cjs/components/MultiSelect/MultiSelect.js +1 -0
- package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/cjs/components/OverviewItem/OverviewItem.js +5 -2
- package/dist/cjs/components/OverviewItem/OverviewItem.js.map +1 -1
- package/dist/cjs/components/OverviewItem/OverviewItemList.js +2 -2
- package/dist/cjs/components/OverviewItem/OverviewItemList.js.map +1 -1
- package/dist/cjs/components/Switch/Switch.js +6 -4
- package/dist/cjs/components/Switch/Switch.js.map +1 -1
- package/dist/cjs/components/Tag/TagList.js +1 -1
- package/dist/cjs/components/Tag/TagList.js.map +1 -1
- package/dist/cjs/components/TextField/SearchField.js +19 -2
- package/dist/cjs/components/TextField/SearchField.js.map +1 -1
- package/dist/cjs/components/Typography/OverflowText.js +1 -1
- package/dist/cjs/components/Typography/OverflowText.js.map +1 -1
- package/dist/cjs/components/index.js +1 -0
- package/dist/cjs/components/index.js.map +1 -1
- package/dist/cjs/extensions/codemirror/CodeMirror.js +93 -11
- package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
- package/dist/cjs/extensions/codemirror/debouncedLinter.js +18 -0
- package/dist/cjs/extensions/codemirror/debouncedLinter.js.map +1 -0
- package/dist/cjs/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js +23 -14
- package/dist/cjs/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js.map +1 -1
- package/dist/cjs/extensions/codemirror/linters/jsLinter.js +36 -0
- package/dist/cjs/extensions/codemirror/linters/jsLinter.js.map +1 -0
- package/dist/cjs/extensions/codemirror/linters/turtleLinter.js +81 -0
- package/dist/cjs/extensions/codemirror/linters/turtleLinter.js.map +1 -0
- package/dist/cjs/extensions/codemirror/tests/codemirrorTestHelper.js +4 -1
- package/dist/cjs/extensions/codemirror/tests/codemirrorTestHelper.js.map +1 -1
- package/dist/cjs/extensions/codemirror/toolbars/commands/markdown.command.js +278 -0
- package/dist/cjs/extensions/codemirror/toolbars/commands/markdown.command.js.map +1 -0
- package/dist/cjs/extensions/codemirror/toolbars/markdown.toolbar.js +47 -0
- package/dist/cjs/extensions/codemirror/toolbars/markdown.toolbar.js.map +1 -0
- package/dist/cjs/extensions/codemirror/types.js +3 -0
- package/dist/cjs/extensions/codemirror/types.js.map +1 -0
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js +140 -41
- package/dist/cjs/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/cjs/extensions/react-flow/nodes/nodeUtils.js +5 -6
- package/dist/cjs/extensions/react-flow/nodes/nodeUtils.js.map +1 -1
- package/dist/esm/cmem/ActivityControl/ActivityControlWidget.js +7 -2
- package/dist/esm/cmem/ActivityControl/ActivityControlWidget.js.map +1 -1
- package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +4 -4
- package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js +13 -3
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js +14 -3
- package/dist/esm/components/AutoSuggestion/ExtendedCodeEditor.js.map +1 -1
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js +4 -3
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/esm/components/Card/CardActions.js +2 -1
- package/dist/esm/components/Card/CardActions.js.map +1 -1
- package/dist/esm/components/Card/CardContent.js +4 -5
- package/dist/esm/components/Card/CardContent.js.map +1 -1
- package/dist/esm/components/ContentGroup/ContentGroup.js +100 -0
- package/dist/esm/components/ContentGroup/ContentGroup.js.map +1 -0
- package/dist/esm/components/Dialog/SimpleDialog.js +4 -4
- package/dist/esm/components/Dialog/SimpleDialog.js.map +1 -1
- package/dist/esm/components/Icon/canonicalIconNames.js +12 -0
- package/dist/esm/components/Icon/canonicalIconNames.js.map +1 -1
- package/dist/esm/components/Label/Label.js +8 -3
- package/dist/esm/components/Label/Label.js.map +1 -1
- package/dist/esm/components/Menu/MenuItem.js +3 -2
- package/dist/esm/components/Menu/MenuItem.js.map +1 -1
- package/dist/esm/components/MultiSelect/MultiSelect.js +1 -0
- package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/esm/components/OverviewItem/OverviewItem.js +5 -2
- package/dist/esm/components/OverviewItem/OverviewItem.js.map +1 -1
- package/dist/esm/components/OverviewItem/OverviewItemList.js +2 -2
- package/dist/esm/components/OverviewItem/OverviewItemList.js.map +1 -1
- package/dist/esm/components/Switch/Switch.js +7 -5
- package/dist/esm/components/Switch/Switch.js.map +1 -1
- package/dist/esm/components/Tag/TagList.js +1 -1
- package/dist/esm/components/Tag/TagList.js.map +1 -1
- package/dist/esm/components/TextField/SearchField.js +35 -2
- package/dist/esm/components/TextField/SearchField.js.map +1 -1
- package/dist/esm/components/Typography/OverflowText.js +1 -1
- package/dist/esm/components/Typography/OverflowText.js.map +1 -1
- package/dist/esm/components/index.js +1 -0
- package/dist/esm/components/index.js.map +1 -1
- package/dist/esm/extensions/codemirror/CodeMirror.js +94 -13
- package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
- package/dist/esm/extensions/codemirror/debouncedLinter.js +15 -0
- package/dist/esm/extensions/codemirror/debouncedLinter.js.map +1 -0
- package/dist/esm/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js +20 -11
- package/dist/esm/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.js.map +1 -1
- package/dist/esm/extensions/codemirror/linters/jsLinter.js +32 -0
- package/dist/esm/extensions/codemirror/linters/jsLinter.js.map +1 -0
- package/dist/esm/extensions/codemirror/linters/turtleLinter.js +77 -0
- package/dist/esm/extensions/codemirror/linters/turtleLinter.js.map +1 -0
- package/dist/esm/extensions/codemirror/tests/codemirrorTestHelper.js +4 -0
- package/dist/esm/extensions/codemirror/tests/codemirrorTestHelper.js.map +1 -1
- package/dist/esm/extensions/codemirror/toolbars/commands/markdown.command.js +283 -0
- package/dist/esm/extensions/codemirror/toolbars/commands/markdown.command.js.map +1 -0
- package/dist/esm/extensions/codemirror/toolbars/markdown.toolbar.js +41 -0
- package/dist/esm/extensions/codemirror/toolbars/markdown.toolbar.js.map +1 -0
- package/dist/esm/extensions/codemirror/types.js +2 -0
- package/dist/esm/extensions/codemirror/types.js.map +1 -0
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js +149 -48
- package/dist/esm/extensions/react-flow/nodes/NodeContent.js.map +1 -1
- package/dist/esm/extensions/react-flow/nodes/nodeUtils.js +5 -6
- package/dist/esm/extensions/react-flow/nodes/nodeUtils.js.map +1 -1
- package/dist/types/cmem/ActivityControl/ActivityControlWidget.d.ts +1 -1
- package/dist/types/cmem/react-flow/StickyNoteModal/StickyNoteModal.d.ts +5 -1
- package/dist/types/components/AutoSuggestion/ExtendedCodeEditor.d.ts +11 -6
- package/dist/types/components/Card/CardActions.d.ts +5 -1
- package/dist/types/components/Card/CardContent.d.ts +1 -2
- package/dist/types/components/ContentGroup/ContentGroup.d.ts +78 -0
- package/dist/types/components/Dialog/SimpleDialog.d.ts +4 -1
- package/dist/types/components/Icon/canonicalIconNames.d.ts +12 -0
- package/dist/types/components/Label/Label.d.ts +7 -1
- package/dist/types/components/Menu/MenuItem.d.ts +8 -1
- package/dist/types/components/OverviewItem/OverviewItem.d.ts +13 -1
- package/dist/types/components/OverviewItem/OverviewItemList.d.ts +3 -2
- package/dist/types/components/ProgressBar/ProgressBar.d.ts +2 -2
- package/dist/types/components/Structure/TitleSubsection.d.ts +9 -1
- package/dist/types/components/Switch/Switch.d.ts +3 -3
- package/dist/types/components/Tabs/Tab.d.ts +20 -4
- package/dist/types/components/TextField/SearchField.d.ts +1 -1
- package/dist/types/components/Typography/OverflowText.d.ts +23 -2
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/extensions/codemirror/CodeMirror.d.ts +32 -5
- package/dist/types/extensions/codemirror/debouncedLinter.d.ts +4 -0
- package/dist/types/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.d.ts +7 -5
- package/dist/types/extensions/codemirror/linters/jsLinter.d.ts +5 -0
- package/dist/types/extensions/codemirror/linters/turtleLinter.d.ts +5 -0
- package/dist/types/extensions/codemirror/tests/codemirrorTestHelper.d.ts +1 -0
- package/dist/types/extensions/codemirror/toolbars/commands/markdown.command.d.ts +55 -0
- package/dist/types/extensions/codemirror/toolbars/markdown.toolbar.d.ts +12 -0
- package/dist/types/extensions/codemirror/types.d.ts +5 -0
- package/dist/types/extensions/react-flow/nodes/NodeContent.d.ts +18 -4
- package/dist/types/extensions/react-flow/nodes/nodeUtils.d.ts +7 -6
- package/dist/types/extensions/react-flow/versionsupport.d.ts +1 -1
- package/package.json +59 -47
- package/src/cmem/ActivityControl/ActivityControlWidget.tsx +5 -2
- package/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx +16 -2
- package/src/cmem/react-flow/configuration/_colors-graph.scss +4 -1
- package/src/cmem/react-flow/configuration/_colors-workflow.scss +3 -0
- package/src/components/AutoSuggestion/AutoSuggestion.tsx +14 -3
- package/src/components/AutoSuggestion/ExtendedCodeEditor.tsx +29 -6
- package/src/components/AutocompleteField/AutoCompleteField.tsx +5 -3
- package/src/components/Card/CardActions.tsx +6 -0
- package/src/components/Card/CardContent.tsx +8 -4
- package/src/components/Card/card.scss +15 -0
- package/src/components/CodeAutocompleteField/CodeAutocompleteField.stories.tsx +3 -2
- package/src/components/ContentGroup/ContentGroup.stories.tsx +47 -0
- package/src/components/ContentGroup/ContentGroup.tsx +256 -0
- package/src/components/ContentGroup/_contentgroup.scss +56 -0
- package/src/components/ContextOverlay/ContextOverlay.stories.tsx +15 -4
- package/src/components/Depiction/depiction.scss +7 -0
- package/src/components/Dialog/SimpleDialog.tsx +9 -2
- package/src/components/Dialog/stories/AlertDialog.stories.tsx +5 -1
- package/src/components/Dialog/stories/Modal.stories.tsx +4 -2
- package/src/components/Dialog/stories/SimpleDialog.stories.tsx +5 -2
- package/src/components/Icon/canonicalIconNames.tsx +12 -0
- package/src/components/Label/Label.stories.tsx +2 -1
- package/src/components/Label/Label.tsx +17 -1
- package/src/components/Label/label.scss +5 -1
- package/src/components/Menu/MenuItem.tsx +27 -1
- package/src/components/Menu/menu.scss +1 -0
- package/src/components/MultiSelect/MultiSelect.tsx +1 -0
- package/src/components/OverviewItem/OverviewItem.tsx +24 -1
- package/src/components/OverviewItem/OverviewItemList.tsx +3 -2
- package/src/components/OverviewItem/overviewitem.scss +4 -1
- package/src/components/OverviewItem/stories/OverviewItem.stories.tsx +6 -12
- package/src/components/Select/Select.stories.tsx +4 -1
- package/src/components/Switch/Switch.tsx +27 -8
- package/src/components/Tag/TagList.tsx +2 -2
- package/src/components/TextField/SearchField.tsx +37 -9
- package/src/components/TextField/stories/SearchField.stories.tsx +15 -1
- package/src/components/TextField/stories/TextField.stories.tsx +2 -1
- package/src/components/TextField/textfield.scss +17 -3
- package/src/components/Typography/OverflowText.tsx +24 -3
- package/src/components/Typography/stories/OverflowText.stories.tsx +33 -0
- package/src/components/index.scss +1 -0
- package/src/components/index.ts +1 -0
- package/src/extensions/codemirror/CodeMirror.stories.tsx +19 -1
- package/src/extensions/codemirror/CodeMirror.tsx +154 -16
- package/src/extensions/codemirror/_codemirror.scss +130 -1
- package/src/extensions/codemirror/debouncedLinter.ts +26 -0
- package/src/extensions/codemirror/hooks/useCodemirrorModeExtension.hooks.ts +21 -12
- package/src/extensions/codemirror/linters/jsLinter.ts +38 -0
- package/src/extensions/codemirror/linters/turtleLinter.ts +102 -0
- package/src/extensions/codemirror/tests/codemirrorTestHelper.ts +4 -0
- package/src/extensions/codemirror/toolbars/commands/markdown.command.ts +340 -0
- package/src/extensions/codemirror/toolbars/markdown.toolbar.tsx +117 -0
- package/src/extensions/codemirror/types.ts +7 -0
- package/src/extensions/react-flow/_config.scss +1 -0
- package/src/extensions/react-flow/nodes/NodeContent.tsx +170 -52
- package/src/extensions/react-flow/nodes/_nodes.scss +71 -35
- package/src/extensions/react-flow/nodes/nodeUtils.tsx +16 -14
- 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
|
|
27
|
-
height
|
|
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
|
|
345
|
-
const
|
|
346
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
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,
|
|
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
|
-
//
|
|
435
|
+
// conditional enhancements for activated resizing
|
|
390
436
|
React.useEffect(() => {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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
|
-
},
|
|
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
|
-
|
|
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
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
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
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
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
|
|
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
|
|
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
|
|
235
|
+
// Node Resizer
|
|
204
236
|
|
|
205
|
-
.#{$eccgui}-
|
|
206
|
-
.#{$eccgui}-graphviz__node.is-
|
|
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
|
-
|
|
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 {
|
|
2
|
+
import {Node, XYPosition} from "react-flow-renderer";
|
|
3
3
|
import Color from "color";
|
|
4
|
+
import {NodeDimensions} from "./NodeContent";
|
|
4
5
|
|
|
5
|
-
|
|
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:
|
|
10
|
-
|
|
11
|
-
};
|
|
11
|
+
position: XYPosition & NodeDimensions;
|
|
12
|
+
}
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* converts a react-flow node with
|
|
15
|
-
* type = "stickynote" to
|
|
16
|
+
* type = "stickynote" to StickyNote type compatible with the backend
|
|
16
17
|
* @param node
|
|
17
|
-
* @returns {
|
|
18
|
+
* @returns {StickyNote}
|
|
18
19
|
*/
|
|
19
|
-
const transformNodeToStickyNode = (node: Node<any>):
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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:
|
|
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:
|
|
122
|
-
footerContent: { control:
|
|
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
|
-
|
|
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
|
-
|
|
140
|
-
|
|
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
|
};
|