From 61f849e140704841bc63b11c46201fe441d3ba80 Mon Sep 17 00:00:00 2001 From: arausly Date: Sun, 20 Oct 2024 23:28:00 +0100 Subject: [PATCH 01/31] added adaptation to change resize direction --- src/extensions/react-flow/nodes/NodeContent.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index ed79f808d..02d77f270 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -2,7 +2,7 @@ import React from "react"; import { Position, useStoreState as getStoreStateFlowLegacy } from "react-flow-renderer"; import { useStore as getStoreStateFlowNext } from "react-flow-renderer-lts"; import Color from "color"; -import { Resizable } from "re-resizable"; +import { Enable, Resizable } from "re-resizable"; import { intentClassName, IntentTypes } from "../../../common/Intent"; import { DepictionProps } from "../../../components/Depiction/Depiction"; @@ -222,7 +222,9 @@ export interface NodeContentProps /** * width and height dimensions of the node (Optional) */ - nodeDimensions?: NodeDimensions; + nodeDimensions?: any; + /** if node is resizable, this allows direction of specificity */ + resizeDirections?: Enable; } interface MemoHandlerLegacyProps extends HandleProps { @@ -351,6 +353,7 @@ export function NodeContent({ letPassWheelEvents = false, // businessData is just being ignored businessData, + resizeDirections = { bottomRight: true }, // other props for DOM element ...otherDomProps }: NodeContentProps) { @@ -615,9 +618,11 @@ export function NodeContent({ const resizableNode = () => ( { if (nodeContentRef.current) { From fa6fb3d3e8bc5c4ecbe99a3fcc46802b24b38850 Mon Sep 17 00:00:00 2001 From: arausly Date: Mon, 28 Oct 2024 18:07:50 +0100 Subject: [PATCH 02/31] started logic for setting max-wdith for resizable nodes --- src/extensions/react-flow/nodes/NodeContent.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 02d77f270..35315b8bc 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -222,9 +222,11 @@ export interface NodeContentProps /** * width and height dimensions of the node (Optional) */ - nodeDimensions?: any; + nodeDimensions?: NodeDimensions; /** if node is resizable, this allows direction of specificity */ resizeDirections?: Enable; + /** determines how much width a node can be resized to */ + resizeMaxWidth?: number; } interface MemoHandlerLegacyProps extends HandleProps { @@ -354,6 +356,7 @@ export function NodeContent({ // businessData is just being ignored businessData, resizeDirections = { bottomRight: true }, + resizeMaxWidth = Infinity, // other props for DOM element ...otherDomProps }: NodeContentProps) { @@ -631,12 +634,16 @@ export function NodeContent({ } }} onResizeStop={(_0, _1, _2, d) => { - setWidth(width + d.width); + const nextWidthSize = width + d.width; + console.log("NEXT WIDTH ==>", nextWidthSize); + const changeOrRetainWidth = (prevWidth: number) => + nextWidthSize < resizeMaxWidth ? nextWidthSize : prevWidth; + setWidth(changeOrRetainWidth); setHeight(height + d.height); onNodeResize && onNodeResize({ height: height + d.height, - width: width + d.width, + width: changeOrRetainWidth(width), }); }} > From b8efa4afd64b7a93d618dad5cf04586caba74ad7 Mon Sep 17 00:00:00 2001 From: arausly Date: Tue, 5 Nov 2024 17:47:54 +0100 Subject: [PATCH 03/31] fixed undo/redo for resizable nodes --- src/extensions/react-flow/nodes/NodeContent.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 35315b8bc..32d5e4cd6 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -485,7 +485,7 @@ export function NodeContent({ ); const resizableStyles = - !!onNodeResize === true && minimalShape === "none" && width + height > 0 ? { width, height } : {}; + !!onNodeResize === true && minimalShape === "none" && width + (height || 0) > 0 ? { width, height } : {}; const introductionStyles = introductionTime && !introductionDone @@ -624,7 +624,7 @@ export function NodeContent({ handleWrapperClass={ `${resizeDirections.bottomRight ? `${eccgui}-graphviz__node__resizer--cursorhandles` : ""}` + " nodrag" } - size={{ height, width }} + size={{ height: height || "100%", width }} enable={resizeDirections} scale={zoom} onResize={(_0, _1, _2, d) => { @@ -635,9 +635,8 @@ export function NodeContent({ }} onResizeStop={(_0, _1, _2, d) => { const nextWidthSize = width + d.width; - console.log("NEXT WIDTH ==>", nextWidthSize); const changeOrRetainWidth = (prevWidth: number) => - nextWidthSize < resizeMaxWidth ? nextWidthSize : prevWidth; + nextWidthSize < resizeMaxWidth ? nextWidthSize : prevWidth - 1; setWidth(changeOrRetainWidth); setHeight(height + d.height); onNodeResize && From 6c61b90b2e635872dce419634f560ded0929c403 Mon Sep 17 00:00:00 2001 From: arausly Date: Wed, 13 Nov 2024 07:09:17 +0100 Subject: [PATCH 04/31] refactors --- .../react-flow/nodes/NodeContent.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 32d5e4cd6..a91e3dc6c 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -226,7 +226,7 @@ export interface NodeContentProps /** if node is resizable, this allows direction of specificity */ resizeDirections?: Enable; /** determines how much width a node can be resized to */ - resizeMaxWidth?: number; + resizeMaxDimensions?: Partial; } interface MemoHandlerLegacyProps extends HandleProps { @@ -356,7 +356,7 @@ export function NodeContent({ // businessData is just being ignored businessData, resizeDirections = { bottomRight: true }, - resizeMaxWidth = Infinity, + resizeMaxDimensions = { width: Infinity, height: Infinity }, // other props for DOM element ...otherDomProps }: NodeContentProps) { @@ -624,7 +624,7 @@ export function NodeContent({ handleWrapperClass={ `${resizeDirections.bottomRight ? `${eccgui}-graphviz__node__resizer--cursorhandles` : ""}` + " nodrag" } - size={{ height: height || "100%", width }} + size={{ height, width }} enable={resizeDirections} scale={zoom} onResize={(_0, _1, _2, d) => { @@ -634,15 +634,14 @@ export function NodeContent({ } }} onResizeStop={(_0, _1, _2, d) => { - const nextWidthSize = width + d.width; - const changeOrRetainWidth = (prevWidth: number) => - nextWidthSize < resizeMaxWidth ? nextWidthSize : prevWidth - 1; - setWidth(changeOrRetainWidth); - setHeight(height + d.height); + const nextWidth = Math.min(width + d.width, resizeMaxDimensions.width!); + const nextHeight = Math.min(height + d.height, resizeMaxDimensions.height!); + setWidth(nextWidth); + setHeight(nextHeight); onNodeResize && onNodeResize({ - height: height + d.height, - width: changeOrRetainWidth(width), + height: nextHeight, + width: nextWidth, }); }} > From d0aada47d2f21252024a617cf0ddc1cfec7b761d Mon Sep 17 00:00:00 2001 From: arausly Date: Mon, 18 Nov 2024 10:00:49 +0100 Subject: [PATCH 05/31] refactors and changes --- src/extensions/react-flow/nodes/NodeContent.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index a91e3dc6c..621e4fc01 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -356,7 +356,7 @@ export function NodeContent({ // businessData is just being ignored businessData, resizeDirections = { bottomRight: true }, - resizeMaxDimensions = { width: Infinity, height: Infinity }, + resizeMaxDimensions, // other props for DOM element ...otherDomProps }: NodeContentProps) { @@ -367,6 +367,7 @@ export function NodeContent({ const { handles = defaultHandles(flowVersionCheck), ...otherProps } = otherDomProps; const isResizeable = !!onNodeResize && minimalShape === "none"; + const isNotStickyNoteResizableNode = isResizeable && (resizeMaxDimensions?.width || resizeMaxDimensions?.height); const [width, setWidth] = React.useState(nodeDimensions?.width ?? 0); const [height, setHeight] = React.useState(nodeDimensions?.height ?? 0); let zoom = 1; @@ -484,8 +485,11 @@ export function NodeContent({ highlightColor ); + const resizableForNonStickyNodes = isNotStickyNoteResizableNode ? { height: "auto", minHeight: height } : {}; const resizableStyles = - !!onNodeResize === true && minimalShape === "none" && width + (height || 0) > 0 ? { width, height } : {}; + isResizeable && width + (height || 0) > 0 + ? { width, height, maxWidth: resizeMaxDimensions?.width, ...resizableForNonStickyNodes } + : {}; const introductionStyles = introductionTime && !introductionDone @@ -634,8 +638,8 @@ export function NodeContent({ } }} onResizeStop={(_0, _1, _2, d) => { - const nextWidth = Math.min(width + d.width, resizeMaxDimensions.width!); - const nextHeight = Math.min(height + d.height, resizeMaxDimensions.height!); + const nextWidth = Math.min(width + d.width, resizeMaxDimensions?.width ?? Infinity); + const nextHeight = Math.min(height + d.height, resizeMaxDimensions?.height ?? Infinity); setWidth(nextWidth); setHeight(nextHeight); onNodeResize && From 1998848236bfaee7365512e94ad3b051c066a970 Mon Sep 17 00:00:00 2001 From: arausly Date: Tue, 19 Nov 2024 09:48:53 +0100 Subject: [PATCH 06/31] fixed horizontally overflowing evaluation results --- src/extensions/react-flow/nodes/NodeContent.tsx | 14 +++++++------- src/extensions/react-flow/nodes/_nodes.scss | 4 ++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 621e4fc01..590125af5 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -366,12 +366,12 @@ export function NodeContent({ const { handles = defaultHandles(flowVersionCheck), ...otherProps } = otherDomProps; - const isResizeable = !!onNodeResize && minimalShape === "none"; - const isNotStickyNoteResizableNode = isResizeable && (resizeMaxDimensions?.width || resizeMaxDimensions?.height); + const isResizable = !!onNodeResize && minimalShape === "none"; + const isNonStickyNodeResizable = isResizable && (!!resizeMaxDimensions?.height || !!resizeMaxDimensions?.width); //cannot expand infinitely like sticky notes const [width, setWidth] = React.useState(nodeDimensions?.width ?? 0); const [height, setHeight] = React.useState(nodeDimensions?.height ?? 0); let zoom = 1; - if (isResizeable) + if (isResizable) try { [, , zoom] = flowVersionCheck === "legacy" @@ -485,10 +485,9 @@ export function NodeContent({ highlightColor ); - const resizableForNonStickyNodes = isNotStickyNoteResizableNode ? { height: "auto", minHeight: height } : {}; const resizableStyles = - isResizeable && width + (height || 0) > 0 - ? { width, height, maxWidth: resizeMaxDimensions?.width, ...resizableForNonStickyNodes } + isResizable && width + (height || 0) > 0 + ? { width, minHeight: height, maxWidth: resizeMaxDimensions?.width } : {}; const introductionStyles = @@ -516,6 +515,7 @@ export function NodeContent({ ` ${eccgui}-graphviz__node--${size}` + ` ${eccgui}-graphviz__node--minimal-${minimalShape}` + (fullWidth ? ` ${eccgui}-graphviz__node--fullwidth` : "") + + (isNonStickyNodeResizable ? ` ${eccgui}-graphviz__node--flexible-height` : "") + (border ? ` ${eccgui}-graphviz__node--border-${border}` : "") + (intent ? ` ${intentClassName(intent)}` : "") + (highlightClassNameSuffix.length > 0 @@ -653,7 +653,7 @@ export function NodeContent({ ); - return isResizeable ? resizableNode() : nodeContent; + return isResizable ? resizableNode() : nodeContent; } const evaluateHighlightColors = ( diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 5d707bf0d..c33c076fa 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -51,6 +51,10 @@ } } +.#{$eccgui}-graphviz__node--flexible-height { + height: auto !important; +} + .#{$eccgui}-graphviz__node--minimal-rectangular, .#{$eccgui}-graphviz__node--minimal-circular { /* FIXME: does not work correctly with tooltips around From bc6aa05290ea3b14e929391d6260ec782b3f5c1d Mon Sep 17 00:00:00 2001 From: arausly Date: Tue, 19 Nov 2024 18:24:14 +0100 Subject: [PATCH 07/31] resizable wrapper fix --- src/extensions/react-flow/nodes/NodeContent.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 590125af5..181f1c0c4 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -628,7 +628,8 @@ export function NodeContent({ handleWrapperClass={ `${resizeDirections.bottomRight ? `${eccgui}-graphviz__node__resizer--cursorhandles` : ""}` + " nodrag" } - size={{ height, width }} + size={{ height: "auto", width }} + style={{ minHeight: height }} enable={resizeDirections} scale={zoom} onResize={(_0, _1, _2, d) => { From 7d7bd4565ed661a1dd20666b25b09815275b52b8 Mon Sep 17 00:00:00 2001 From: arausly Date: Thu, 21 Nov 2024 09:52:07 +0100 Subject: [PATCH 08/31] added resizable feature to linking editor and removed height from being saved --- src/extensions/react-flow/nodes/NodeContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 181f1c0c4..012f1f6e7 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -400,7 +400,7 @@ export function NodeContent({ // initial dimension before resize React.useEffect(() => { if (!!onNodeResize && minimalShape === "none") { - if (!nodeDimensions) { + if (!nodeDimensions?.width) { setWidth(nodeContentRef.current.offsetWidth); setHeight(nodeContentRef.current.offsetHeight); onNodeResize({ From 889fc7035dacc98b3e250e6e42d85c27f8412c1b Mon Sep 17 00:00:00 2001 From: arausly Date: Thu, 23 Jan 2025 16:27:27 +0100 Subject: [PATCH 09/31] added updates for resizing feature --- package.json | 2 +- .../react-flow/nodes/NodeContent.tsx | 22 ++++++---- src/extensions/react-flow/nodes/_nodes.scss | 44 ++++++++++++++++++- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 18358941b..dca77b3ff 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "color": "^4.2.3", "compute-scroll-into-view": "^3.1.0", "lodash": "^4.17.21", - "re-resizable": "^6.10.1", + "re-resizable": "^6.10.3", "react": "^16.13.1", "react-dom": "^16.13.1", "react-flow-renderer": "9.7.4", diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 7537d7026..b3f827193 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -381,12 +381,12 @@ export function NodeContent({ // initial dimension before resize React.useEffect(() => { if (!!onNodeResize && minimalShape === "none") { - if (!nodeDimensions?.width) { + if (!nodeDimensions?.height || !nodeDimensions?.width) { setWidth(nodeContentRef.current.offsetWidth); setHeight(nodeContentRef.current.offsetHeight); onNodeResize({ - height: nodeContentRef.current.offsetHeight, - width: nodeContentRef.current.offsetWidth, + height: nodeDimensions?.height ?? nodeContentRef.current.offsetHeight, + width: nodeDimensions?.width ?? nodeContentRef.current.offsetWidth, }); } nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; @@ -395,10 +395,8 @@ export function NodeContent({ // update node dimensions when resized React.useEffect(() => { - if (nodeDimensions) { - setWidth(nodeDimensions.width); - setHeight(nodeDimensions.height); - } + setWidth(nodeDimensions?.width ?? width); + setHeight(nodeDimensions?.height ?? height); }, [nodeDimensions]); // remove introduction class @@ -600,9 +598,17 @@ export function NodeContent({ ); + const resizeDirectionClass = resizeDirections.bottomRight + ? `${eccgui}-graphviz__node__resizer--bottomright` + : resizeDirections.right + ? `${eccgui}-graphviz__node__resizer--right` + : resizeDirections.bottom + ? `${eccgui}-graphviz__node__resizer--bottom` + : ""; + const resizableNode = () => ( div { overflow: auto; - resize: both; + z-index: 1; } } } From 405a1e438e920ac77d1d6d1624ae620ef59ce5d4 Mon Sep 17 00:00:00 2001 From: arausly Date: Thu, 6 Feb 2025 22:19:58 +0100 Subject: [PATCH 10/31] added fix for skewed widths --- .../react-flow/nodes/NodeContent.tsx | 22 +++++++++++-------- src/extensions/react-flow/nodes/_nodes.scss | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index b3f827193..8bcc5c561 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -351,6 +351,8 @@ export function NodeContent({ const isNonStickyNodeResizable = isResizable && (!!resizeMaxDimensions?.height || !!resizeMaxDimensions?.width); //cannot expand infinitely like sticky notes const [width, setWidth] = React.useState(nodeDimensions?.width ?? 0); const [height, setHeight] = React.useState(nodeDimensions?.height ?? 0); + const [resizeHasChanged, setResizeHasChanged] = React.useState(false); + let zoom = 1; if (isResizable) try { @@ -378,16 +380,18 @@ export function NodeContent({ handleStack[Position.Left] = flowVersionCheck === "legacy" ? ([] as NodeContentHandleLegacyProps[]) : ([] as NodeContentHandleNextProps[]); - // initial dimension before resize + // // initial dimension before resize React.useEffect(() => { if (!!onNodeResize && minimalShape === "none") { if (!nodeDimensions?.height || !nodeDimensions?.width) { setWidth(nodeContentRef.current.offsetWidth); setHeight(nodeContentRef.current.offsetHeight); - onNodeResize({ - height: nodeDimensions?.height ?? nodeContentRef.current.offsetHeight, - width: nodeDimensions?.width ?? nodeContentRef.current.offsetWidth, - }); + if (resizeHasChanged) { + onNodeResize({ + height: nodeDimensions?.height ?? nodeContentRef.current.offsetHeight, + width: nodeDimensions?.width ?? nodeContentRef.current.offsetWidth, + }); + } } nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; } @@ -395,8 +399,8 @@ export function NodeContent({ // update node dimensions when resized React.useEffect(() => { - setWidth(nodeDimensions?.width ?? width); - setHeight(nodeDimensions?.height ?? height); + setWidth(nodeDimensions?.width || width || nodeContentRef.current?.offsetWidth); + setHeight(nodeDimensions?.height || height || nodeContentRef.current?.offsetHeight); }, [nodeDimensions]); // remove introduction class @@ -612,8 +616,7 @@ export function NodeContent({ handleWrapperClass={ `${resizeDirections.bottomRight ? `${eccgui}-graphviz__node__resizer--cursorhandles` : ""}` + " nodrag" } - size={{ height: "auto", width }} - style={{ minHeight: height }} + size={{ height, width }} enable={resizeDirections} scale={zoom} onResize={(_0, _1, _2, d) => { @@ -632,6 +635,7 @@ export function NodeContent({ height: nextHeight, width: nextWidth, }); + setResizeHasChanged(true); }} > {nodeContent} diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 4828dff7c..1b69f7e35 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -276,7 +276,7 @@ max-height: $reactflow-node-basesize * 8; } -.#{$eccgui}-graphviz__node--medium:not(.is-resizeable) { +.#{$eccgui}-graphviz__node--medium { width: $reactflow-node-basesize * 8; min-height: $reactflow-node-basesize; max-height: $reactflow-node-basesize * 13; From 2a2fa93b0cc61c4e794eb95017f845d040f8b401 Mon Sep 17 00:00:00 2001 From: arausly Date: Fri, 7 Feb 2025 10:50:47 +0100 Subject: [PATCH 11/31] fixed reset nodes option --- src/extensions/react-flow/nodes/NodeContent.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 8bcc5c561..137d23d18 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -214,6 +214,8 @@ export interface NodeContentProps resizeDirections?: Enable; /** determines how much width a node can be resized to */ resizeMaxDimensions?: Partial; + //get default dimensions + getDefaultDimensions?: (dimensions: NodeDimensions) => void; } interface MemoHandlerLegacyProps extends HandleProps { @@ -338,6 +340,7 @@ export function NodeContent({ businessData, resizeDirections = { bottomRight: true }, resizeMaxDimensions, + getDefaultDimensions, // other props for DOM element ...otherDomProps }: NodeContentProps) { @@ -395,7 +398,15 @@ export function NodeContent({ } nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; } - }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions]); + }, [getDefaultDimensions, nodeContentRef, onNodeResize, minimalShape, nodeDimensions]); + + React.useEffect(() => { + getDefaultDimensions && + getDefaultDimensions({ + height: nodeContentRef.current?.offsetHeight, + width: nodeContentRef.current?.offsetWidth, + }); + }, [nodeContentRef]); // update node dimensions when resized React.useEffect(() => { From 2a669788292c00317e3825adf0b4cb449d9aa8f5 Mon Sep 17 00:00:00 2001 From: arausly Date: Mon, 10 Feb 2025 12:16:08 +0100 Subject: [PATCH 12/31] added patch for overflowing menu --- src/components/Menu/menu.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Menu/menu.scss b/src/components/Menu/menu.scss index dff9f4961..431bc386e 100644 --- a/src/components/Menu/menu.scss +++ b/src/components/Menu/menu.scss @@ -48,6 +48,7 @@ $menu-background-color: transparent !default; @import "~@blueprintjs/core/src/components/menu/menu"; .#{$ns}-menu { + min-width: auto; padding: 0; .#{$ns}-popover2-content > & { From 2c47c96dfe82d37f56832e9002147d576c93d7c0 Mon Sep 17 00:00:00 2001 From: arausly Date: Wed, 12 Feb 2025 22:30:03 +0100 Subject: [PATCH 13/31] fix for cursor handles and extra padding --- src/extensions/react-flow/_config.scss | 1 + .../react-flow/nodes/NodeContent.tsx | 10 +++--- src/extensions/react-flow/nodes/_nodes.scss | 35 ++++++++++++------- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/extensions/react-flow/_config.scss b/src/extensions/react-flow/_config.scss index ad836e86d..f32e4ece1 100644 --- a/src/extensions/react-flow/_config.scss +++ b/src/extensions/react-flow/_config.scss @@ -15,3 +15,4 @@ $reactflow-edge-stroke-color-selected: $eccgui-color-accent !default; $reactflow-transition-time: 0.25s !default; $reactflow-transition-function: "" !default; $reactflow-transition-anglestart: -90deg; +$react-flow-cursor-delimiter-offset: -6.5 * $reactflow-node-border-width; diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 137d23d18..e2f43ed90 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -480,9 +480,7 @@ export function NodeContent({ ); const resizableStyles = - isResizable && width + (height || 0) > 0 - ? { width, minHeight: height, maxWidth: resizeMaxDimensions?.width } - : {}; + isResizable && width + (height || 0) > 0 ? { width, height, maxWidth: resizeMaxDimensions?.width } : {}; const introductionStyles = introductionTime && !introductionDone @@ -625,9 +623,11 @@ export function NodeContent({ { diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 1b69f7e35..05ae8c604 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -19,11 +19,11 @@ &::after { content: ""; position: absolute; - margin: -13px; + margin: $react-flow-cursor-delimiter-offset; right: 0; bottom: 1px; - height: 30px; - border-right: 3px solid $reactflow-node-border-color; + height: $reactflow-node-basesize; + border-right: $reactflow-node-border-width solid $reactflow-node-border-color; } } @@ -32,11 +32,11 @@ content: ""; position: absolute; inset: auto 0 0 auto; - margin: -13px; - width: 30px; - height: 30px; - border-right: 3px solid $reactflow-node-border-color; - border-bottom: 3px solid $reactflow-node-border-color; + margin: $react-flow-cursor-delimiter-offset; + width: $reactflow-node-basesize; + height: $reactflow-node-basesize; + border-right: $reactflow-node-border-width solid $reactflow-node-border-color; + border-bottom: $reactflow-node-border-width solid $reactflow-node-border-color; } } @@ -44,12 +44,12 @@ &::after { content: ""; position: absolute; - margin: -13px; + margin: $react-flow-cursor-delimiter-offset; z-index: 1; right: 1px; bottom: 0; - width: 30px; - border-bottom: 3px solid $reactflow-node-border-color; + width: $reactflow-node-basesize; + border-bottom: $reactflow-node-border-width solid $reactflow-node-border-color; } } } @@ -258,7 +258,18 @@ .#{$eccgui}-graphviz__node__resizer--cursorhandles { & > div { overflow: auto; - z-index: 1; + z-index: 2; + } + } + + .#{$eccgui}-graphviz__node__resizer--cursorhandles-right { + & > div { + top: $react-flow-cursor-delimiter-offset !important; + bottom: $react-flow-cursor-delimiter-offset !important; + right: $react-flow-cursor-delimiter-offset !important; + height: unset !important; + width: $reactflow-node-basesize !important; + z-index: 2 !important; } } } From 1d7a98975b99fa5e3aebabc0dba8abd043e8e025 Mon Sep 17 00:00:00 2001 From: arausly Date: Wed, 12 Feb 2025 22:43:11 +0100 Subject: [PATCH 14/31] tentative patch --- src/extensions/react-flow/nodes/_nodes.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 05ae8c604..bb85037d0 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -275,13 +275,13 @@ } } -.#{$eccgui}-graphviz__node--tiny:not(.is-resizeable) { +.#{$eccgui}-graphviz__node--tiny { width: $reactflow-node-basesize * 4; min-height: $reactflow-node-basesize; max-height: $reactflow-node-basesize * 4; } -.#{$eccgui}-graphviz__node--small:not(.is-resizeable) { +.#{$eccgui}-graphviz__node--small { width: $reactflow-node-basesize * 5; min-height: $reactflow-node-basesize; max-height: $reactflow-node-basesize * 8; From 4d01305e2060fa33d5aa584af0f613171741fe7c Mon Sep 17 00:00:00 2001 From: arausly Date: Sat, 15 Feb 2025 13:25:53 +0100 Subject: [PATCH 15/31] More refactors --- .../react-flow/nodes/NodeContent.tsx | 35 +++++++++++-------- src/extensions/react-flow/nodes/_nodes.scss | 2 +- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index e2f43ed90..d9558c5c0 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -25,6 +25,8 @@ export type NodeContentHandleProps = NodeContentHandleLegacyProps | NodeContentH type NodeDimensions = { width: number; height: number; + defaultWidth?: number | null; + defaultHeight?: number | null; }; type IntroductionTime = { @@ -214,8 +216,6 @@ export interface NodeContentProps resizeDirections?: Enable; /** determines how much width a node can be resized to */ resizeMaxDimensions?: Partial; - //get default dimensions - getDefaultDimensions?: (dimensions: NodeDimensions) => void; } interface MemoHandlerLegacyProps extends HandleProps { @@ -340,7 +340,6 @@ export function NodeContent({ businessData, resizeDirections = { bottomRight: true }, resizeMaxDimensions, - getDefaultDimensions, // other props for DOM element ...otherDomProps }: NodeContentProps) { @@ -355,6 +354,7 @@ export function NodeContent({ const [width, setWidth] = React.useState(nodeDimensions?.width ?? 0); const [height, setHeight] = React.useState(nodeDimensions?.height ?? 0); const [resizeHasChanged, setResizeHasChanged] = React.useState(false); + const [defaultSizes, setDefaultSizes] = React.useState<{ width: number; height: number }>(); let zoom = 1; if (isResizable) @@ -386,33 +386,38 @@ export function NodeContent({ // // initial dimension before resize React.useEffect(() => { if (!!onNodeResize && minimalShape === "none") { + const isResetRequest = !nodeDimensions?.height && !nodeDimensions?.width && resizeHasChanged; // i.e height and width is set to null + const newWidth = isResetRequest ? defaultSizes?.width : nodeContentRef.current.offsetWidth; + const newHeight = isResetRequest ? defaultSizes?.height : nodeContentRef.current.offsetHeight; + setWidth(newWidth); + setHeight(newHeight); + if (!nodeDimensions?.height || !nodeDimensions?.width) { - setWidth(nodeContentRef.current.offsetWidth); - setHeight(nodeContentRef.current.offsetHeight); if (resizeHasChanged) { onNodeResize({ - height: nodeDimensions?.height ?? nodeContentRef.current.offsetHeight, - width: nodeDimensions?.width ?? nodeContentRef.current.offsetWidth, + height: newHeight, + width: newWidth, + defaultHeight: defaultSizes?.height, + defaultWidth: defaultSizes?.width, }); } } nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; } - }, [getDefaultDimensions, nodeContentRef, onNodeResize, minimalShape, nodeDimensions]); + }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions, defaultSizes]); React.useEffect(() => { - getDefaultDimensions && - getDefaultDimensions({ - height: nodeContentRef.current?.offsetHeight, - width: nodeContentRef.current?.offsetWidth, - }); + setDefaultSizes({ + height: nodeContentRef.current?.offsetHeight, + width: nodeContentRef.current?.offsetWidth, + }); }, [nodeContentRef]); // update node dimensions when resized React.useEffect(() => { setWidth(nodeDimensions?.width || width || nodeContentRef.current?.offsetWidth); setHeight(nodeDimensions?.height || height || nodeContentRef.current?.offsetHeight); - }, [nodeDimensions]); + }, [nodeDimensions, defaultSizes]); // remove introduction class React.useEffect(() => { @@ -645,6 +650,8 @@ export function NodeContent({ onNodeResize({ height: nextHeight, width: nextWidth, + defaultHeight: defaultSizes?.height, + defaultWidth: defaultSizes?.width, }); setResizeHasChanged(true); }} diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index bb85037d0..4fbf95a85 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -269,7 +269,7 @@ right: $react-flow-cursor-delimiter-offset !important; height: unset !important; width: $reactflow-node-basesize !important; - z-index: 2 !important; + z-index: 1 !important; } } } From f5dfbfd47f25f2709787b11d69311462a92b1d64 Mon Sep 17 00:00:00 2001 From: arausly Date: Tue, 18 Feb 2025 08:35:27 +0100 Subject: [PATCH 16/31] test patches --- src/extensions/codemirror/CodeMirror.tsx | 34 ++++++++++--------- .../codemirror/tests/codemirrorTestHelper.ts | 4 +++ .../react-flow/nodes/NodeContent.tsx | 16 ++++----- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/extensions/codemirror/CodeMirror.tsx b/src/extensions/codemirror/CodeMirror.tsx index 3a040b06f..727a78c6d 100644 --- a/src/extensions/codemirror/CodeMirror.tsx +++ b/src/extensions/codemirror/CodeMirror.tsx @@ -1,7 +1,6 @@ import React, { useMemo, useRef } from "react"; import { defaultKeymap, indentWithTab } from "@codemirror/commands"; import { foldKeymap } from "@codemirror/language"; -import { lintGutter } from "@codemirror/lint"; import { EditorState, Extension } from "@codemirror/state"; import { DOMEventHandlers, EditorView, KeyBinding, keymap, Rect, ViewUpdate } from "@codemirror/view"; import { minimalSetup } from "codemirror"; @@ -29,6 +28,7 @@ import { adaptedHighlightSpecialChars, adaptedLineNumbers, adaptedPlaceholder, + adaptedLintGutter, } from "./tests/codemirrorTestHelper"; import { ExtensionCreator } from "./types"; @@ -212,7 +212,7 @@ export const CodeEditor = ({ return []; } - const values = [lintGutter()]; + const values = [adaptedLintGutter()]; const linters = ModeLinterMap.get(mode); if (linters) { @@ -320,24 +320,26 @@ export const CodeEditor = ({ parent: parent.current, }); - if (height) { - view.dom.style.height = typeof height === "string" ? height : `${height}px`; - } + if (view?.dom) { + if (height) { + view.dom.style.height = typeof height === "string" ? height : `${height}px`; + } - if (disabled) { - view.dom.className += ` ${eccgui}-disabled`; - } + if (disabled) { + view.dom.className += ` ${eccgui}-disabled`; + } - if (intent) { - view.dom.className += ` ${eccgui}-intent--${intent}`; - } + if (intent) { + view.dom.className += ` ${eccgui}-intent--${intent}`; + } - if (autoFocus) { - view.focus(); - } + if (autoFocus) { + view.focus(); + } - if (setEditorView) { - setEditorView(view); + if (setEditorView) { + setEditorView(view); + } } return () => { diff --git a/src/extensions/codemirror/tests/codemirrorTestHelper.ts b/src/extensions/codemirror/tests/codemirrorTestHelper.ts index f7a38162c..8d1c35e26 100644 --- a/src/extensions/codemirror/tests/codemirrorTestHelper.ts +++ b/src/extensions/codemirror/tests/codemirrorTestHelper.ts @@ -10,6 +10,7 @@ import { EditorView, placeholder, highlightSpecialChars, lineNumbers, highlightActiveLine } from "@codemirror/view"; import { syntaxHighlighting, foldGutter, codeFolding } from "@codemirror/language"; import { Extension } from "@codemirror/state"; +import { lintGutter } from "@codemirror/lint"; /** placeholder extension, current error '_view.placeholder is not a function' */ export const adaptedPlaceholder = (text?: string) => @@ -55,3 +56,6 @@ export const adaptedFoldGutter = (props?: any) => export const adaptedCodeFolding = (props?: any) => typeof codeFolding === "function" ? codeFolding(props) : emptyExtension; + +export const adaptedLintGutter = (props?: any) => + typeof lintGutter === "function" ? lintGutter(props) : emptyExtension; diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index d9558c5c0..ff8486d1e 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -392,15 +392,13 @@ export function NodeContent({ setWidth(newWidth); setHeight(newHeight); - if (!nodeDimensions?.height || !nodeDimensions?.width) { - if (resizeHasChanged) { - onNodeResize({ - height: newHeight, - width: newWidth, - defaultHeight: defaultSizes?.height, - defaultWidth: defaultSizes?.width, - }); - } + if ((!nodeDimensions?.height || !nodeDimensions?.width) && resizeHasChanged) { + onNodeResize({ + height: newHeight, + width: newWidth, + defaultHeight: defaultSizes?.height, + defaultWidth: defaultSizes?.width, + }); } nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; } From a77abb7cf36b4f10f7a3834bc85886ba3f9ab9aa Mon Sep 17 00:00:00 2001 From: arausly Date: Thu, 20 Feb 2025 10:50:06 +0100 Subject: [PATCH 17/31] corrected isresizable flag and other refactors --- src/extensions/react-flow/_config.scss | 2 +- src/extensions/react-flow/nodes/NodeContent.tsx | 15 ++++++++------- src/extensions/react-flow/nodes/_nodes.scss | 14 +++++++------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/extensions/react-flow/_config.scss b/src/extensions/react-flow/_config.scss index f32e4ece1..d01660d2c 100644 --- a/src/extensions/react-flow/_config.scss +++ b/src/extensions/react-flow/_config.scss @@ -15,4 +15,4 @@ $reactflow-edge-stroke-color-selected: $eccgui-color-accent !default; $reactflow-transition-time: 0.25s !default; $reactflow-transition-function: "" !default; $reactflow-transition-anglestart: -90deg; -$react-flow-cursor-delimiter-offset: -6.5 * $reactflow-node-border-width; +$reactflow-cursor-delimiter-offset: -0.9 * $eccgui-size-block-whitespace; diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index ff8486d1e..cf9f51ae1 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -2,7 +2,7 @@ import React from "react"; import { Position, useStoreState as getStoreStateFlowLegacy } from "react-flow-renderer"; import { useStore as getStoreStateFlowNext } from "react-flow-renderer-lts"; import Color from "color"; -import { Enable, Resizable } from "re-resizable"; +import { Resizable } from "re-resizable"; import { intentClassName, IntentTypes } from "../../../common/Intent"; import { DepictionProps } from "../../../components/Depiction/Depiction"; @@ -213,7 +213,7 @@ export interface NodeContentProps */ nodeDimensions?: NodeDimensions; /** if node is resizable, this allows direction of specificity */ - resizeDirections?: Enable; + resizeDirections?: Partial<{ right: boolean; bottom: boolean; bottomRight: boolean }>; /** determines how much width a node can be resized to */ resizeMaxDimensions?: Partial; } @@ -338,7 +338,7 @@ export function NodeContent({ letPassWheelEvents = false, // businessData is just being ignored businessData, - resizeDirections = { bottomRight: true }, + resizeDirections = {}, resizeMaxDimensions, // other props for DOM element ...otherDomProps @@ -349,8 +349,9 @@ export function NodeContent({ const { handles = defaultHandles(flowVersionCheck), ...otherProps } = otherDomProps; - const isResizable = !!onNodeResize && minimalShape === "none"; - const isNonStickyNodeResizable = isResizable && (!!resizeMaxDimensions?.height || !!resizeMaxDimensions?.width); //cannot expand infinitely like sticky notes + const isResizable = + typeof onNodeResize === "function" && Object.keys(resizeDirections).length && minimalShape === "none"; + const [width, setWidth] = React.useState(nodeDimensions?.width ?? 0); const [height, setHeight] = React.useState(nodeDimensions?.height ?? 0); const [resizeHasChanged, setResizeHasChanged] = React.useState(false); @@ -385,7 +386,7 @@ export function NodeContent({ // // initial dimension before resize React.useEffect(() => { - if (!!onNodeResize && minimalShape === "none") { + if (isResizable) { const isResetRequest = !nodeDimensions?.height && !nodeDimensions?.width && resizeHasChanged; // i.e height and width is set to null const newWidth = isResetRequest ? defaultSizes?.width : nodeContentRef.current.offsetWidth; const newHeight = isResetRequest ? defaultSizes?.height : nodeContentRef.current.offsetHeight; @@ -510,7 +511,7 @@ export function NodeContent({ ` ${eccgui}-graphviz__node--${size}` + ` ${eccgui}-graphviz__node--minimal-${minimalShape}` + (fullWidth ? ` ${eccgui}-graphviz__node--fullwidth` : "") + - (isNonStickyNodeResizable ? ` ${eccgui}-graphviz__node--flexible-height` : "") + + ` ${eccgui}-graphviz__node--flexible-height` + (border ? ` ${eccgui}-graphviz__node--border-${border}` : "") + (intent ? ` ${intentClassName(intent)}` : "") + (highlightClassNameSuffix.length > 0 diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 4fbf95a85..1c63d418f 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -19,7 +19,7 @@ &::after { content: ""; position: absolute; - margin: $react-flow-cursor-delimiter-offset; + margin: $reactflow-cursor-delimiter-offset; right: 0; bottom: 1px; height: $reactflow-node-basesize; @@ -32,7 +32,7 @@ content: ""; position: absolute; inset: auto 0 0 auto; - margin: $react-flow-cursor-delimiter-offset; + margin: $reactflow-cursor-delimiter-offset; width: $reactflow-node-basesize; height: $reactflow-node-basesize; border-right: $reactflow-node-border-width solid $reactflow-node-border-color; @@ -44,7 +44,7 @@ &::after { content: ""; position: absolute; - margin: $react-flow-cursor-delimiter-offset; + margin: $reactflow-cursor-delimiter-offset; z-index: 1; right: 1px; bottom: 0; @@ -264,9 +264,9 @@ .#{$eccgui}-graphviz__node__resizer--cursorhandles-right { & > div { - top: $react-flow-cursor-delimiter-offset !important; - bottom: $react-flow-cursor-delimiter-offset !important; - right: $react-flow-cursor-delimiter-offset !important; + top: $reactflow-cursor-delimiter-offset !important; + bottom: $reactflow-cursor-delimiter-offset !important; + right: $reactflow-cursor-delimiter-offset !important; height: unset !important; width: $reactflow-node-basesize !important; z-index: 1 !important; @@ -293,7 +293,7 @@ max-height: $reactflow-node-basesize * 13; } -.#{$eccgui}-graphviz__node--large:not(.is-resizeable) { +.#{$eccgui}-graphviz__node--large { width: $reactflow-node-basesize * 13; min-height: $reactflow-node-basesize; max-height: $reactflow-node-basesize * 13; From 9c52178c29bae8e691fae4fd33c3820b1c6d6f61 Mon Sep 17 00:00:00 2001 From: arausly Date: Fri, 21 Feb 2025 15:53:23 +0100 Subject: [PATCH 18/31] fixed bug with height expansion --- src/extensions/react-flow/nodes/NodeContent.tsx | 14 +++++++++++--- src/extensions/react-flow/nodes/_nodes.scss | 4 ++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index cf9f51ae1..8a213e054 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -484,7 +484,9 @@ export function NodeContent({ ); const resizableStyles = - isResizable && width + (height || 0) > 0 ? { width, height, maxWidth: resizeMaxDimensions?.width } : {}; + isResizable && width + (height || 0) > 0 + ? { width, height, maxWidth: resizeMaxDimensions?.width, flexGrow: 1, minHeight: "fit-content" } + : {}; const introductionStyles = introductionTime && !introductionDone @@ -625,13 +627,19 @@ export function NodeContent({ const resizableNode = () => ( { diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 1c63d418f..7b4d61461 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -252,6 +252,10 @@ min-height: 2.5 * $reactflow-node-basesize; } +.#{eccgui}-graphviz__node__resizer--fit-content { + min-height: fit-content !important; +} + .#{$eccgui}-graphviz__node__resizer { .selected &, &:hover { From b95d5d0bcfd3f063e0582baa3a8eae15f677ec6b Mon Sep 17 00:00:00 2001 From: arausly Date: Mon, 24 Feb 2025 19:38:14 +0100 Subject: [PATCH 19/31] node content refactors --- src/extensions/react-flow/nodes/NodeContent.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 8a213e054..da7a57a28 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -338,7 +338,7 @@ export function NodeContent({ letPassWheelEvents = false, // businessData is just being ignored businessData, - resizeDirections = {}, + resizeDirections = { bottomRight: true }, resizeMaxDimensions, // other props for DOM element ...otherDomProps @@ -349,8 +349,8 @@ export function NodeContent({ const { handles = defaultHandles(flowVersionCheck), ...otherProps } = otherDomProps; - const isResizable = - typeof onNodeResize === "function" && Object.keys(resizeDirections).length && minimalShape === "none"; + const hasValidResizeDirection = resizeDirections.bottom || resizeDirections.bottomRight || resizeDirections.right; + const isResizable = typeof onNodeResize === "function" && hasValidResizeDirection && minimalShape === "none"; const [width, setWidth] = React.useState(nodeDimensions?.width ?? 0); const [height, setHeight] = React.useState(nodeDimensions?.height ?? 0); @@ -401,9 +401,10 @@ export function NodeContent({ defaultWidth: defaultSizes?.width, }); } - nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; + if (!nodeContentRef.current.includes("is-resizable")) + nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; } - }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions, defaultSizes]); + }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions, defaultSizes, resizeHasChanged]); React.useEffect(() => { setDefaultSizes({ From 6e0fab8ad07f61eb67f3b37f9f38237c0c54000f Mon Sep 17 00:00:00 2001 From: arausly Date: Tue, 25 Feb 2025 09:41:20 +0100 Subject: [PATCH 20/31] more refactors --- src/extensions/react-flow/nodes/NodeContent.tsx | 4 ++-- src/extensions/react-flow/nodes/_nodes.scss | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index da7a57a28..c49b8875b 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -384,7 +384,7 @@ export function NodeContent({ handleStack[Position.Left] = flowVersionCheck === "legacy" ? ([] as NodeContentHandleLegacyProps[]) : ([] as NodeContentHandleNextProps[]); - // // initial dimension before resize + // initial dimension before resize React.useEffect(() => { if (isResizable) { const isResetRequest = !nodeDimensions?.height && !nodeDimensions?.width && resizeHasChanged; // i.e height and width is set to null @@ -401,7 +401,7 @@ export function NodeContent({ defaultWidth: defaultSizes?.width, }); } - if (!nodeContentRef.current.includes("is-resizable")) + if (!nodeContentRef.current?.className.includes("is-resizable")) nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; } }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions, defaultSizes, resizeHasChanged]); diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 7b4d61461..778823309 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -21,7 +21,7 @@ position: absolute; margin: $reactflow-cursor-delimiter-offset; right: 0; - bottom: 1px; + bottom: -1 * $reactflow-cursor-delimiter-offset; height: $reactflow-node-basesize; border-right: $reactflow-node-border-width solid $reactflow-node-border-color; } @@ -46,7 +46,7 @@ position: absolute; margin: $reactflow-cursor-delimiter-offset; z-index: 1; - right: 1px; + right: -1 * $reactflow-cursor-delimiter-offset; bottom: 0; width: $reactflow-node-basesize; border-bottom: $reactflow-node-border-width solid $reactflow-node-border-color; From f0338928737cb8d23b681a728baba4fda78093cb Mon Sep 17 00:00:00 2001 From: arausly Date: Tue, 25 Feb 2025 09:56:46 +0100 Subject: [PATCH 21/31] removed max-height for nodes since they are all possibly resizable --- src/extensions/react-flow/nodes/_nodes.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 778823309..c02c98b47 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -282,25 +282,25 @@ .#{$eccgui}-graphviz__node--tiny { width: $reactflow-node-basesize * 4; min-height: $reactflow-node-basesize; - max-height: $reactflow-node-basesize * 4; + // max-height: $reactflow-node-basesize * 4; } .#{$eccgui}-graphviz__node--small { width: $reactflow-node-basesize * 5; min-height: $reactflow-node-basesize; - max-height: $reactflow-node-basesize * 8; + // max-height: $reactflow-node-basesize * 8; } .#{$eccgui}-graphviz__node--medium { width: $reactflow-node-basesize * 8; min-height: $reactflow-node-basesize; - max-height: $reactflow-node-basesize * 13; + // max-height: $reactflow-node-basesize * 13; } .#{$eccgui}-graphviz__node--large { width: $reactflow-node-basesize * 13; min-height: $reactflow-node-basesize; - max-height: $reactflow-node-basesize * 13; + // max-height: $reactflow-node-basesize * 13; } .#{$eccgui}-graphviz__node--fullwidth:not(.is-resizeable) { From 365c5888030ca25176e92bd072791112dd03ecd7 Mon Sep 17 00:00:00 2001 From: arausly Date: Tue, 25 Feb 2025 12:02:39 +0100 Subject: [PATCH 22/31] overwrote max-height for resizable, expands based on content --- src/extensions/react-flow/nodes/NodeContent.tsx | 2 +- src/extensions/react-flow/nodes/_nodes.scss | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index c49b8875b..7db7212c6 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -401,7 +401,7 @@ export function NodeContent({ defaultWidth: defaultSizes?.width, }); } - if (!nodeContentRef.current?.className.includes("is-resizable")) + if (!nodeContentRef.current?.className.includes("is-resizeable")) nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; } }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions, defaultSizes, resizeHasChanged]); diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index c02c98b47..4256a1c3d 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -257,6 +257,9 @@ } .#{$eccgui}-graphviz__node__resizer { + & > .is-resizeable { + max-height: none !important; + } .selected &, &:hover { .#{$eccgui}-graphviz__node__resizer--cursorhandles { @@ -282,25 +285,25 @@ .#{$eccgui}-graphviz__node--tiny { width: $reactflow-node-basesize * 4; min-height: $reactflow-node-basesize; - // max-height: $reactflow-node-basesize * 4; + max-height: $reactflow-node-basesize * 4; } .#{$eccgui}-graphviz__node--small { width: $reactflow-node-basesize * 5; min-height: $reactflow-node-basesize; - // max-height: $reactflow-node-basesize * 8; + max-height: $reactflow-node-basesize * 8; } .#{$eccgui}-graphviz__node--medium { width: $reactflow-node-basesize * 8; min-height: $reactflow-node-basesize; - // max-height: $reactflow-node-basesize * 13; + max-height: $reactflow-node-basesize * 13; } .#{$eccgui}-graphviz__node--large { width: $reactflow-node-basesize * 13; min-height: $reactflow-node-basesize; - // max-height: $reactflow-node-basesize * 13; + max-height: $reactflow-node-basesize * 13; } .#{$eccgui}-graphviz__node--fullwidth:not(.is-resizeable) { From 1f0bae58faa983220d8643c38f78009b64878668 Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Thu, 27 Feb 2025 17:32:01 +0100 Subject: [PATCH 23/31] fix node resizing: use correct default size and do not set values for resize directions that are not allowed --- src/extensions/react-flow/_config.scss | 2 +- .../react-flow/nodes/NodeContent.tsx | 193 +++++++++++------- src/extensions/react-flow/nodes/_nodes.scss | 162 ++++++--------- .../nodes/stories/NodeContent.stories.tsx | 9 +- 4 files changed, 190 insertions(+), 176 deletions(-) diff --git a/src/extensions/react-flow/_config.scss b/src/extensions/react-flow/_config.scss index d01660d2c..d5855aaf4 100644 --- a/src/extensions/react-flow/_config.scss +++ b/src/extensions/react-flow/_config.scss @@ -15,4 +15,4 @@ $reactflow-edge-stroke-color-selected: $eccgui-color-accent !default; $reactflow-transition-time: 0.25s !default; $reactflow-transition-function: "" !default; $reactflow-transition-anglestart: -90deg; -$reactflow-cursor-delimiter-offset: -0.9 * $eccgui-size-block-whitespace; +$reactflow-cursor-delimiter-offset: 0.9 * $eccgui-size-block-whitespace; diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 7db7212c6..17fa06b85 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -23,12 +23,12 @@ type NodeContentHandleNextProps = HandleNextProps; export type NodeContentHandleProps = NodeContentHandleLegacyProps | NodeContentHandleNextProps; type NodeDimensions = { - width: number; - height: number; - defaultWidth?: number | null; - defaultHeight?: number | null; + width?: number; + height?: number; }; +type ResizeDirections = { right: true, bottom?: false } | { right?: false, bottom: true } | { right: true, bottom: true }; + type IntroductionTime = { /** * The delay time in ms before the introduction animation is displayed. @@ -213,7 +213,7 @@ export interface NodeContentProps */ nodeDimensions?: NodeDimensions; /** if node is resizable, this allows direction of specificity */ - resizeDirections?: Partial<{ right: boolean; bottom: boolean; bottomRight: boolean }>; + resizeDirections?: ResizeDirections; /** determines how much width a node can be resized to */ resizeMaxDimensions?: Partial; } @@ -323,23 +323,25 @@ export function NodeContent({ //handles = defaultHandles(), adaptHeightForHandleMinCount, adaptSizeIncrement = 15, + // FIXME: getMinimalTooltipData is just being ignored, only used in `NodeDefault` getMinimalTooltipData = getDefaultMinimalTooltipData, style = {}, showUnconnectableHandles = false, animated = false, introductionTime = 0, + // resizing onNodeResize, nodeDimensions, + resizeDirections = { bottom: true, right: true }, + resizeMaxDimensions, // forwarded props targetPosition = Position.Left, sourcePosition = Position.Right, isConnectable = true, selected, letPassWheelEvents = false, - // businessData is just being ignored + // FIXME: businessData is just being ignored businessData, - resizeDirections = { bottomRight: true }, - resizeMaxDimensions, // other props for DOM element ...otherDomProps }: NodeContentProps) { @@ -349,13 +351,13 @@ export function NodeContent({ const { handles = defaultHandles(flowVersionCheck), ...otherProps } = otherDomProps; - const hasValidResizeDirection = resizeDirections.bottom || resizeDirections.bottomRight || resizeDirections.right; + const hasValidResizeDirection = resizeDirections.bottom || resizeDirections.right; const isResizable = typeof onNodeResize === "function" && hasValidResizeDirection && minimalShape === "none"; - const [width, setWidth] = React.useState(nodeDimensions?.width ?? 0); - const [height, setHeight] = React.useState(nodeDimensions?.height ?? 0); - const [resizeHasChanged, setResizeHasChanged] = React.useState(false); - const [defaultSizes, setDefaultSizes] = React.useState<{ width: number; height: number }>(); + const [width, setWidth] = React.useState(nodeDimensions?.width ?? undefined); + const [height, setHeight] = React.useState(nodeDimensions?.height ?? undefined); + + const originalSize = {} as NodeDimensions; let zoom = 1; if (isResizable) @@ -384,40 +386,60 @@ export function NodeContent({ handleStack[Position.Left] = flowVersionCheck === "legacy" ? ([] as NodeContentHandleLegacyProps[]) : ([] as NodeContentHandleNextProps[]); + const saveOriginalSize = () => { + if ((!originalSize.width && !originalSize.height)) { + originalSize.width = nodeContentRef.current.offsetWidth as number; + originalSize.height = nodeContentRef.current.offsetHeight as number; + } + } + + // update node dimensions when resized + React.useEffect(() => { + const updateWidth = nodeDimensions?.width ? validateWidth(nodeDimensions?.width) : undefined; + const updateHeight = nodeDimensions?.height ? validateHeight(nodeDimensions?.height) : undefined; + setWidth(updateWidth); + setHeight(updateHeight); + }, [nodeDimensions]); + // initial dimension before resize React.useEffect(() => { - if (isResizable) { - const isResetRequest = !nodeDimensions?.height && !nodeDimensions?.width && resizeHasChanged; // i.e height and width is set to null - const newWidth = isResetRequest ? defaultSizes?.width : nodeContentRef.current.offsetWidth; - const newHeight = isResetRequest ? defaultSizes?.height : nodeContentRef.current.offsetHeight; + saveOriginalSize(); + const currentClassNames = nodeContentRef.current.classList; + const resizingActive = ( + resizeDirections.right === currentClassNames.contains("is-resizable-horizontal") && + resizeDirections.bottom === currentClassNames.contains("is-resizable-vertical") + ) + + if (isResizable && !resizingActive) { + if (currentClassNames.contains("is-resizable-horizontal")) { + nodeContentRef.current.classList.remove( + "is-resizable-horizontal" + ); + } + if (currentClassNames.contains("is-resizable-vertical")) { + nodeContentRef.current.classList.remove( + "is-resizable-vertical" + ); + } + + const newWidth = validateWidth(originalSize?.width as number); + const newHeight = validateHeight(originalSize?.height as number); + setWidth(newWidth); setHeight(newHeight); - if ((!nodeDimensions?.height || !nodeDimensions?.width) && resizeHasChanged) { - onNodeResize({ - height: newHeight, - width: newWidth, - defaultHeight: defaultSizes?.height, - defaultWidth: defaultSizes?.width, - }); + if (resizeDirections.right) { + nodeContentRef.current.classList.add( + "is-resizable-horizontal" + ); } - if (!nodeContentRef.current?.className.includes("is-resizeable")) - nodeContentRef.current.className = nodeContentRef.current.className + " is-resizeable"; + if (resizeDirections.bottom) { + nodeContentRef.current.classList.add( + "is-resizable-vertical" + ); + } } - }, [nodeContentRef, onNodeResize, minimalShape, nodeDimensions, defaultSizes, resizeHasChanged]); - - React.useEffect(() => { - setDefaultSizes({ - height: nodeContentRef.current?.offsetHeight, - width: nodeContentRef.current?.offsetWidth, - }); - }, [nodeContentRef]); - - // update node dimensions when resized - React.useEffect(() => { - setWidth(nodeDimensions?.width || width || nodeContentRef.current?.offsetWidth); - setHeight(nodeDimensions?.height || height || nodeContentRef.current?.offsetHeight); - }, [nodeDimensions, defaultSizes]); + }, [nodeContentRef, onNodeResize, minimalShape, resizeDirections]); // remove introduction class React.useEffect(() => { @@ -484,10 +506,12 @@ export function NodeContent({ highlightColor ); - const resizableStyles = - isResizable && width + (height || 0) > 0 - ? { width, height, maxWidth: resizeMaxDimensions?.width, flexGrow: 1, minHeight: "fit-content" } - : {}; + const resizableStyles = isResizable && ((width??0) + (height??0)) > 0 ? { + width, + height, + maxWidth: resizeMaxDimensions?.width ?? undefined, + maxHeight: resizeMaxDimensions?.height ?? undefined, + } : {}; const introductionStyles = introductionTime && !introductionDone @@ -497,6 +521,7 @@ export function NodeContent({ }ms`, } as React.CSSProperties) : {}; + const nodeContent = ( <>
({ ` ${eccgui}-graphviz__node--${size}` + ` ${eccgui}-graphviz__node--minimal-${minimalShape}` + (fullWidth ? ` ${eccgui}-graphviz__node--fullwidth` : "") + - ` ${eccgui}-graphviz__node--flexible-height` + (border ? ` ${eccgui}-graphviz__node--border-${border}` : "") + (intent ? ` ${intentClassName(intent)}` : "") + (highlightClassNameSuffix.length > 0 @@ -618,55 +642,68 @@ export function NodeContent({ ); - const resizeDirectionClass = resizeDirections.bottomRight - ? `${eccgui}-graphviz__node__resizer--bottomright` - : resizeDirections.right - ? `${eccgui}-graphviz__node__resizer--right` - : resizeDirections.bottom - ? `${eccgui}-graphviz__node__resizer--bottom` - : ""; - - const resizableNode = () => ( - { + // only allow value if resize direction is allowed + if (!resizeDirections.right) { return undefined; } + // we need to check because there is probably a min value defined via CSS + const min = nodeContentRef.current.offsetWidth; + // we need to check for a given max value + const max = resizeMaxDimensions?.width ?? Infinity; + const validatedWidth = Math.max(Math.min(resizedWidth, max), min); + return validatedWidth; + } + + const validateHeight = (resizedHeight: number) : number | undefined => { + if (!resizeDirections.bottom) { return undefined; } + const min = nodeContentRef.current.offsetHeight; + const max = resizeMaxDimensions?.height ?? Infinity; + const validatedHeight = Math.max(Math.min(resizedHeight, max), min); + return validatedHeight; + } + + const resizableNode = () => { + const size = { height: height ?? "auto", width: width ?? "auto" }; + return { if (nodeContentRef.current) { - nodeContentRef.current.style.width = width + d.width + "px"; - nodeContentRef.current.style.height = height + d.height + "px"; + saveOriginalSize(); + const nextWidth = resizeDirections.right ? (width??originalSize.width??0) + d.width : undefined; + const nextHeight = resizeDirections.bottom ? (height??originalSize.height??0) + d.height : undefined; + if (nextWidth) { + nodeContentRef.current.style.width = `${nextWidth}px`; + } + if (nextHeight) { + nodeContentRef.current.style.height = `${nextHeight}px`; + } } }} onResizeStop={(_0, _1, _2, d) => { - const nextWidth = Math.min(width + d.width, resizeMaxDimensions?.width ?? Infinity); - const nextHeight = Math.min(height + d.height, resizeMaxDimensions?.height ?? Infinity); + const nextWidth = validateWidth((width??0) + d.width); + const nextHeight = validateHeight((height??0) + d.height); setWidth(nextWidth); setHeight(nextHeight); - onNodeResize && + if (onNodeResize) { onNodeResize({ height: nextHeight, width: nextWidth, - defaultHeight: defaultSizes?.height, - defaultWidth: defaultSizes?.width, }); - setResizeHasChanged(true); + } }} > {nodeContent} - ); + }; return isResizable ? resizableNode() : nodeContent; } @@ -695,7 +732,7 @@ const evaluateHighlightColors = ( let customColor = Color("#ffffff"); try { customColor = Color(color); - } catch (ex) { + } catch { // eslint-disable-next-line no-console console.warn("Received invalid color for highlight: " + color); } diff --git a/src/extensions/react-flow/nodes/_nodes.scss b/src/extensions/react-flow/nodes/_nodes.scss index 4256a1c3d..f87bb701b 100644 --- a/src/extensions/react-flow/nodes/_nodes.scss +++ b/src/extensions/react-flow/nodes/_nodes.scss @@ -13,47 +13,6 @@ border-radius: $reactflow-node-border-radius; } - &.selected &, - &:hover { - .#{eccgui}-graphviz__node__resizer--right { - &::after { - content: ""; - position: absolute; - margin: $reactflow-cursor-delimiter-offset; - right: 0; - bottom: -1 * $reactflow-cursor-delimiter-offset; - height: $reactflow-node-basesize; - border-right: $reactflow-node-border-width solid $reactflow-node-border-color; - } - } - - .#{eccgui}-graphviz__node__resizer--bottomright { - &::after { - content: ""; - position: absolute; - inset: auto 0 0 auto; - margin: $reactflow-cursor-delimiter-offset; - width: $reactflow-node-basesize; - height: $reactflow-node-basesize; - border-right: $reactflow-node-border-width solid $reactflow-node-border-color; - border-bottom: $reactflow-node-border-width solid $reactflow-node-border-color; - } - } - - .#{eccgui}-graphviz__node__resizer--bottom { - &::after { - content: ""; - position: absolute; - margin: $reactflow-cursor-delimiter-offset; - z-index: 1; - right: -1 * $reactflow-cursor-delimiter-offset; - bottom: 0; - width: $reactflow-node-basesize; - border-bottom: $reactflow-node-border-width solid $reactflow-node-border-color; - } - } - } - &.react-flow__node-default { width: unset !important; height: unset !important; @@ -90,10 +49,38 @@ &:hover { box-shadow: 0 0 0 6 * $reactflow-node-border-width rgba($reactflow-edge-stroke-color-selected, 0.05); } + + &.is-resizable-vertical { + max-height: unset; + } } -.#{$eccgui}-graphviz__node--flexible-height { - height: auto !important; +.#{$eccgui}-graphviz__node--tiny { + width: $reactflow-node-basesize * 4; + min-height: $reactflow-node-basesize; + max-height: $reactflow-node-basesize * 4; +} + +.#{$eccgui}-graphviz__node--small { + width: $reactflow-node-basesize * 5; + min-height: $reactflow-node-basesize; + max-height: $reactflow-node-basesize * 8; +} + +.#{$eccgui}-graphviz__node--medium { + width: $reactflow-node-basesize * 8; + min-height: $reactflow-node-basesize; + max-height: $reactflow-node-basesize * 13; +} + +.#{$eccgui}-graphviz__node--large { + width: $reactflow-node-basesize * 13; + min-height: $reactflow-node-basesize; + max-height: $reactflow-node-basesize * 13; +} + +.#{$eccgui}-graphviz__node--fullwidth { + width: 100%; } .#{$eccgui}-graphviz__node--minimal-rectangular, @@ -245,71 +232,58 @@ background-color: $reactflow-node-background-color; } -// Node sizes -.#{$eccgui}-graphviz__node__resizer, -.#{$eccgui}-graphviz__node.is-resizeable { +// Node Resizer + +.#{$eccgui}-graphviz__node.is-resizable-horizontal, +.#{$eccgui}-graphviz__node.is-resizable-vertical { min-width: 2.5 * $reactflow-node-basesize; min-height: 2.5 * $reactflow-node-basesize; } -.#{eccgui}-graphviz__node__resizer--fit-content { - min-height: fit-content !important; +.#{$eccgui}-graphviz__node__resizer--cursorhandles { + position: absolute; + height: 0; + width: 0; + bottom: 0; + right: 0; + overflow: visible; + display: none; + + & > div { + overflow: visible; + z-index: 0 !important; + height: $reactflow-cursor-delimiter-offset * 3 !important; + width: $reactflow-cursor-delimiter-offset * 3 !important; + top: unset !important; + left: unset !important; + bottom: -1 * $reactflow-cursor-delimiter-offset !important; + right: -1 * $reactflow-cursor-delimiter-offset !important; + border-bottom: $reactflow-node-border-width solid $reactflow-node-border-color; + border-right: $reactflow-node-border-width solid $reactflow-node-border-color; + + .#{$eccgui}-graphviz__node__resizer--right:not(.#{$eccgui}-graphviz__node__resizer--bottom) & { + bottom: 0 !important; + border-bottom: none; + } + .#{$eccgui}-graphviz__node__resizer--bottom:not(.#{$eccgui}-graphviz__node__resizer--right) & { + right: 0 !important; + border-right: none; + } + } } .#{$eccgui}-graphviz__node__resizer { - & > .is-resizeable { - max-height: none !important; - } + min-width: 2.5 * $reactflow-node-basesize; + min-height: 2.5 * $reactflow-node-basesize; + .selected &, &:hover { .#{$eccgui}-graphviz__node__resizer--cursorhandles { - & > div { - overflow: auto; - z-index: 2; - } - } - - .#{$eccgui}-graphviz__node__resizer--cursorhandles-right { - & > div { - top: $reactflow-cursor-delimiter-offset !important; - bottom: $reactflow-cursor-delimiter-offset !important; - right: $reactflow-cursor-delimiter-offset !important; - height: unset !important; - width: $reactflow-node-basesize !important; - z-index: 1 !important; - } + display: block; } } } -.#{$eccgui}-graphviz__node--tiny { - width: $reactflow-node-basesize * 4; - min-height: $reactflow-node-basesize; - max-height: $reactflow-node-basesize * 4; -} - -.#{$eccgui}-graphviz__node--small { - width: $reactflow-node-basesize * 5; - min-height: $reactflow-node-basesize; - max-height: $reactflow-node-basesize * 8; -} - -.#{$eccgui}-graphviz__node--medium { - width: $reactflow-node-basesize * 8; - min-height: $reactflow-node-basesize; - max-height: $reactflow-node-basesize * 13; -} - -.#{$eccgui}-graphviz__node--large { - width: $reactflow-node-basesize * 13; - min-height: $reactflow-node-basesize; - max-height: $reactflow-node-basesize * 13; -} - -.#{$eccgui}-graphviz__node--fullwidth:not(.is-resizeable) { - width: 100%; -} - // Node border overwrites .#{$eccgui}-graphviz__node--border-solid { diff --git a/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx b/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx index 828fbf8b0..68f76a284 100644 --- a/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +++ b/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx @@ -15,9 +15,9 @@ import { OverflowText, Tag, TagList, + NodeContent, + NodeContentExtension, } from "./../../../../index"; -import { NodeContent } from "./../NodeContent"; -import { NodeContentExtension } from "./../NodeContentExtension"; import { Default as ContentExtensionExample, SlideOutOfNode as ContentExtensionExampleSlideOut, @@ -131,7 +131,6 @@ export default { const NodeContentExample = (args: any) => { const [reactflowInstance, setReactflowInstance] = useState(null); const [elements, setElements] = useState([] as Elements); - //const [edgeTools, setEdgeTools] = useState(<>); useEffect(() => { setElements([ @@ -206,7 +205,11 @@ Default.args = { export const Resizeable = Template.bind({}); Resizeable.args = { ...Default.args, + resizeMaxDimensions: { width: 1000, height: 500 }, + nodeDimensions: {}, + resizeDirections: { bottom: true, right: true }, onNodeResize: (dimensions) => { + // eslint-disable-next-line no-console console.log("onNodeResize", `new dimensions: ${dimensions.width}x${dimensions.height}`); }, }; From 4c3c81971b13fa5a9c452921333727af05fc2b9e Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Thu, 27 Feb 2025 17:38:42 +0100 Subject: [PATCH 24/31] autoformat --- .../react-flow/nodes/NodeContent.tsx | 153 +++++++++--------- 1 file changed, 80 insertions(+), 73 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 17fa06b85..44e767771 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -27,7 +27,10 @@ type NodeDimensions = { height?: number; }; -type ResizeDirections = { right: true, bottom?: false } | { right?: false, bottom: true } | { right: true, bottom: true }; +type ResizeDirections = + | { right: true; bottom?: false } + | { right?: false; bottom: true } + | { right: true; bottom: true }; type IntroductionTime = { /** @@ -354,9 +357,9 @@ export function NodeContent({ const hasValidResizeDirection = resizeDirections.bottom || resizeDirections.right; const isResizable = typeof onNodeResize === "function" && hasValidResizeDirection && minimalShape === "none"; - const [width, setWidth] = React.useState(nodeDimensions?.width ?? undefined); - const [height, setHeight] = React.useState(nodeDimensions?.height ?? undefined); - + const [width, setWidth] = React.useState(nodeDimensions?.width ?? undefined); + const [height, setHeight] = React.useState(nodeDimensions?.height ?? undefined); + const originalSize = {} as NodeDimensions; let zoom = 1; @@ -387,11 +390,11 @@ export function NodeContent({ flowVersionCheck === "legacy" ? ([] as NodeContentHandleLegacyProps[]) : ([] as NodeContentHandleNextProps[]); const saveOriginalSize = () => { - if ((!originalSize.width && !originalSize.height)) { + if (!originalSize.width && !originalSize.height) { originalSize.width = nodeContentRef.current.offsetWidth as number; originalSize.height = nodeContentRef.current.offsetHeight as number; } - } + }; // update node dimensions when resized React.useEffect(() => { @@ -405,23 +408,18 @@ export function NodeContent({ React.useEffect(() => { saveOriginalSize(); const currentClassNames = nodeContentRef.current.classList; - const resizingActive = ( + const resizingActive = resizeDirections.right === currentClassNames.contains("is-resizable-horizontal") && - resizeDirections.bottom === currentClassNames.contains("is-resizable-vertical") - ) + resizeDirections.bottom === currentClassNames.contains("is-resizable-vertical"); if (isResizable && !resizingActive) { if (currentClassNames.contains("is-resizable-horizontal")) { - nodeContentRef.current.classList.remove( - "is-resizable-horizontal" - ); + nodeContentRef.current.classList.remove("is-resizable-horizontal"); } if (currentClassNames.contains("is-resizable-vertical")) { - nodeContentRef.current.classList.remove( - "is-resizable-vertical" - ); + nodeContentRef.current.classList.remove("is-resizable-vertical"); } - + const newWidth = validateWidth(originalSize?.width as number); const newHeight = validateHeight(originalSize?.height as number); @@ -429,15 +427,11 @@ export function NodeContent({ setHeight(newHeight); if (resizeDirections.right) { - nodeContentRef.current.classList.add( - "is-resizable-horizontal" - ); + nodeContentRef.current.classList.add("is-resizable-horizontal"); } if (resizeDirections.bottom) { - nodeContentRef.current.classList.add( - "is-resizable-vertical" - ); - } + nodeContentRef.current.classList.add("is-resizable-vertical"); + } } }, [nodeContentRef, onNodeResize, minimalShape, resizeDirections]); @@ -506,12 +500,15 @@ export function NodeContent({ highlightColor ); - const resizableStyles = isResizable && ((width??0) + (height??0)) > 0 ? { - width, - height, - maxWidth: resizeMaxDimensions?.width ?? undefined, - maxHeight: resizeMaxDimensions?.height ?? undefined, - } : {}; + const resizableStyles = + isResizable && (width ?? 0) + (height ?? 0) > 0 + ? { + width, + height, + maxWidth: resizeMaxDimensions?.width ?? undefined, + maxHeight: resizeMaxDimensions?.height ?? undefined, + } + : {}; const introductionStyles = introductionTime && !introductionDone @@ -642,67 +639,77 @@ export function NodeContent({ ); - const validateWidth = (resizedWidth: number) : number | undefined => { + const validateWidth = (resizedWidth: number): number | undefined => { // only allow value if resize direction is allowed - if (!resizeDirections.right) { return undefined; } + if (!resizeDirections.right) { + return undefined; + } // we need to check because there is probably a min value defined via CSS const min = nodeContentRef.current.offsetWidth; // we need to check for a given max value const max = resizeMaxDimensions?.width ?? Infinity; const validatedWidth = Math.max(Math.min(resizedWidth, max), min); return validatedWidth; - } + }; - const validateHeight = (resizedHeight: number) : number | undefined => { - if (!resizeDirections.bottom) { return undefined; } + const validateHeight = (resizedHeight: number): number | undefined => { + if (!resizeDirections.bottom) { + return undefined; + } const min = nodeContentRef.current.offsetHeight; const max = resizeMaxDimensions?.height ?? Infinity; const validatedHeight = Math.max(Math.min(resizedHeight, max), min); return validatedHeight; - } + }; const resizableNode = () => { const size = { height: height ?? "auto", width: width ?? "auto" }; - return { - if (nodeContentRef.current) { - saveOriginalSize(); - const nextWidth = resizeDirections.right ? (width??originalSize.width??0) + d.width : undefined; - const nextHeight = resizeDirections.bottom ? (height??originalSize.height??0) + d.height : undefined; - if (nextWidth) { - nodeContentRef.current.style.width = `${nextWidth}px`; + return ( + { + if (nodeContentRef.current) { + saveOriginalSize(); + const nextWidth = resizeDirections.right + ? (width ?? originalSize.width ?? 0) + d.width + : undefined; + const nextHeight = resizeDirections.bottom + ? (height ?? originalSize.height ?? 0) + d.height + : undefined; + if (nextWidth) { + nodeContentRef.current.style.width = `${nextWidth}px`; + } + if (nextHeight) { + nodeContentRef.current.style.height = `${nextHeight}px`; + } } - if (nextHeight) { - nodeContentRef.current.style.height = `${nextHeight}px`; + }} + onResizeStop={(_0, _1, _2, d) => { + const nextWidth = validateWidth((width ?? 0) + d.width); + const nextHeight = validateHeight((height ?? 0) + d.height); + setWidth(nextWidth); + setHeight(nextHeight); + if (onNodeResize) { + onNodeResize({ + height: nextHeight, + width: nextWidth, + }); } - } - }} - onResizeStop={(_0, _1, _2, d) => { - const nextWidth = validateWidth((width??0) + d.width); - const nextHeight = validateHeight((height??0) + d.height); - setWidth(nextWidth); - setHeight(nextHeight); - if (onNodeResize) { - onNodeResize({ - height: nextHeight, - width: nextWidth, - }); - } - }} - > - {nodeContent} - + }} + > + {nodeContent} + + ); }; return isResizable ? resizableNode() : nodeContent; From 841ab52aaf3950c5b60204cad6b417659f8e8ceb Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Thu, 27 Feb 2025 17:47:10 +0100 Subject: [PATCH 25/31] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 144187220..e3ddcfa34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - implemented support for `intent` states in code editor - `Label` component - added `additionalElements` property to display elements at the end of the label +- `` + - `resizeDirections` to specifiy the axis that can be used to resize the node + - `resizeMaxDimensions` to add maximum values for resizing height/width ## [24.0.1] - 2025-02-06 From 12ea72617e1c2070eeccacae115d66fbe87e5b88 Mon Sep 17 00:00:00 2001 From: arausly Date: Mon, 3 Mar 2025 10:44:45 +0100 Subject: [PATCH 26/31] corrected to right min dimensions --- src/extensions/react-flow/nodes/NodeContent.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 44e767771..458fc3787 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -645,7 +645,7 @@ export function NodeContent({ return undefined; } // we need to check because there is probably a min value defined via CSS - const min = nodeContentRef.current.offsetWidth; + const min = parseFloat(getComputedStyle(nodeContentRef.current).getPropertyValue("min-width")); // we need to check for a given max value const max = resizeMaxDimensions?.width ?? Infinity; const validatedWidth = Math.max(Math.min(resizedWidth, max), min); @@ -656,7 +656,8 @@ export function NodeContent({ if (!resizeDirections.bottom) { return undefined; } - const min = nodeContentRef.current.offsetHeight; + // we need to check because there is probably a min value defined via CSS + const min = parseFloat(getComputedStyle(nodeContentRef.current).getPropertyValue("min-height")); const max = resizeMaxDimensions?.height ?? Infinity; const validatedHeight = Math.max(Math.min(resizedHeight, max), min); return validatedHeight; From 765782dfed4cc2ec49ad8281cc4319935de5ee5f Mon Sep 17 00:00:00 2001 From: arausly Date: Tue, 4 Mar 2025 16:53:11 +0100 Subject: [PATCH 27/31] preserved reset changes in stack --- src/extensions/react-flow/nodes/NodeContent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 458fc3787..77e19280d 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -696,8 +696,8 @@ export function NodeContent({ } }} onResizeStop={(_0, _1, _2, d) => { - const nextWidth = validateWidth((width ?? 0) + d.width); - const nextHeight = validateHeight((height ?? 0) + d.height); + const nextWidth = validateWidth((width ?? originalSize.width ?? 0) + d.width); + const nextHeight = validateHeight((height ?? originalSize.height ?? 0) + d.height); setWidth(nextWidth); setHeight(nextHeight); if (onNodeResize) { From 6184a0f8a8dba9fce291c7481c3a46e94fd54b75 Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Wed, 5 Mar 2025 12:17:45 +0100 Subject: [PATCH 28/31] check resizing for all property changes, otherwise class information is lost --- src/extensions/react-flow/nodes/NodeContent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 77e19280d..fce72e734 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -404,7 +404,7 @@ export function NodeContent({ setHeight(updateHeight); }, [nodeDimensions]); - // initial dimension before resize + // resizing check and conditional enhancements React.useEffect(() => { saveOriginalSize(); const currentClassNames = nodeContentRef.current.classList; @@ -433,7 +433,7 @@ export function NodeContent({ nodeContentRef.current.classList.add("is-resizable-vertical"); } } - }, [nodeContentRef, onNodeResize, minimalShape, resizeDirections]); + }); // need to be done everytime a property is changed an the element is re-rendered, otherwise the resizing class is lost // remove introduction class React.useEffect(() => { From 358ea04bc1b42e2d85cd809fbf4ac8417db03509 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Tue, 11 Mar 2025 15:35:38 +0100 Subject: [PATCH 29/31] Refactoring of NodeContent --- .../react-flow/nodes/NodeContent.tsx | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index fce72e734..b12e1302a 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -359,8 +359,8 @@ export function NodeContent({ const [width, setWidth] = React.useState(nodeDimensions?.width ?? undefined); const [height, setHeight] = React.useState(nodeDimensions?.height ?? undefined); - - const originalSize = {} as NodeDimensions; + // Keeps the inital size of the element + const originalSize = React.useRef({}) let zoom = 1; if (isResizable) @@ -389,12 +389,12 @@ export function NodeContent({ handleStack[Position.Left] = flowVersionCheck === "legacy" ? ([] as NodeContentHandleLegacyProps[]) : ([] as NodeContentHandleNextProps[]); - const saveOriginalSize = () => { - if (!originalSize.width && !originalSize.height) { - originalSize.width = nodeContentRef.current.offsetWidth as number; - originalSize.height = nodeContentRef.current.offsetHeight as number; + React.useEffect(() => { + if(nodeContentRef.current && !(originalSize.current.width || originalSize.current.height)) { + originalSize.current.width = nodeContentRef.current.offsetWidth as number; + originalSize.current.height = nodeContentRef.current.offsetHeight as number; } - }; + }, [!!nodeContentRef.current, (!originalSize.current.width || !originalSize.current.height)]) // update node dimensions when resized React.useEffect(() => { @@ -406,7 +406,6 @@ export function NodeContent({ // resizing check and conditional enhancements React.useEffect(() => { - saveOriginalSize(); const currentClassNames = nodeContentRef.current.classList; const resizingActive = resizeDirections.right === currentClassNames.contains("is-resizable-horizontal") && @@ -420,12 +419,6 @@ export function NodeContent({ nodeContentRef.current.classList.remove("is-resizable-vertical"); } - const newWidth = validateWidth(originalSize?.width as number); - const newHeight = validateHeight(originalSize?.height as number); - - setWidth(newWidth); - setHeight(newHeight); - if (resizeDirections.right) { nodeContentRef.current.classList.add("is-resizable-horizontal"); } @@ -433,7 +426,7 @@ export function NodeContent({ nodeContentRef.current.classList.add("is-resizable-vertical"); } } - }); // need to be done everytime a property is changed an the element is re-rendered, otherwise the resizing class is lost + }, [nodeContentRef.current, onNodeResize, minimalShape, resizeDirections?.bottom, resizeDirections?.right]); // need to be done everytime a property is changed and the element is re-rendered, otherwise the resizing class is lost // remove introduction class React.useEffect(() => { @@ -680,12 +673,11 @@ export function NodeContent({ scale={zoom} onResize={(_0, _1, _2, d) => { if (nodeContentRef.current) { - saveOriginalSize(); const nextWidth = resizeDirections.right - ? (width ?? originalSize.width ?? 0) + d.width + ? (width ?? originalSize.current.width ?? 0) + d.width : undefined; const nextHeight = resizeDirections.bottom - ? (height ?? originalSize.height ?? 0) + d.height + ? (height ?? originalSize.current.height ?? 0) + d.height : undefined; if (nextWidth) { nodeContentRef.current.style.width = `${nextWidth}px`; @@ -696,8 +688,8 @@ export function NodeContent({ } }} onResizeStop={(_0, _1, _2, d) => { - const nextWidth = validateWidth((width ?? originalSize.width ?? 0) + d.width); - const nextHeight = validateHeight((height ?? originalSize.height ?? 0) + d.height); + const nextWidth = validateWidth((width ?? originalSize.current.width ?? 0) + d.width); + const nextHeight = validateHeight((height ?? originalSize.current.height ?? 0) + d.height); setWidth(nextWidth); setHeight(nextHeight); if (onNodeResize) { From 203d3eb62c2ddee09969eec55bfe6be54f4a672e Mon Sep 17 00:00:00 2001 From: Michael Haschke Date: Tue, 11 Mar 2025 17:14:58 +0100 Subject: [PATCH 30/31] fix initial size, updating initial measures and fix clas enahncement --- .../react-flow/nodes/NodeContent.tsx | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index b12e1302a..0bde5954d 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -389,10 +389,14 @@ export function NodeContent({ handleStack[Position.Left] = flowVersionCheck === "legacy" ? ([] as NodeContentHandleLegacyProps[]) : ([] as NodeContentHandleNextProps[]); + const saveOriginalSize = () => { + originalSize.current.width = nodeContentRef.current.offsetWidth as number; + originalSize.current.height = nodeContentRef.current.offsetHeight as number; + } + React.useEffect(() => { if(nodeContentRef.current && !(originalSize.current.width || originalSize.current.height)) { - originalSize.current.width = nodeContentRef.current.offsetWidth as number; - originalSize.current.height = nodeContentRef.current.offsetHeight as number; + saveOriginalSize(); } }, [!!nodeContentRef.current, (!originalSize.current.width || !originalSize.current.height)]) @@ -402,14 +406,38 @@ export function NodeContent({ const updateHeight = nodeDimensions?.height ? validateHeight(nodeDimensions?.height) : undefined; setWidth(updateWidth); setHeight(updateHeight); + if (!nodeDimensions?.width && !nodeDimensions?.height) { + // provoke new measuring if no dimensions are set + saveOriginalSize(); + } }, [nodeDimensions]); - // resizing check and conditional enhancements - React.useEffect(() => { + const isResizingActive = () : boolean => { const currentClassNames = nodeContentRef.current.classList; const resizingActive = resizeDirections.right === currentClassNames.contains("is-resizable-horizontal") && resizeDirections.bottom === currentClassNames.contains("is-resizable-vertical"); + return resizingActive; + } + + // force default size when resizing is activated but no dimensions are set + React.useEffect(() => { + const resizingActive = isResizingActive(); + + if (isResizable && !resizingActive) { + if (!width || !height) { + const newWidth = validateWidth(width ?? originalSize.current?.width as number); + const newHeight = validateHeight(height ?? originalSize.current?.height as number); + setWidth(newWidth); + setHeight(newHeight); + } + } + }, [nodeContentRef.current, onNodeResize, minimalShape, resizeDirections?.bottom, resizeDirections?.right]); // need to be done everytime a property is changed and the element is re-rendered, otherwise the resizing class is lost + + // conditional enhancements for activated resizing + React.useEffect(() => { + const currentClassNames = nodeContentRef.current.classList; + const resizingActive = isResizingActive(); if (isResizable && !resizingActive) { if (currentClassNames.contains("is-resizable-horizontal")) { @@ -426,7 +454,7 @@ export function NodeContent({ nodeContentRef.current.classList.add("is-resizable-vertical"); } } - }, [nodeContentRef.current, onNodeResize, minimalShape, resizeDirections?.bottom, resizeDirections?.right]); // need to be done everytime a property is changed and the element is re-rendered, otherwise the resizing class is lost + }); // need to be done everytime a property is changed and the element is re-rendered, otherwise the resizing class is lost // remove introduction class React.useEffect(() => { From 3877e5ae5665112b1aa6cff6f246857dd2f5e776 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Wed, 12 Mar 2025 09:29:48 +0100 Subject: [PATCH 31/31] Small clean-ups --- src/extensions/react-flow/nodes/NodeContent.tsx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/extensions/react-flow/nodes/NodeContent.tsx b/src/extensions/react-flow/nodes/NodeContent.tsx index 0bde5954d..99add1745 100644 --- a/src/extensions/react-flow/nodes/NodeContent.tsx +++ b/src/extensions/react-flow/nodes/NodeContent.tsx @@ -359,7 +359,7 @@ export function NodeContent({ const [width, setWidth] = React.useState(nodeDimensions?.width ?? undefined); const [height, setHeight] = React.useState(nodeDimensions?.height ?? undefined); - // Keeps the inital size of the element + // Keeps the initial size of the element const originalSize = React.useRef({}) let zoom = 1; @@ -398,9 +398,9 @@ export function NodeContent({ if(nodeContentRef.current && !(originalSize.current.width || originalSize.current.height)) { saveOriginalSize(); } - }, [!!nodeContentRef.current, (!originalSize.current.width || !originalSize.current.height)]) + }, [!!nodeContentRef.current, !(originalSize.current.width || originalSize.current.height)]) - // update node dimensions when resized + // Update width and height when node dimensions parameters has changed React.useEffect(() => { const updateWidth = nodeDimensions?.width ? validateWidth(nodeDimensions?.width) : undefined; const updateHeight = nodeDimensions?.height ? validateHeight(nodeDimensions?.height) : undefined; @@ -412,13 +412,11 @@ export function NodeContent({ } }, [nodeDimensions]); - const isResizingActive = () : boolean => { + const isResizingActive = React.useCallback((): boolean => { const currentClassNames = nodeContentRef.current.classList; - const resizingActive = - resizeDirections.right === currentClassNames.contains("is-resizable-horizontal") && + return resizeDirections.right === currentClassNames.contains("is-resizable-horizontal") && resizeDirections.bottom === currentClassNames.contains("is-resizable-vertical"); - return resizingActive; - } + }, []) // force default size when resizing is activated but no dimensions are set React.useEffect(() => { @@ -432,7 +430,7 @@ export function NodeContent({ setHeight(newHeight); } } - }, [nodeContentRef.current, onNodeResize, minimalShape, resizeDirections?.bottom, resizeDirections?.right]); // need to be done everytime a property is changed and the element is re-rendered, otherwise the resizing class is lost + }, [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 // conditional enhancements for activated resizing React.useEffect(() => {