From de71b5af6516409065922a9f2043820883d41c40 Mon Sep 17 00:00:00 2001 From: braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Wed, 4 Jan 2023 12:50:23 +0100 Subject: [PATCH] feat(core): allow setting padding for extent `parent` Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com> --- packages/core/src/types/node.ts | 8 +++- packages/core/src/utils/drag.ts | 72 +++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/packages/core/src/types/node.ts b/packages/core/src/types/node.ts index 149cf484..c5d5e914 100644 --- a/packages/core/src/types/node.ts +++ b/packages/core/src/types/node.ts @@ -4,6 +4,12 @@ import type { DefaultNodeTypes, NodeComponent } from './components' import type { HandleConnectable, HandleElement, ValidConnectionFunc } from './handle' import type { CustomEvent, NodeEventsHandler, NodeEventsOn } from './hooks' +export interface ExtendedParentExtent { + range: 'parent' + /** Values are top, right, bottom, left, you can use these the same as CSS padding */ + padding: [number] | [number, number] | [number, number, number] | [number, number, number, number] +} + /** Defined as [[x-from, y-from], [x-to, y-to]] **/ export type CoordinateExtent = [[number, number], [number, number]] @@ -41,7 +47,7 @@ export interface Node): boolean { let current = target @@ -59,31 +67,61 @@ export function getEventHandlerParams({ return [id ? extendedDragItems.find((n) => n.id === id)! : extendedDragItems[0], extendedDragItems] } +function getExtentPadding(padding: number[]) { + switch (padding.length) { + case 1: + return [padding[0], padding[0], padding[0], padding[0]] + case 2: + return [padding[0], padding[1], padding[0], padding[1]] + case 3: + return [padding[0], padding[1], padding[2], padding[1]] + default: + return padding || [0, 0, 0, 0] + } +} + +function getParentExtent( + currentExtent: ExtendedParentExtent | 'parent', + node: GraphNode | NodeDragItem, + parent: GraphNode, +): CoordinateExtent | false { + const [top, right, bottom, left] = typeof currentExtent !== 'string' ? getExtentPadding(currentExtent.padding) : [0, 0, 0, 0] + + if ( + parent && + isNumber(parent.computedPosition.x) && + isNumber(parent.computedPosition.y) && + isNumber(parent.dimensions.width) && + isNumber(parent.dimensions.height) + ) { + return [ + [parent.computedPosition.x + left, parent.computedPosition.y + top], + [ + parent.computedPosition.x + (parent.dimensions.width - node.dimensions.width) - right, + parent.computedPosition.y + (parent.dimensions.height - node.dimensions.height) - bottom, + ], + ] + } + + return false +} + export function getExtent(item: T, extent?: CoordinateExtent, parent?: GraphNode) { let currentExtent = item.extent || extent - if (item.extent === 'parent') { + if (item.extent === 'parent' || (!Array.isArray(item.extent) && item.extent?.range === 'parent')) { if (item.parentNode && parent && item.dimensions.width && item.dimensions.height) { - currentExtent = - parent && - isNumber(parent.computedPosition.x) && - isNumber(parent.computedPosition.y) && - isNumber(parent.dimensions.width) && - isNumber(parent.dimensions.height) - ? [ - [parent.computedPosition.x, parent.computedPosition.y], - [ - parent.computedPosition.x + parent.dimensions.width - item.dimensions.width, - parent.computedPosition.y + parent.dimensions.height - item.dimensions.height, - ], - ] - : currentExtent + const parentExtent = getParentExtent(item.extent, item, parent) + + if (parentExtent) { + currentExtent = parentExtent + } } else { warn('Only child nodes can use a parent extent.') currentExtent = extent } - } else if (item.extent && parent) { + } else if (Array.isArray(item.extent) && item.extent && parent) { const parentX = parent.computedPosition.x const parentY = parent.computedPosition.y