import { type NodeDragItem, type XYPosition, InternalNodeBase, NodeBase, NodeLookup } from '../types'; export function isParentSelected(node: NodeType, nodeLookup: NodeLookup): boolean { if (!node.parentId) { return false; } const parentNode = nodeLookup.get(node.parentId); if (!parentNode) { return false; } if (parentNode.selected) { return true; } return isParentSelected(parentNode, nodeLookup); } export function hasSelector(target: Element | EventTarget | null, selector: string, domNode: Element): boolean { let current = target as Partial | null | undefined; do { if (current?.matches?.(selector)) return true; if (current === domNode) return false; current = current?.parentElement; } while (current); return false; } // looks for all selected nodes and created a NodeDragItem for each of them export function getDragItems( nodeLookup: Map>, nodesDraggable: boolean, mousePos: XYPosition, nodeId?: string ): Map { const dragItems = new Map(); for (const [id, node] of nodeLookup) { if ( (node.selected || node.id === nodeId) && (!node.parentId || !isParentSelected(node, nodeLookup)) && (node.draggable || (nodesDraggable && typeof node.draggable === 'undefined')) ) { const internalNode = nodeLookup.get(id); if (internalNode) { dragItems.set(id, { id, position: internalNode.position || { x: 0, y: 0 }, distance: { x: mousePos.x - internalNode.internals.positionAbsolute.x, y: mousePos.y - internalNode.internals.positionAbsolute.y, }, extent: internalNode.extent, parentId: internalNode.parentId, origin: internalNode.origin, expandParent: internalNode.expandParent, internals: { positionAbsolute: internalNode.internals.positionAbsolute || { x: 0, y: 0 }, }, measured: { width: internalNode.measured.width ?? 0, height: internalNode.measured.height ?? 0, }, }); } } } return dragItems; } // returns two params: // 1. the dragged node (or the first of the list, if we are dragging a node selection) // 2. array of selected nodes (for multi selections) export function getEventHandlerParams({ nodeId, dragItems, nodeLookup, dragging = true, }: { nodeId?: string; dragItems: Map; nodeLookup: Map; dragging?: boolean; }): [NodeBase, NodeBase[]] { const nodesFromDragItems: NodeBase[] = []; for (const [id, dragItem] of dragItems) { const node = nodeLookup.get(id)?.internals.userNode; if (node) { nodesFromDragItems.push({ ...node, position: dragItem.position, dragging, }); } } if (!nodeId) { return [nodesFromDragItems[0], nodesFromDragItems]; } const node = nodeLookup.get(nodeId)?.internals.userNode; return [ !node ? nodesFromDragItems[0] : { ...node, position: dragItems.get(nodeId)?.position || node.position, dragging, }, nodesFromDragItems, ]; }