diff --git a/examples/react/src/examples/NodeResizer/index.tsx b/examples/react/src/examples/NodeResizer/index.tsx index a9412da7..968ec9d7 100644 --- a/examples/react/src/examples/NodeResizer/index.tsx +++ b/examples/react/src/examples/NodeResizer/index.tsx @@ -32,96 +32,96 @@ const nodeStyle = { const initialEdges: Edge[] = []; const initialNodes: Node[] = [ - { - id: '1', - type: 'defaultResizer', - data: { label: 'default resizer' }, - position: { x: 0, y: 0 }, - origin: [1, 1], - style: { ...nodeStyle }, - }, - { - id: '1a', - type: 'defaultResizer', - data: { - label: 'default resizer with min and max dimensions', - minWidth: 100, - minHeight: 80, - maxWidth: 200, - maxHeight: 200, - }, - position: { x: 0, y: 60 }, - width: 100, - height: 80, - style: { ...nodeStyle }, - }, - { - id: '1b', - type: 'defaultResizer', - data: { - label: 'default resizer with initial size and aspect ratio', - keepAspectRatio: true, - minWidth: 100, - minHeight: 60, - maxWidth: 400, - maxHeight: 400, - }, - position: { x: 250, y: 0 }, - width: 174, - height: 123, - style: { - ...nodeStyle, - }, - }, - { - id: '2', - type: 'customResizer', - data: { label: 'custom resize icon' }, - position: { x: 0, y: 200 }, - width: 100, - height: 60, - style: { ...nodeStyle }, - }, - { - id: '3', - type: 'verticalResizer', - data: { label: 'vertical resizer' }, - position: { x: 250, y: 200 }, - style: { ...nodeStyle }, - }, - { - id: '3a', - type: 'verticalResizer', - data: { - label: 'vertical resizer with min/maxHeight and aspect ratio', - minHeight: 50, - maxHeight: 200, - keepAspectRatio: true, - }, - position: { x: 400, y: 200 }, - height: 50, - style: { ...nodeStyle }, - }, - { - id: '4', - type: 'horizontalResizer', - data: { - label: 'horizontal resizer with aspect ratio', - keepAspectRatio: true, - minHeight: 20, - maxHeight: 80, - maxWidth: 300, - }, - position: { x: 250, y: 300 }, - style: { ...nodeStyle }, - }, - { - id: '4a', - type: 'horizontalResizer', - data: { label: 'horizontal resizer with maxWidth', maxWidth: 300 }, - position: { x: 250, y: 400 }, - style: { ...nodeStyle }, - }, + // { + // id: '1', + // type: 'defaultResizer', + // data: { label: 'default resizer' }, + // position: { x: 0, y: 0 }, + // origin: [1, 1], + // style: { ...nodeStyle }, + // }, + // { + // id: '1a', + // type: 'defaultResizer', + // data: { + // label: 'default resizer with min and max dimensions', + // minWidth: 100, + // minHeight: 80, + // maxWidth: 200, + // maxHeight: 200, + // }, + // position: { x: 0, y: 60 }, + // width: 100, + // height: 80, + // style: { ...nodeStyle }, + // }, + // { + // id: '1b', + // type: 'defaultResizer', + // data: { + // label: 'default resizer with initial size and aspect ratio', + // keepAspectRatio: true, + // minWidth: 100, + // minHeight: 60, + // maxWidth: 400, + // maxHeight: 400, + // }, + // position: { x: 250, y: 0 }, + // width: 174, + // height: 123, + // style: { + // ...nodeStyle, + // }, + // }, + // { + // id: '2', + // type: 'customResizer', + // data: { label: 'custom resize icon' }, + // position: { x: 0, y: 200 }, + // width: 100, + // height: 60, + // style: { ...nodeStyle }, + // }, + // { + // id: '3', + // type: 'verticalResizer', + // data: { label: 'vertical resizer' }, + // position: { x: 250, y: 200 }, + // style: { ...nodeStyle }, + // }, + // { + // id: '3a', + // type: 'verticalResizer', + // data: { + // label: 'vertical resizer with min/maxHeight and aspect ratio', + // minHeight: 50, + // maxHeight: 200, + // keepAspectRatio: true, + // }, + // position: { x: 400, y: 200 }, + // height: 50, + // style: { ...nodeStyle }, + // }, + // { + // id: '4', + // type: 'horizontalResizer', + // data: { + // label: 'horizontal resizer with aspect ratio', + // keepAspectRatio: true, + // minHeight: 20, + // maxHeight: 80, + // maxWidth: 300, + // }, + // position: { x: 250, y: 300 }, + // style: { ...nodeStyle }, + // }, + // { + // id: '4a', + // type: 'horizontalResizer', + // data: { label: 'horizontal resizer with maxWidth', maxWidth: 300 }, + // position: { x: 250, y: 400 }, + // style: { ...nodeStyle }, + // }, { id: '5', type: 'defaultResizer', @@ -130,35 +130,36 @@ const initialNodes: Node[] = [ width: 300, height: 400, style: { ...nodeStyle }, - origin: [0, 0], - }, - { - id: '5a', - type: 'defaultResizer', - data: { - label: 'Child with extent: parent', - }, - position: { x: 50, y: 50 }, - parentId: '5', - extent: 'parent', - width: 50, - height: 100, - style: { ...nodeStyle }, - }, - { - id: '5b', - type: 'defaultResizer', - data: { label: 'Child with expandParent' }, - position: { x: 150, y: 100 }, - parentId: '5', - expandParent: true, - style: { ...nodeStyle }, }, + // { + // id: '5a', + // type: 'defaultResizer', + // data: { + // label: 'Child with extent: parent', + // }, + // position: { x: 50, y: 50 }, + // parentId: '5', + // extent: 'parent', + // width: 50, + // height: 100, + // style: { ...nodeStyle }, + // }, + // { + // id: '5b', + // type: 'defaultResizer', + // data: { label: 'Child with expandParent' }, + // position: { x: 150, y: 100 }, + // parentId: '5', + // expandParent: true, + // style: { ...nodeStyle }, + // }, { id: '5c', type: 'defaultResizer', - data: { label: 'Child with expandParent & keepAspectRatio', keepAspectRatio: true }, - position: { x: 25, y: 200 }, + data: { label: 'Child with expandParent & keepAspectRatio' }, + position: { x: 250, y: 200 }, + height: 100, + width: 100, parentId: '5', expandParent: true, style: { ...nodeStyle }, diff --git a/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx b/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx index 9f5ac4fd..517dbd9f 100644 --- a/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx +++ b/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx @@ -67,11 +67,10 @@ function ResizeControl({ }, onChange: (change: XYResizerChange, childChanges: XYResizerChildChange[]) => { const { triggerNodeChanges, nodeLookup, parentLookup, nodeOrigin } = store.getState(); - const changes: NodeChange[] = []; const nextPosition = { x: change.x, y: change.y }; - const node = nodeLookup.get(id); + if (node && node.expandParent && node.parentId) { const origin = node.origin ?? nodeOrigin; const width = change.width ?? node.measured.width!; diff --git a/packages/system/src/utils/store.ts b/packages/system/src/utils/store.ts index ae0de3f7..60184f16 100644 --- a/packages/system/src/utils/store.ts +++ b/packages/system/src/utils/store.ts @@ -172,6 +172,7 @@ export function handleExpandParent( parentExpansions.get(child.parentId)?.expandedRect ?? nodeToRect(parent, parent.origin ?? nodeOrigin); const expandedRect = getBoundsOfRects(parentRect, child.rect); + parentExpansions.set(child.parentId, { expandedRect, parent }); } diff --git a/packages/system/src/xyresizer/XYResizer.ts b/packages/system/src/xyresizer/XYResizer.ts index 5188a424..695b1f0a 100644 --- a/packages/system/src/xyresizer/XYResizer.ts +++ b/packages/system/src/xyresizer/XYResizer.ts @@ -3,7 +3,15 @@ import { select } from 'd3-selection'; import { getControlDirection, getDimensionsAfterResize, getResizeDirection } from './utils'; import { getPointerPosition } from '../utils'; -import type { CoordinateExtent, NodeBase, NodeLookup, NodeOrigin, Transform, XYPosition } from '../types'; +import type { + CoordinateExtent, + InternalNodeBase, + NodeBase, + NodeLookup, + NodeOrigin, + Transform, + XYPosition, +} from '../types'; import type { OnResize, OnResizeEnd, OnResizeStart, ResizeDragEvent, ShouldResize, ControlPosition } from './types'; const initPrevValues = { width: 0, height: 0, x: 0, y: 0 }; @@ -100,9 +108,9 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X const controlDirection = getControlDirection(controlPosition); - let node: NodeBase | undefined = undefined; + let node: InternalNodeBase | undefined = undefined; let childNodes: XYResizerChildChange[] = []; - let parentNode: NodeBase | undefined = undefined; // Needed to fix expandParent + let parentNode: InternalNodeBase | undefined = undefined; // Needed to fix expandParent let parentExtent: CoordinateExtent | undefined = undefined; let childExtent: CoordinateExtent | undefined = undefined; @@ -118,8 +126,8 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid }); prevValues = { - width: node.measured?.width ?? 0, - height: node.measured?.height ?? 0, + width: node.measured.width ?? 0, + height: node.measured.height ?? 0, x: node.position.x ?? 0, y: node.position.y ?? 0, }; @@ -132,11 +140,10 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X }; parentNode = undefined; - if (node.extent === 'parent' || node.expandParent) { - parentNode = nodeLookup.get(node.parentId!); - if (parentNode && node.extent === 'parent') { - parentExtent = nodeToParentExtent(parentNode); - } + + if (node.parentId && (node.extent === 'parent' || node.expandParent)) { + parentNode = nodeLookup.get(node.parentId); + parentExtent = parentNode && node.extent === 'parent' ? nodeToParentExtent(parentNode) : undefined; } // Collect all child nodes to correct their relative positions when top/left changes @@ -153,7 +160,7 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X }); if (child.extent === 'parent' || child.expandParent) { - const extent = nodeToChildExtent(child, node!, child.origin ?? nodeOrigin); + const extent = nodeToChildExtent(child, node, child.origin ?? nodeOrigin); if (childExtent) { childExtent = [ @@ -202,7 +209,7 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X return; } - if (isXPosChange || isYPosChange || nodeOrigin[0] === 1 || nodeOrigin[1] == 1) { + if (isXPosChange || isYPosChange || nodeOrigin[0] === 1 || nodeOrigin[1] === 1) { change.x = isXPosChange ? x : prevValues.x; change.y = isYPosChange ? y : prevValues.y; @@ -222,6 +229,8 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X } } + // when top/left changes, correct the relative positions of child nodes + // so that they stay in the same position if (childNodes.length > 0) { const xChange = x - prevX; const yChange = y - prevY; @@ -243,6 +252,12 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X prevValues.height = change.height; } + if (parentNode && node.expandParent) { + if (prevValues.x - (change?.width ?? 0) < 0) { + // console.log(1); + } + } + const direction = getResizeDirection({ width: prevValues.width, prevWidth,