@ii_elif_ii/ui-node-tree 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.cjs +12 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +10 -10
- package/dist/index.css.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/dist/node-tree.css +10 -10
- package/dist/node-tree.css.map +1 -1
- package/package.json +6 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 II-ELIF-II
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
CHANGED
|
@@ -85,7 +85,7 @@ function TreeConnections({
|
|
|
85
85
|
y1: segment.y1 - layoutState.svgBounds.offsetY,
|
|
86
86
|
x2: segment.x2 - layoutState.svgBounds.offsetX,
|
|
87
87
|
y2: segment.y2 - layoutState.svgBounds.offsetY,
|
|
88
|
-
className: "node-line",
|
|
88
|
+
className: "unt-node-line",
|
|
89
89
|
style: {
|
|
90
90
|
strokeDasharray: segment.length,
|
|
91
91
|
strokeDashoffset: segment.length,
|
|
@@ -123,7 +123,13 @@ function axisToFlexJustify(axis) {
|
|
|
123
123
|
}
|
|
124
124
|
return "center";
|
|
125
125
|
}
|
|
126
|
-
function NodeFrame({
|
|
126
|
+
function NodeFrame({
|
|
127
|
+
node,
|
|
128
|
+
className,
|
|
129
|
+
onRef,
|
|
130
|
+
children,
|
|
131
|
+
...props
|
|
132
|
+
}) {
|
|
127
133
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
128
134
|
"div",
|
|
129
135
|
{
|
|
@@ -173,7 +179,9 @@ function renderTreeNode({
|
|
|
173
179
|
flexShrink: 0,
|
|
174
180
|
flexDirection: childrenLayoutIsStack ? "column" : "row",
|
|
175
181
|
alignItems: axisToFlexAlign(childrenLayoutIsStack ? alignX : alignY),
|
|
176
|
-
justifyContent: axisToFlexJustify(
|
|
182
|
+
justifyContent: axisToFlexJustify(
|
|
183
|
+
childrenLayoutIsStack ? alignY : alignX
|
|
184
|
+
),
|
|
177
185
|
gap,
|
|
178
186
|
marginTop: flowDown || stackUnder ? gap : 0,
|
|
179
187
|
marginLeft: flowDown ? node.children?.layout === "stack" ? gap : 0 : stackUnder ? gap / 2 : gap
|
|
@@ -216,7 +224,7 @@ function renderTreeNode({
|
|
|
216
224
|
NodeFrame,
|
|
217
225
|
{
|
|
218
226
|
node,
|
|
219
|
-
className: cn("node-enter unt-tree-node-frame", nodeFrameClassName),
|
|
227
|
+
className: cn("unt-node-enter unt-tree-node-frame", nodeFrameClassName),
|
|
220
228
|
style: {
|
|
221
229
|
justifyContent: axisToFlexJustify(alignX),
|
|
222
230
|
animationDuration: `${layoutState.nodeAnimDuration}s`,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/components/node-tree.tsx","../src/utils/cn.ts","../src/components/tree-connections.tsx","../src/components/tree-renderer.tsx","../src/hooks/use-node-tree-layout.ts"],"sourcesContent":["export { NodeTree } from \"./components/node-tree\";\nexport type {\r\n NodeFrameProps,\r\n NodeTreeAnimationOptions,\r\n NodeTreeClassNameOptions,\r\n NodeTreeConnectionOptions,\r\n NodeTreeFrameOptions,\n NodeTreeLayoutOptions,\n NodeTreeProps,\n TreeNodeChildren,\n TreeNode,\n TreeNodeEdge,\n TreeNodeRenderContext,\n} from \"./types\";\n","import * as React from \"react\";\nimport \"../node-tree.css\";\nimport { cn } from \"../utils/cn\";\nimport { TreeConnections } from \"./tree-connections\";\nimport { TreeRenderer } from \"./tree-renderer\";\nimport { useNodeTreeLayout } from \"../hooks/use-node-tree-layout\";\nimport type { AlignAxis, NodeTreeProps } from \"../types\";\n\r\nconst NodeTree = React.forwardRef<HTMLDivElement, NodeTreeProps>(\r\n (\r\n {\r\n className,\r\n nodeTree,\r\n layout,\r\n connection,\r\n animation,\r\n nodeFrame,\r\n debug = false,\r\n style,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n const containerRef = React.useRef<HTMLDivElement | null>(null);\r\n const nodeRefs = React.useRef(new Map<string, HTMLDivElement>());\r\n const registerNode = React.useCallback(\r\n (id: string, element: HTMLDivElement | null) => {\r\n const registry = nodeRefs.current;\r\n if (element) {\r\n registry.set(id, element);\r\n } else {\r\n registry.delete(id);\r\n }\r\n },\r\n [],\r\n );\r\n\r\n const resolvedAlign = layout?.align ?? \"center\";\r\n const resolvedDirection = layout?.direction ?? \"down\";\r\n const resolvedRootLayout = layout?.root ?? \"stack\";\r\n const resolvedPaddingContainer = layout?.containerPadding ?? 128;\r\n const resolvedPadding = layout?.padding ?? 64;\r\n const resolvedGap = layout?.gap ?? 64;\r\n const resolvedStrokeColor = connection?.color ?? \"rgba(255,255,255)\";\r\n const resolvedStrokeWidth = connection?.width ?? 1;\r\n const resolvedAnimationDurationMs = animation?.durationMs ?? 2000;\r\n const resolvedNodeFrameStyle = nodeFrame?.style;\r\n\r\n const { doneNodes, layoutState } = useNodeTreeLayout({\r\n nodeTree,\r\n direction: resolvedDirection,\r\n gap: resolvedGap,\r\n padding: resolvedPadding,\r\n animationSpeed: resolvedAnimationDurationMs,\r\n debug,\r\n containerRef,\r\n nodeRefs,\r\n });\r\n\r\n const flowDown = resolvedDirection === \"down\";\r\n const alignValue = resolvedAlign;\r\n const alignX: AlignAxis =\r\n typeof alignValue === \"string\" ? alignValue : alignValue.x;\r\n const alignY: AlignAxis =\r\n typeof alignValue === \"string\" ? \"start\" : alignValue.y;\r\n const resolvedConnectionOpacity = connection?.opacity ?? (debug ? 1 : 0.1);\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={cn(\"unt-tree-root-container\", className?.root)}\r\n style={style}\r\n {...props}\r\n >\r\n <div\r\n ref={containerRef}\r\n className={cn(\"unt-tree-canvas\", className?.canvas)}\r\n style={{ padding: resolvedPaddingContainer }}\r\n >\r\n <TreeConnections\r\n layoutState={layoutState}\r\n debug={debug}\r\n strokeColor={resolvedStrokeColor}\r\n strokeWidth={resolvedStrokeWidth}\r\n opacity={resolvedConnectionOpacity}\r\n className={className?.connections}\r\n />\r\n <TreeRenderer\r\n nodeTree={nodeTree}\r\n rootLayout={resolvedRootLayout}\r\n flowDown={flowDown}\r\n alignX={alignX}\r\n alignY={alignY}\r\n gap={resolvedGap}\r\n debug={debug}\r\n layoutState={layoutState}\r\n doneNodes={doneNodes}\r\n registerNode={registerNode}\r\n rendererClassName={className?.renderer}\r\n nodeFrameClassName={className?.frame}\r\n nodeFrameStyle={resolvedNodeFrameStyle}\r\n />\r\n </div>\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nNodeTree.displayName = \"NodeTree\";\r\n\r\nexport { NodeTree };\r\n","import { clsx, type ClassValue } from \"clsx\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return clsx(inputs);\r\n}\r\n","import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport type { NodeTreeLayoutState } from \"../types\";\n\r\ntype TreeConnectionsProps = {\r\n layoutState: NodeTreeLayoutState;\r\n debug: boolean;\r\n strokeColor: string;\r\n strokeWidth: number;\r\n opacity: number;\r\n className?: string;\r\n};\r\n\r\nexport function TreeConnections({\r\n layoutState,\r\n debug,\r\n strokeColor,\r\n strokeWidth,\r\n opacity,\r\n className,\r\n}: TreeConnectionsProps) {\r\n if (!layoutState.svgBounds) {\r\n return null;\r\n }\r\n\r\n return (\r\n <svg\r\n className={cn(\"unt-tree-connections\", className)}\r\n width={layoutState.svgBounds.width}\r\n height={layoutState.svgBounds.height}\r\n viewBox={`0 0 ${layoutState.svgBounds.width} ${layoutState.svgBounds.height}`}\r\n style={{\r\n left: layoutState.svgBounds.offsetX,\r\n top: layoutState.svgBounds.offsetY,\r\n opacity,\r\n }}\r\n >\r\n {layoutState.segments.map((segment) => {\r\n const debugPalette = [\r\n \"#22d3ee\",\r\n \"#a855f7\",\r\n \"#f59e0b\",\r\n \"#10b981\",\r\n \"#f97316\",\r\n \"#38bdf8\",\r\n ];\r\n const lineColor = debug\r\n ? debugPalette[segment.colorIndex % debugPalette.length]\r\n : strokeColor;\r\n return (\r\n <line\r\n key={`${segment.x1}-${segment.y1}-${segment.x2}-${segment.y2}-${segment.delay}`}\r\n x1={segment.x1 - layoutState.svgBounds!.offsetX}\r\n y1={segment.y1 - layoutState.svgBounds!.offsetY}\r\n x2={segment.x2 - layoutState.svgBounds!.offsetX}\r\n y2={segment.y2 - layoutState.svgBounds!.offsetY}\r\n className=\"node-line\"\r\n style={{\r\n strokeDasharray: segment.length,\r\n strokeDashoffset: segment.length,\r\n animationDelay: `${segment.delay}s`,\r\n animationDuration: `${segment.duration}s`,\r\n }}\r\n stroke={lineColor}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n );\r\n })}\r\n </svg>\r\n );\r\n}\r\n","import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport type {\n AlignAxis,\n NodeFrameProps,\n NodeTreeLayoutState,\n TreeNode,\n} from \"../types\";\n\r\ntype TreeRendererProps = {\r\n nodeTree: TreeNode[];\n rootLayout: \"stack\" | \"row\";\r\n flowDown: boolean;\r\n alignX: AlignAxis;\r\n alignY: AlignAxis;\r\n gap: number;\r\n debug: boolean;\r\n layoutState: NodeTreeLayoutState;\r\n doneNodes: Set<string>;\r\n registerNode: (id: string, element: HTMLDivElement | null) => void;\r\n rendererClassName?: string;\r\n nodeFrameClassName?: string;\r\n nodeFrameStyle?: React.CSSProperties;\r\n};\r\n\r\nfunction axisToFlexAlign(axis: AlignAxis): React.CSSProperties[\"alignItems\"] {\r\n if (axis === \"start\") {\r\n return \"flex-start\";\r\n }\r\n if (axis === \"end\") {\r\n return \"flex-end\";\r\n }\r\n return \"center\";\r\n}\r\n\r\nfunction axisToFlexJustify(axis: AlignAxis): React.CSSProperties[\"justifyContent\"] {\r\n if (axis === \"start\") {\r\n return \"flex-start\";\r\n }\r\n if (axis === \"end\") {\r\n return \"flex-end\";\r\n }\r\n return \"center\";\r\n}\r\n\r\nfunction NodeFrame({ node, className, onRef, children, ...props }: NodeFrameProps) {\r\n return (\r\n <div\r\n ref={(element) => {\r\n onRef(node.id, element);\r\n }}\r\n className={cn(\"unt-tree-node-hit\", className)}\r\n data-nodeframe\r\n data-viewport-no-pan\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nfunction renderTreeNode({\r\n node,\r\n index,\r\n parentId,\r\n depth,\r\n path,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n}: {\r\n node: TreeNode;\n index: number;\r\n parentId?: string;\r\n depth: number;\r\n path: Set<string>;\r\n flowDown: boolean;\r\n alignX: AlignAxis;\r\n alignY: AlignAxis;\r\n gap: number;\r\n debug: boolean;\r\n layoutState: NodeTreeLayoutState;\r\n doneNodes: Set<string>;\r\n registerNode: (id: string, element: HTMLDivElement | null) => void;\r\n nodeFrameClassName?: string;\r\n nodeFrameStyle?: React.CSSProperties;\r\n}): React.ReactNode {\r\n const stackUnder = !flowDown && node.children?.layout === \"stack\";\r\n if (path.has(node.id)) {\r\n return null;\r\n }\r\n\r\n path.add(node.id);\r\n const childrenLayoutIsStack = node.children?.layout === \"stack\" || !flowDown;\r\n const childCount = node.children?.nodes.length ?? 0;\r\n const isLeaf = childCount === 0;\r\n const pathIds = [...path];\r\n const childrenContent =\r\n node.children?.nodes && node.children.nodes.length > 0 ? (\r\n <div\r\n className=\"unt-tree-children\"\r\n style={{\r\n display: \"flex\",\r\n flexShrink: 0,\r\n flexDirection: childrenLayoutIsStack ? \"column\" : \"row\",\r\n alignItems: axisToFlexAlign(childrenLayoutIsStack ? alignX : alignY),\r\n justifyContent: axisToFlexJustify(childrenLayoutIsStack ? alignY : alignX),\r\n gap,\r\n marginTop: flowDown || stackUnder ? gap : 0,\r\n marginLeft: flowDown\r\n ? node.children?.layout === \"stack\"\r\n ? gap\r\n : 0\r\n : stackUnder\r\n ? gap / 2\r\n : gap,\r\n }}\r\n >\r\n {node.children.nodes.map((child, childIndex) =>\r\n renderTreeNode({\r\n node: child,\r\n index: childIndex,\r\n parentId: node.id,\r\n depth: depth + 1,\r\n path,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n }),\r\n )}\r\n </div>\r\n ) : null;\r\n path.delete(node.id);\r\n\r\n return (\r\n <div\r\n key={`${node.id}-${index}`}\r\n className=\"unt-tree-node-wrap\"\r\n style={{\r\n display: \"flex\",\r\n position: \"relative\",\r\n flexDirection: flowDown || stackUnder ? \"column\" : \"row\",\r\n alignItems: axisToFlexAlign(flowDown ? alignX : alignY),\r\n justifyContent: axisToFlexJustify(flowDown ? alignY : alignX),\r\n }}\r\n >\r\n <NodeFrame\r\n node={node}\r\n className={cn(\"node-enter unt-tree-node-frame\", nodeFrameClassName)}\r\n style={{\r\n justifyContent: axisToFlexJustify(alignX),\r\n animationDuration: `${layoutState.nodeAnimDuration}s`,\r\n animationDelay: `${\r\n layoutState.nodeDelays.get(node.id) ?? depth * 0.08 + index * 0.04\r\n }s`,\r\n ...nodeFrameStyle,\r\n }}\r\n onRef={registerNode}\r\n >\r\n {debug ? (\r\n <div\r\n className={cn(\r\n \"unt-tree-debug-badge\",\r\n `unt-tree-debug-badge--${depth % 6}`,\r\n )}\r\n >\r\n <div>{`DEPTH: ${depth}`}</div>\r\n <div>{`PARENT-ID: ${parentId ?? \"root\"}`}</div>\r\n <div>{`NODE-ID: ${node.id}`}</div>\r\n <div>{`C-LAYOUT: ${node.children?.layout ?? \"N/A\"}`}</div>\r\n </div>\r\n ) : null}\r\n {node.render({\r\n node,\r\n index,\r\n depth,\r\n parentId,\r\n path: pathIds,\r\n isLeaf,\r\n childCount,\r\n isNodeAnimationDone: doneNodes.has(node.id),\r\n })}\r\n </NodeFrame>\r\n\r\n {childrenContent}\r\n </div>\r\n );\r\n}\r\n\r\nexport function TreeRenderer({\r\n nodeTree,\r\n rootLayout,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n rendererClassName,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n}: TreeRendererProps) {\r\n const rootLayoutRow = rootLayout === \"row\";\r\n return (\r\n <section\r\n className={cn(\"unt-tree-renderer\", rendererClassName)}\r\n style={{\r\n gap,\r\n display: \"flex\",\r\n width: \"100%\",\r\n overflow: \"visible\",\r\n position: \"relative\",\r\n zIndex: 10,\r\n flexDirection: rootLayoutRow ? \"row\" : \"column\",\r\n alignItems: axisToFlexAlign(rootLayoutRow ? alignY : alignX),\r\n justifyContent: axisToFlexJustify(rootLayoutRow ? alignX : alignY),\r\n }}\r\n >\r\n {nodeTree.map((node, index) =>\r\n renderTreeNode({\r\n node,\r\n index,\r\n depth: 0,\r\n path: new Set<string>(),\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n }),\r\n )}\r\n </section>\r\n );\r\n}\r\n","import * as React from \"react\";\nimport type {\n NodeTreeLayoutState,\n TreeNode,\n TreeNodeEdge,\n} from \"../types\";\n\ntype EdgeGeometry = {\n edge: TreeNodeEdge;\n fromX: number;\n fromY: number;\n fromBottom: number;\n fromCenterX: number;\n toX: number;\n toY: number;\n toLeft: number;\n toCenterY: number;\n};\n\ntype UseNodeTreeLayoutParams = {\n nodeTree: TreeNode[];\n direction: \"down\" | \"right\";\n gap: number;\n padding: number;\n animationSpeed: number;\n debug: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n nodeRefs: React.MutableRefObject<Map<string, HTMLDivElement>>;\n};\n\nconst EMPTY_LAYOUT: NodeTreeLayoutState = {\n segments: [],\n nodeDelays: new Map(),\n nodeAnimDuration: 0.42,\n animationTotal: 0,\n svgBounds: null,\n};\n\nfunction collectEdges(nodes: TreeNode[]) {\n const edges: TreeNodeEdge[] = [];\n const visiting = new Set<string>();\n const visit = (node: TreeNode) => {\n if (visiting.has(node.id)) {\n return;\n }\n visiting.add(node.id);\n if (node.children?.nodes && node.children.nodes.length > 0) {\n node.children.nodes.forEach((child, index) => {\n const key = `${node.id}=>${child.id}`;\n edges.push({\n key,\n from: node.id,\n to: child.id,\n index,\n count: node.children?.nodes.length ?? 1,\n });\n visit(child);\n });\n }\n visiting.delete(node.id);\n };\n\n nodes.forEach(visit);\n return edges;\n}\n\nfunction collectDescendants(nodes: TreeNode[]) {\n const map = new Map<string, string[]>();\n const visiting = new Set<string>();\n const visit = (node: TreeNode): string[] => {\n if (visiting.has(node.id)) {\n return [];\n }\n visiting.add(node.id);\n const descendants: string[] = [];\n node.children?.nodes.forEach((child) => {\n descendants.push(child.id);\n descendants.push(...visit(child));\n });\n map.set(node.id, descendants);\n visiting.delete(node.id);\n return descendants;\n };\n nodes.forEach(visit);\n return map;\n}\n\nexport function useNodeTreeLayout({\n nodeTree,\n direction,\n gap,\n padding,\n animationSpeed,\n debug,\n containerRef,\n nodeRefs,\n}: UseNodeTreeLayoutParams) {\n const [layoutState, setLayoutState] =\n React.useState<NodeTreeLayoutState>(EMPTY_LAYOUT);\n const [doneNodes, setDoneNodes] = React.useState<Set<string>>(\n () => new Set(),\n );\n const doneNodesRef = React.useRef<Set<string>>(new Set());\n const edges = React.useMemo(() => collectEdges(nodeTree), [nodeTree]);\n const descendantMap = React.useMemo(\n () => collectDescendants(nodeTree),\n [nodeTree],\n );\n\n const totalAnimationSec = Math.max(0.1, animationSpeed / 1000);\n\n const drawConnections = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n const flowDown = direction === \"down\";\n\n const getRelativeRect = (element: HTMLElement) => {\n let left = 0;\n let top = 0;\n let current: HTMLElement | null = element;\n while (current && current !== container) {\n left += current.offsetLeft;\n top += current.offsetTop;\n current = current.offsetParent as HTMLElement | null;\n }\n return {\n left,\n top,\n right: left + element.offsetWidth,\n bottom: top + element.offsetHeight,\n width: element.offsetWidth,\n height: element.offsetHeight,\n };\n };\n\n const rectMap = new Map<string, ReturnType<typeof getRelativeRect>>();\n nodeRefs.current.forEach((el, id) => {\n rectMap.set(id, getRelativeRect(el));\n });\n\n const nextSegments: NodeTreeLayoutState[\"segments\"] = [];\n const nextNodeDelays = new Map<string, number>();\n const baseSecondsPerPixel = 1 / 900;\n const baseNodeAnimDuration = 0.42;\n const edgeColorIndex = debug ? new Map<string, number>() : null;\n const edgeData = new Map<string, EdgeGeometry>();\n\n edges.forEach((edge) => {\n const fromRect = rectMap.get(edge.from);\n const toRect = rectMap.get(edge.to);\n if (!fromRect || !toRect) {\n return;\n }\n\n const fromX = flowDown ? fromRect.left + fromRect.width / 2 : fromRect.right;\n const fromY = flowDown\n ? fromRect.bottom\n : fromRect.top + fromRect.height / 2;\n const toX = flowDown ? toRect.left + toRect.width / 2 : toRect.left;\n const toY = flowDown ? toRect.top : toRect.top + toRect.height / 2;\n\n edgeData.set(edge.key, {\n edge,\n fromX,\n fromY,\n fromBottom: fromRect.bottom,\n fromCenterX: fromRect.left + fromRect.width / 2,\n toX,\n toY,\n toLeft: toRect.left,\n toCenterY: toRect.top + toRect.height / 2,\n });\n });\n\n const pushSegment = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n depth: number,\n delay: number,\n colorIndex: number,\n order: number,\n ) => {\n const length = Math.hypot(x2 - x1, y2 - y1);\n const duration = Math.max(0.05, length * baseSecondsPerPixel);\n nextSegments.push({\n x1,\n y1,\n x2,\n y2,\n length,\n depth,\n delay,\n duration,\n colorIndex,\n order,\n });\n return duration;\n };\n\n const visit = (node: TreeNode, depth: number, nodeDelay: number) => {\n const existing = nextNodeDelays.get(node.id) ?? 0;\n const resolvedDelay = Math.max(existing, nodeDelay);\n nextNodeDelays.set(node.id, resolvedDelay);\n\n const childEdges =\n node.children?.nodes\n .map((child) => edgeData.get(`${node.id}=>${child.id}`))\n .filter((edge): edge is EdgeGeometry => Boolean(edge)) ?? [];\n const stackLayout = node.children?.layout === \"stack\";\n const descendantIds =\n flowDown && stackLayout ? (descendantMap.get(node.id) ?? []) : [];\n const descendantLefts =\n flowDown && stackLayout\n ? descendantIds\n .map((id) => rectMap.get(id))\n .filter((rect): rect is NonNullable<typeof rect> => Boolean(rect))\n .map((rect) => rect.left)\n : [];\n const descendantMinLeft =\n descendantLefts.length > 0 ? Math.min(...descendantLefts) : undefined;\n const gutterX =\n flowDown && stackLayout\n ? (descendantMinLeft ??\n (childEdges.length > 0\n ? Math.min(...childEdges.map((edge) => edge.toLeft))\n : 0)) -\n gap / 2\n : 0;\n const gutterXRight =\n !flowDown && stackLayout\n ? (childEdges.length > 0\n ? Math.min(...childEdges.map((edge) => edge.toLeft))\n : 0) -\n gap / 2\n : 0;\n\n const orderedChildren =\n node.children?.nodes\n .map((child) => {\n const edge = edgeData.get(`${node.id}=>${child.id}`);\n if (!edge) {\n return null;\n }\n const dx = edge.toX - edge.fromX;\n const dy = edge.toY - edge.fromY;\n const length = Math.hypot(dx, dy);\n return { child, edge, length, toX: edge.toX };\n })\n .filter(\n (entry): entry is NonNullable<typeof entry> => Boolean(entry),\n ) ?? [];\n\n if (debug) {\n orderedChildren.sort((a, b) => {\n if (a.length !== b.length) {\n return a.length - b.length;\n }\n return a.toX - b.toX;\n });\n }\n\n orderedChildren.forEach((entry, index) => {\n const { child, edge } = entry;\n const edgeKey = edge.edge.key;\n let colorIndex = 0;\n if (edgeColorIndex) {\n if (!edgeColorIndex.has(edgeKey)) {\n edgeColorIndex.set(edgeKey, edgeColorIndex.size);\n }\n colorIndex = edgeColorIndex.get(edgeKey) ?? 0;\n }\n const order = orderedChildren.length - 1 - index;\n const edgeDelay = resolvedDelay + baseNodeAnimDuration + index * 0.04;\n let totalDuration = 0;\n if (flowDown && stackLayout) {\n const baseDrop = Math.max(12, gap / 2);\n const targetY = edge.toCenterY;\n const midY =\n edge.fromY + Math.min(baseDrop, (targetY - edge.fromY) * 0.6);\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n edge.fromX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromX,\n midY,\n gutterX,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterX,\n midY,\n gutterX,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterX,\n targetY,\n edge.toLeft,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else if (!flowDown && stackLayout) {\n const targetY = edge.toCenterY;\n const baseDrop = Math.max(12, gap / 2);\n const midY =\n edge.fromBottom +\n Math.min(baseDrop, (targetY - edge.fromBottom) * 0.6);\n totalDuration += pushSegment(\n edge.fromCenterX,\n edge.fromBottom,\n edge.fromCenterX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromCenterX,\n midY,\n gutterXRight,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterXRight,\n midY,\n gutterXRight,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterXRight,\n targetY,\n edge.toLeft,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else if (flowDown) {\n const midY = edge.fromY + (edge.toY - edge.fromY) * 0.5;\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n edge.fromX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromX,\n midY,\n edge.toX,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.toX,\n midY,\n edge.toX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else {\n const midX = edge.fromX + (edge.toX - edge.fromX) * 0.5;\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n midX,\n edge.fromY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n midX,\n edge.fromY,\n midX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n midX,\n edge.toY,\n edge.toX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n }\n visit(child, depth + 1, edgeDelay + totalDuration);\n });\n };\n\n nodeTree.forEach((node) => visit(node, 0, 0));\n\n if (nextSegments.length === 0) {\n setLayoutState((prev) => ({\n ...prev,\n segments: [],\n svgBounds: null,\n animationTotal: 0,\n }));\n setDoneNodes(new Set());\n doneNodesRef.current = new Set();\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n nextSegments.forEach((segment) => {\n minX = Math.min(minX, segment.x1, segment.x2);\n minY = Math.min(minY, segment.y1, segment.y2);\n maxX = Math.max(maxX, segment.x1, segment.x2);\n maxY = Math.max(maxY, segment.y1, segment.y2);\n });\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return;\n }\n\n const width = Math.max(1, maxX - minX + padding * 2);\n const height = Math.max(1, maxY - minY + padding * 2);\n const offsetX = minX - padding;\n const offsetY = minY - padding;\n\n const maxLineEnd = Math.max(\n 0,\n ...nextSegments.map((segment) => segment.delay + segment.duration),\n );\n const maxNodeEnd =\n Math.max(0, ...Array.from(nextNodeDelays.values())) + baseNodeAnimDuration;\n const animationMax = Math.max(maxLineEnd, maxNodeEnd);\n const scale = animationMax > 0 ? totalAnimationSec / animationMax : 1;\n const scaledSegments = nextSegments\n .map((segment) => ({\n ...segment,\n delay: segment.delay * scale,\n duration: segment.duration * scale,\n }))\n .sort((a, b) => a.order - b.order);\n const scaledNodeDelays = new Map<string, number>();\n nextNodeDelays.forEach((value, key) => {\n scaledNodeDelays.set(key, value * scale);\n });\n\n setLayoutState({\n segments: scaledSegments,\n nodeDelays: scaledNodeDelays,\n nodeAnimDuration: baseNodeAnimDuration * scale,\n animationTotal: animationMax * scale,\n svgBounds: { width, height, offsetX, offsetY },\n });\n setDoneNodes(new Set());\n doneNodesRef.current = new Set();\n }, [\n animationSpeed,\n containerRef,\n debug,\n descendantMap,\n direction,\n edges,\n gap,\n nodeRefs,\n nodeTree,\n padding,\n totalAnimationSec,\n ]);\n\n React.useLayoutEffect(() => {\n const rafId = requestAnimationFrame(drawConnections);\n return () => cancelAnimationFrame(rafId);\n }, [drawConnections, nodeTree]);\n\n React.useEffect(() => {\n if (layoutState.animationTotal <= 0 || layoutState.nodeDelays.size === 0) {\n return;\n }\n\n const entries = Array.from(layoutState.nodeDelays.entries())\n .map(([id, delay]) => ({\n id,\n end: delay + layoutState.nodeAnimDuration,\n }))\n .sort((a, b) => a.end - b.end);\n\n doneNodesRef.current = new Set();\n setDoneNodes(new Set());\n\n const start = performance.now();\n let rafId = 0;\n let index = 0;\n\n const tick = () => {\n const elapsed = (performance.now() - start) / 1000;\n let updated = false;\n\n while (index < entries.length && elapsed >= entries[index].end) {\n doneNodesRef.current.add(entries[index].id);\n index += 1;\n updated = true;\n }\n\n if (updated) {\n setDoneNodes(new Set(doneNodesRef.current));\n }\n\n if (index < entries.length) {\n rafId = requestAnimationFrame(tick);\n }\n };\n\n rafId = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(rafId);\n }, [\n layoutState.animationTotal,\n layoutState.nodeAnimDuration,\n layoutState.nodeDelays,\n ]);\n\n return { doneNodes, layoutState };\n}\n"],"mappings":"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","names":["React","import_jsx_runtime","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/node-tree.tsx","../src/utils/cn.ts","../src/components/tree-connections.tsx","../src/components/tree-renderer.tsx","../src/hooks/use-node-tree-layout.ts"],"sourcesContent":["export { NodeTree } from \"./components/node-tree\";\nexport type {\r\n NodeFrameProps,\r\n NodeTreeAnimationOptions,\r\n NodeTreeClassNameOptions,\r\n NodeTreeConnectionOptions,\r\n NodeTreeFrameOptions,\n NodeTreeLayoutOptions,\n NodeTreeProps,\n TreeNodeChildren,\n TreeNode,\n TreeNodeEdge,\n TreeNodeRenderContext,\n} from \"./types\";\n","import * as React from \"react\";\nimport \"../node-tree.css\";\nimport { cn } from \"../utils/cn\";\nimport { TreeConnections } from \"./tree-connections\";\nimport { TreeRenderer } from \"./tree-renderer\";\nimport { useNodeTreeLayout } from \"../hooks/use-node-tree-layout\";\nimport type { AlignAxis, NodeTreeProps } from \"../types\";\n\r\nconst NodeTree = React.forwardRef<HTMLDivElement, NodeTreeProps>(\r\n (\r\n {\r\n className,\r\n nodeTree,\r\n layout,\r\n connection,\r\n animation,\r\n nodeFrame,\r\n debug = false,\r\n style,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n const containerRef = React.useRef<HTMLDivElement | null>(null);\r\n const nodeRefs = React.useRef(new Map<string, HTMLDivElement>());\r\n const registerNode = React.useCallback(\r\n (id: string, element: HTMLDivElement | null) => {\r\n const registry = nodeRefs.current;\r\n if (element) {\r\n registry.set(id, element);\r\n } else {\r\n registry.delete(id);\r\n }\r\n },\r\n [],\r\n );\r\n\r\n const resolvedAlign = layout?.align ?? \"center\";\r\n const resolvedDirection = layout?.direction ?? \"down\";\r\n const resolvedRootLayout = layout?.root ?? \"stack\";\r\n const resolvedPaddingContainer = layout?.containerPadding ?? 128;\r\n const resolvedPadding = layout?.padding ?? 64;\r\n const resolvedGap = layout?.gap ?? 64;\r\n const resolvedStrokeColor = connection?.color ?? \"rgba(255,255,255)\";\r\n const resolvedStrokeWidth = connection?.width ?? 1;\r\n const resolvedAnimationDurationMs = animation?.durationMs ?? 2000;\r\n const resolvedNodeFrameStyle = nodeFrame?.style;\r\n\r\n const { doneNodes, layoutState } = useNodeTreeLayout({\r\n nodeTree,\r\n direction: resolvedDirection,\r\n gap: resolvedGap,\r\n padding: resolvedPadding,\r\n animationSpeed: resolvedAnimationDurationMs,\r\n debug,\r\n containerRef,\r\n nodeRefs,\r\n });\r\n\r\n const flowDown = resolvedDirection === \"down\";\r\n const alignValue = resolvedAlign;\r\n const alignX: AlignAxis =\r\n typeof alignValue === \"string\" ? alignValue : alignValue.x;\r\n const alignY: AlignAxis =\r\n typeof alignValue === \"string\" ? \"start\" : alignValue.y;\r\n const resolvedConnectionOpacity = connection?.opacity ?? (debug ? 1 : 0.1);\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={cn(\"unt-tree-root-container\", className?.root)}\r\n style={style}\r\n {...props}\r\n >\r\n <div\r\n ref={containerRef}\r\n className={cn(\"unt-tree-canvas\", className?.canvas)}\r\n style={{ padding: resolvedPaddingContainer }}\r\n >\r\n <TreeConnections\r\n layoutState={layoutState}\r\n debug={debug}\r\n strokeColor={resolvedStrokeColor}\r\n strokeWidth={resolvedStrokeWidth}\r\n opacity={resolvedConnectionOpacity}\r\n className={className?.connections}\r\n />\r\n <TreeRenderer\r\n nodeTree={nodeTree}\r\n rootLayout={resolvedRootLayout}\r\n flowDown={flowDown}\r\n alignX={alignX}\r\n alignY={alignY}\r\n gap={resolvedGap}\r\n debug={debug}\r\n layoutState={layoutState}\r\n doneNodes={doneNodes}\r\n registerNode={registerNode}\r\n rendererClassName={className?.renderer}\r\n nodeFrameClassName={className?.frame}\r\n nodeFrameStyle={resolvedNodeFrameStyle}\r\n />\r\n </div>\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nNodeTree.displayName = \"NodeTree\";\r\n\r\nexport { NodeTree };\r\n","import { clsx, type ClassValue } from \"clsx\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return clsx(inputs);\r\n}\r\n","import * as React from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\nimport type { NodeTreeLayoutState } from \"../types\";\r\n\r\ntype TreeConnectionsProps = {\r\n layoutState: NodeTreeLayoutState;\r\n debug: boolean;\r\n strokeColor: string;\r\n strokeWidth: number;\r\n opacity: number;\r\n className?: string;\r\n};\r\n\r\nexport function TreeConnections({\r\n layoutState,\r\n debug,\r\n strokeColor,\r\n strokeWidth,\r\n opacity,\r\n className,\r\n}: TreeConnectionsProps) {\r\n if (!layoutState.svgBounds) {\r\n return null;\r\n }\r\n\r\n return (\r\n <svg\r\n className={cn(\"unt-tree-connections\", className)}\r\n width={layoutState.svgBounds.width}\r\n height={layoutState.svgBounds.height}\r\n viewBox={`0 0 ${layoutState.svgBounds.width} ${layoutState.svgBounds.height}`}\r\n style={{\r\n left: layoutState.svgBounds.offsetX,\r\n top: layoutState.svgBounds.offsetY,\r\n opacity,\r\n }}\r\n >\r\n {layoutState.segments.map((segment) => {\r\n const debugPalette = [\r\n \"#22d3ee\",\r\n \"#a855f7\",\r\n \"#f59e0b\",\r\n \"#10b981\",\r\n \"#f97316\",\r\n \"#38bdf8\",\r\n ];\r\n const lineColor = debug\r\n ? debugPalette[segment.colorIndex % debugPalette.length]\r\n : strokeColor;\r\n return (\r\n <line\r\n key={`${segment.x1}-${segment.y1}-${segment.x2}-${segment.y2}-${segment.delay}`}\r\n x1={segment.x1 - layoutState.svgBounds!.offsetX}\r\n y1={segment.y1 - layoutState.svgBounds!.offsetY}\r\n x2={segment.x2 - layoutState.svgBounds!.offsetX}\r\n y2={segment.y2 - layoutState.svgBounds!.offsetY}\r\n className=\"unt-node-line\"\r\n style={{\r\n strokeDasharray: segment.length,\r\n strokeDashoffset: segment.length,\r\n animationDelay: `${segment.delay}s`,\r\n animationDuration: `${segment.duration}s`,\r\n }}\r\n stroke={lineColor}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n );\r\n })}\r\n </svg>\r\n );\r\n}\r\n","import * as React from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\nimport type {\r\n AlignAxis,\r\n NodeFrameProps,\r\n NodeTreeLayoutState,\r\n TreeNode,\r\n} from \"../types\";\r\n\r\ntype TreeRendererProps = {\r\n nodeTree: TreeNode[];\r\n rootLayout: \"stack\" | \"row\";\r\n flowDown: boolean;\r\n alignX: AlignAxis;\r\n alignY: AlignAxis;\r\n gap: number;\r\n debug: boolean;\r\n layoutState: NodeTreeLayoutState;\r\n doneNodes: Set<string>;\r\n registerNode: (id: string, element: HTMLDivElement | null) => void;\r\n rendererClassName?: string;\r\n nodeFrameClassName?: string;\r\n nodeFrameStyle?: React.CSSProperties;\r\n};\r\n\r\nfunction axisToFlexAlign(axis: AlignAxis): React.CSSProperties[\"alignItems\"] {\r\n if (axis === \"start\") {\r\n return \"flex-start\";\r\n }\r\n if (axis === \"end\") {\r\n return \"flex-end\";\r\n }\r\n return \"center\";\r\n}\r\n\r\nfunction axisToFlexJustify(\r\n axis: AlignAxis,\r\n): React.CSSProperties[\"justifyContent\"] {\r\n if (axis === \"start\") {\r\n return \"flex-start\";\r\n }\r\n if (axis === \"end\") {\r\n return \"flex-end\";\r\n }\r\n return \"center\";\r\n}\r\n\r\nfunction NodeFrame({\r\n node,\r\n className,\r\n onRef,\r\n children,\r\n ...props\r\n}: NodeFrameProps) {\r\n return (\r\n <div\r\n ref={(element) => {\r\n onRef(node.id, element);\r\n }}\r\n className={cn(\"unt-tree-node-hit\", className)}\r\n data-nodeframe\r\n data-viewport-no-pan\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nfunction renderTreeNode({\r\n node,\r\n index,\r\n parentId,\r\n depth,\r\n path,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n}: {\r\n node: TreeNode;\r\n index: number;\r\n parentId?: string;\r\n depth: number;\r\n path: Set<string>;\r\n flowDown: boolean;\r\n alignX: AlignAxis;\r\n alignY: AlignAxis;\r\n gap: number;\r\n debug: boolean;\r\n layoutState: NodeTreeLayoutState;\r\n doneNodes: Set<string>;\r\n registerNode: (id: string, element: HTMLDivElement | null) => void;\r\n nodeFrameClassName?: string;\r\n nodeFrameStyle?: React.CSSProperties;\r\n}): React.ReactNode {\r\n const stackUnder = !flowDown && node.children?.layout === \"stack\";\r\n if (path.has(node.id)) {\r\n return null;\r\n }\r\n\r\n path.add(node.id);\r\n const childrenLayoutIsStack = node.children?.layout === \"stack\" || !flowDown;\r\n const childCount = node.children?.nodes.length ?? 0;\r\n const isLeaf = childCount === 0;\r\n const pathIds = [...path];\r\n const childrenContent =\r\n node.children?.nodes && node.children.nodes.length > 0 ? (\r\n <div\r\n className=\"unt-tree-children\"\r\n style={{\r\n display: \"flex\",\r\n flexShrink: 0,\r\n flexDirection: childrenLayoutIsStack ? \"column\" : \"row\",\r\n alignItems: axisToFlexAlign(childrenLayoutIsStack ? alignX : alignY),\r\n justifyContent: axisToFlexJustify(\r\n childrenLayoutIsStack ? alignY : alignX,\r\n ),\r\n gap,\r\n marginTop: flowDown || stackUnder ? gap : 0,\r\n marginLeft: flowDown\r\n ? node.children?.layout === \"stack\"\r\n ? gap\r\n : 0\r\n : stackUnder\r\n ? gap / 2\r\n : gap,\r\n }}\r\n >\r\n {node.children.nodes.map((child, childIndex) =>\r\n renderTreeNode({\r\n node: child,\r\n index: childIndex,\r\n parentId: node.id,\r\n depth: depth + 1,\r\n path,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n }),\r\n )}\r\n </div>\r\n ) : null;\r\n path.delete(node.id);\r\n\r\n return (\r\n <div\r\n key={`${node.id}-${index}`}\r\n className=\"unt-tree-node-wrap\"\r\n style={{\r\n display: \"flex\",\r\n position: \"relative\",\r\n flexDirection: flowDown || stackUnder ? \"column\" : \"row\",\r\n alignItems: axisToFlexAlign(flowDown ? alignX : alignY),\r\n justifyContent: axisToFlexJustify(flowDown ? alignY : alignX),\r\n }}\r\n >\r\n <NodeFrame\r\n node={node}\r\n className={cn(\"unt-node-enter unt-tree-node-frame\", nodeFrameClassName)}\r\n style={{\r\n justifyContent: axisToFlexJustify(alignX),\r\n animationDuration: `${layoutState.nodeAnimDuration}s`,\r\n animationDelay: `${\r\n layoutState.nodeDelays.get(node.id) ?? depth * 0.08 + index * 0.04\r\n }s`,\r\n ...nodeFrameStyle,\r\n }}\r\n onRef={registerNode}\r\n >\r\n {debug ? (\r\n <div\r\n className={cn(\r\n \"unt-tree-debug-badge\",\r\n `unt-tree-debug-badge--${depth % 6}`,\r\n )}\r\n >\r\n <div>{`DEPTH: ${depth}`}</div>\r\n <div>{`PARENT-ID: ${parentId ?? \"root\"}`}</div>\r\n <div>{`NODE-ID: ${node.id}`}</div>\r\n <div>{`C-LAYOUT: ${node.children?.layout ?? \"N/A\"}`}</div>\r\n </div>\r\n ) : null}\r\n {node.render({\r\n node,\r\n index,\r\n depth,\r\n parentId,\r\n path: pathIds,\r\n isLeaf,\r\n childCount,\r\n isNodeAnimationDone: doneNodes.has(node.id),\r\n })}\r\n </NodeFrame>\r\n\r\n {childrenContent}\r\n </div>\r\n );\r\n}\r\n\r\nexport function TreeRenderer({\r\n nodeTree,\r\n rootLayout,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n rendererClassName,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n}: TreeRendererProps) {\r\n const rootLayoutRow = rootLayout === \"row\";\r\n return (\r\n <section\r\n className={cn(\"unt-tree-renderer\", rendererClassName)}\r\n style={{\r\n gap,\r\n display: \"flex\",\r\n width: \"100%\",\r\n overflow: \"visible\",\r\n position: \"relative\",\r\n zIndex: 10,\r\n flexDirection: rootLayoutRow ? \"row\" : \"column\",\r\n alignItems: axisToFlexAlign(rootLayoutRow ? alignY : alignX),\r\n justifyContent: axisToFlexJustify(rootLayoutRow ? alignX : alignY),\r\n }}\r\n >\r\n {nodeTree.map((node, index) =>\r\n renderTreeNode({\r\n node,\r\n index,\r\n depth: 0,\r\n path: new Set<string>(),\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n }),\r\n )}\r\n </section>\r\n );\r\n}\r\n","import * as React from \"react\";\nimport type {\n NodeTreeLayoutState,\n TreeNode,\n TreeNodeEdge,\n} from \"../types\";\n\ntype EdgeGeometry = {\n edge: TreeNodeEdge;\n fromX: number;\n fromY: number;\n fromBottom: number;\n fromCenterX: number;\n toX: number;\n toY: number;\n toLeft: number;\n toCenterY: number;\n};\n\ntype UseNodeTreeLayoutParams = {\n nodeTree: TreeNode[];\n direction: \"down\" | \"right\";\n gap: number;\n padding: number;\n animationSpeed: number;\n debug: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n nodeRefs: React.MutableRefObject<Map<string, HTMLDivElement>>;\n};\n\nconst EMPTY_LAYOUT: NodeTreeLayoutState = {\n segments: [],\n nodeDelays: new Map(),\n nodeAnimDuration: 0.42,\n animationTotal: 0,\n svgBounds: null,\n};\n\nfunction collectEdges(nodes: TreeNode[]) {\n const edges: TreeNodeEdge[] = [];\n const visiting = new Set<string>();\n const visit = (node: TreeNode) => {\n if (visiting.has(node.id)) {\n return;\n }\n visiting.add(node.id);\n if (node.children?.nodes && node.children.nodes.length > 0) {\n node.children.nodes.forEach((child, index) => {\n const key = `${node.id}=>${child.id}`;\n edges.push({\n key,\n from: node.id,\n to: child.id,\n index,\n count: node.children?.nodes.length ?? 1,\n });\n visit(child);\n });\n }\n visiting.delete(node.id);\n };\n\n nodes.forEach(visit);\n return edges;\n}\n\nfunction collectDescendants(nodes: TreeNode[]) {\n const map = new Map<string, string[]>();\n const visiting = new Set<string>();\n const visit = (node: TreeNode): string[] => {\n if (visiting.has(node.id)) {\n return [];\n }\n visiting.add(node.id);\n const descendants: string[] = [];\n node.children?.nodes.forEach((child) => {\n descendants.push(child.id);\n descendants.push(...visit(child));\n });\n map.set(node.id, descendants);\n visiting.delete(node.id);\n return descendants;\n };\n nodes.forEach(visit);\n return map;\n}\n\nexport function useNodeTreeLayout({\n nodeTree,\n direction,\n gap,\n padding,\n animationSpeed,\n debug,\n containerRef,\n nodeRefs,\n}: UseNodeTreeLayoutParams) {\n const [layoutState, setLayoutState] =\n React.useState<NodeTreeLayoutState>(EMPTY_LAYOUT);\n const [doneNodes, setDoneNodes] = React.useState<Set<string>>(\n () => new Set(),\n );\n const doneNodesRef = React.useRef<Set<string>>(new Set());\n const edges = React.useMemo(() => collectEdges(nodeTree), [nodeTree]);\n const descendantMap = React.useMemo(\n () => collectDescendants(nodeTree),\n [nodeTree],\n );\n\n const totalAnimationSec = Math.max(0.1, animationSpeed / 1000);\n\n const drawConnections = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n const flowDown = direction === \"down\";\n\n const getRelativeRect = (element: HTMLElement) => {\n let left = 0;\n let top = 0;\n let current: HTMLElement | null = element;\n while (current && current !== container) {\n left += current.offsetLeft;\n top += current.offsetTop;\n current = current.offsetParent as HTMLElement | null;\n }\n return {\n left,\n top,\n right: left + element.offsetWidth,\n bottom: top + element.offsetHeight,\n width: element.offsetWidth,\n height: element.offsetHeight,\n };\n };\n\n const rectMap = new Map<string, ReturnType<typeof getRelativeRect>>();\n nodeRefs.current.forEach((el, id) => {\n rectMap.set(id, getRelativeRect(el));\n });\n\n const nextSegments: NodeTreeLayoutState[\"segments\"] = [];\n const nextNodeDelays = new Map<string, number>();\n const baseSecondsPerPixel = 1 / 900;\n const baseNodeAnimDuration = 0.42;\n const edgeColorIndex = debug ? new Map<string, number>() : null;\n const edgeData = new Map<string, EdgeGeometry>();\n\n edges.forEach((edge) => {\n const fromRect = rectMap.get(edge.from);\n const toRect = rectMap.get(edge.to);\n if (!fromRect || !toRect) {\n return;\n }\n\n const fromX = flowDown ? fromRect.left + fromRect.width / 2 : fromRect.right;\n const fromY = flowDown\n ? fromRect.bottom\n : fromRect.top + fromRect.height / 2;\n const toX = flowDown ? toRect.left + toRect.width / 2 : toRect.left;\n const toY = flowDown ? toRect.top : toRect.top + toRect.height / 2;\n\n edgeData.set(edge.key, {\n edge,\n fromX,\n fromY,\n fromBottom: fromRect.bottom,\n fromCenterX: fromRect.left + fromRect.width / 2,\n toX,\n toY,\n toLeft: toRect.left,\n toCenterY: toRect.top + toRect.height / 2,\n });\n });\n\n const pushSegment = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n depth: number,\n delay: number,\n colorIndex: number,\n order: number,\n ) => {\n const length = Math.hypot(x2 - x1, y2 - y1);\n const duration = Math.max(0.05, length * baseSecondsPerPixel);\n nextSegments.push({\n x1,\n y1,\n x2,\n y2,\n length,\n depth,\n delay,\n duration,\n colorIndex,\n order,\n });\n return duration;\n };\n\n const visit = (node: TreeNode, depth: number, nodeDelay: number) => {\n const existing = nextNodeDelays.get(node.id) ?? 0;\n const resolvedDelay = Math.max(existing, nodeDelay);\n nextNodeDelays.set(node.id, resolvedDelay);\n\n const childEdges =\n node.children?.nodes\n .map((child) => edgeData.get(`${node.id}=>${child.id}`))\n .filter((edge): edge is EdgeGeometry => Boolean(edge)) ?? [];\n const stackLayout = node.children?.layout === \"stack\";\n const descendantIds =\n flowDown && stackLayout ? (descendantMap.get(node.id) ?? []) : [];\n const descendantLefts =\n flowDown && stackLayout\n ? descendantIds\n .map((id) => rectMap.get(id))\n .filter((rect): rect is NonNullable<typeof rect> => Boolean(rect))\n .map((rect) => rect.left)\n : [];\n const descendantMinLeft =\n descendantLefts.length > 0 ? Math.min(...descendantLefts) : undefined;\n const gutterX =\n flowDown && stackLayout\n ? (descendantMinLeft ??\n (childEdges.length > 0\n ? Math.min(...childEdges.map((edge) => edge.toLeft))\n : 0)) -\n gap / 2\n : 0;\n const gutterXRight =\n !flowDown && stackLayout\n ? (childEdges.length > 0\n ? Math.min(...childEdges.map((edge) => edge.toLeft))\n : 0) -\n gap / 2\n : 0;\n\n const orderedChildren =\n node.children?.nodes\n .map((child) => {\n const edge = edgeData.get(`${node.id}=>${child.id}`);\n if (!edge) {\n return null;\n }\n const dx = edge.toX - edge.fromX;\n const dy = edge.toY - edge.fromY;\n const length = Math.hypot(dx, dy);\n return { child, edge, length, toX: edge.toX };\n })\n .filter(\n (entry): entry is NonNullable<typeof entry> => Boolean(entry),\n ) ?? [];\n\n if (debug) {\n orderedChildren.sort((a, b) => {\n if (a.length !== b.length) {\n return a.length - b.length;\n }\n return a.toX - b.toX;\n });\n }\n\n orderedChildren.forEach((entry, index) => {\n const { child, edge } = entry;\n const edgeKey = edge.edge.key;\n let colorIndex = 0;\n if (edgeColorIndex) {\n if (!edgeColorIndex.has(edgeKey)) {\n edgeColorIndex.set(edgeKey, edgeColorIndex.size);\n }\n colorIndex = edgeColorIndex.get(edgeKey) ?? 0;\n }\n const order = orderedChildren.length - 1 - index;\n const edgeDelay = resolvedDelay + baseNodeAnimDuration + index * 0.04;\n let totalDuration = 0;\n if (flowDown && stackLayout) {\n const baseDrop = Math.max(12, gap / 2);\n const targetY = edge.toCenterY;\n const midY =\n edge.fromY + Math.min(baseDrop, (targetY - edge.fromY) * 0.6);\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n edge.fromX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromX,\n midY,\n gutterX,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterX,\n midY,\n gutterX,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterX,\n targetY,\n edge.toLeft,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else if (!flowDown && stackLayout) {\n const targetY = edge.toCenterY;\n const baseDrop = Math.max(12, gap / 2);\n const midY =\n edge.fromBottom +\n Math.min(baseDrop, (targetY - edge.fromBottom) * 0.6);\n totalDuration += pushSegment(\n edge.fromCenterX,\n edge.fromBottom,\n edge.fromCenterX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromCenterX,\n midY,\n gutterXRight,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterXRight,\n midY,\n gutterXRight,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterXRight,\n targetY,\n edge.toLeft,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else if (flowDown) {\n const midY = edge.fromY + (edge.toY - edge.fromY) * 0.5;\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n edge.fromX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromX,\n midY,\n edge.toX,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.toX,\n midY,\n edge.toX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else {\n const midX = edge.fromX + (edge.toX - edge.fromX) * 0.5;\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n midX,\n edge.fromY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n midX,\n edge.fromY,\n midX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n midX,\n edge.toY,\n edge.toX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n }\n visit(child, depth + 1, edgeDelay + totalDuration);\n });\n };\n\n nodeTree.forEach((node) => visit(node, 0, 0));\n\n if (nextSegments.length === 0) {\n setLayoutState((prev) => ({\n ...prev,\n segments: [],\n svgBounds: null,\n animationTotal: 0,\n }));\n setDoneNodes(new Set());\n doneNodesRef.current = new Set();\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n nextSegments.forEach((segment) => {\n minX = Math.min(minX, segment.x1, segment.x2);\n minY = Math.min(minY, segment.y1, segment.y2);\n maxX = Math.max(maxX, segment.x1, segment.x2);\n maxY = Math.max(maxY, segment.y1, segment.y2);\n });\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return;\n }\n\n const width = Math.max(1, maxX - minX + padding * 2);\n const height = Math.max(1, maxY - minY + padding * 2);\n const offsetX = minX - padding;\n const offsetY = minY - padding;\n\n const maxLineEnd = Math.max(\n 0,\n ...nextSegments.map((segment) => segment.delay + segment.duration),\n );\n const maxNodeEnd =\n Math.max(0, ...Array.from(nextNodeDelays.values())) + baseNodeAnimDuration;\n const animationMax = Math.max(maxLineEnd, maxNodeEnd);\n const scale = animationMax > 0 ? totalAnimationSec / animationMax : 1;\n const scaledSegments = nextSegments\n .map((segment) => ({\n ...segment,\n delay: segment.delay * scale,\n duration: segment.duration * scale,\n }))\n .sort((a, b) => a.order - b.order);\n const scaledNodeDelays = new Map<string, number>();\n nextNodeDelays.forEach((value, key) => {\n scaledNodeDelays.set(key, value * scale);\n });\n\n setLayoutState({\n segments: scaledSegments,\n nodeDelays: scaledNodeDelays,\n nodeAnimDuration: baseNodeAnimDuration * scale,\n animationTotal: animationMax * scale,\n svgBounds: { width, height, offsetX, offsetY },\n });\n setDoneNodes(new Set());\n doneNodesRef.current = new Set();\n }, [\n animationSpeed,\n containerRef,\n debug,\n descendantMap,\n direction,\n edges,\n gap,\n nodeRefs,\n nodeTree,\n padding,\n totalAnimationSec,\n ]);\n\n React.useLayoutEffect(() => {\n const rafId = requestAnimationFrame(drawConnections);\n return () => cancelAnimationFrame(rafId);\n }, [drawConnections, nodeTree]);\n\n React.useEffect(() => {\n if (layoutState.animationTotal <= 0 || layoutState.nodeDelays.size === 0) {\n return;\n }\n\n const entries = Array.from(layoutState.nodeDelays.entries())\n .map(([id, delay]) => ({\n id,\n end: delay + layoutState.nodeAnimDuration,\n }))\n .sort((a, b) => a.end - b.end);\n\n doneNodesRef.current = new Set();\n setDoneNodes(new Set());\n\n const start = performance.now();\n let rafId = 0;\n let index = 0;\n\n const tick = () => {\n const elapsed = (performance.now() - start) / 1000;\n let updated = false;\n\n while (index < entries.length && elapsed >= entries[index].end) {\n doneNodesRef.current.add(entries[index].id);\n index += 1;\n updated = true;\n }\n\n if (updated) {\n setDoneNodes(new Set(doneNodesRef.current));\n }\n\n if (index < entries.length) {\n rafId = requestAnimationFrame(tick);\n }\n };\n\n rafId = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(rafId);\n }, [\n layoutState.animationTotal,\n layoutState.nodeAnimDuration,\n layoutState.nodeDelays,\n ]);\n\n return { doneNodes, layoutState };\n}\n"],"mappings":"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","names":["React","import_jsx_runtime","import_jsx_runtime"]}
|
package/dist/index.css
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
/* src/node-tree.css */
|
|
2
|
-
@keyframes unt-node-enter {
|
|
3
|
-
0% {
|
|
4
|
-
opacity: 0;
|
|
5
|
-
}
|
|
6
|
-
100% {
|
|
7
|
-
opacity: 1;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
2
|
.unt-tree-root-container {
|
|
11
3
|
position: relative;
|
|
12
4
|
width: 100%;
|
|
@@ -65,7 +57,15 @@
|
|
|
65
57
|
inset: 0;
|
|
66
58
|
z-index: 0;
|
|
67
59
|
}
|
|
68
|
-
|
|
60
|
+
@keyframes unt-node-enter {
|
|
61
|
+
0% {
|
|
62
|
+
opacity: 0;
|
|
63
|
+
}
|
|
64
|
+
100% {
|
|
65
|
+
opacity: 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
.unt-node-enter {
|
|
69
69
|
animation-name: unt-node-enter;
|
|
70
70
|
animation-timing-function: ease-out;
|
|
71
71
|
animation-fill-mode: both;
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
opacity: 1;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
.node-line {
|
|
82
|
+
.unt-node-line {
|
|
83
83
|
animation-name: unt-line-draw;
|
|
84
84
|
animation-timing-function: ease-out;
|
|
85
85
|
animation-fill-mode: both;
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/node-tree.css"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../src/node-tree.css"],"sourcesContent":[".unt-tree-root-container {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.unt-tree-canvas {\r\n position: relative;\r\n}\r\n\r\n.unt-tree-node-hit {\r\n cursor: auto;\r\n}\r\n\r\n.unt-tree-node-frame {\r\n position: relative;\r\n display: flex;\r\n border: 1px solid rgba(255, 255, 255, 0.2);\r\n padding: 1rem;\r\n}\r\n\r\n.unt-tree-debug-badge {\r\n position: absolute;\r\n top: 0.5rem;\r\n left: 0.5rem;\r\n z-index: 10;\r\n padding: 0.25rem 0.5rem;\r\n font-size: 0.75rem;\r\n line-height: 1rem;\r\n}\r\n\r\n.unt-tree-debug-badge--0 {\r\n background: #a7f3d0;\r\n color: #042f2e;\r\n}\r\n\r\n.unt-tree-debug-badge--1 {\r\n background: #bae6fd;\r\n color: #082f49;\r\n}\r\n\r\n.unt-tree-debug-badge--2 {\r\n background: #fde68a;\r\n color: #451a03;\r\n}\r\n\r\n.unt-tree-debug-badge--3 {\r\n background: #fecdd3;\r\n color: #4c0519;\r\n}\r\n\r\n.unt-tree-debug-badge--4 {\r\n background: #d9f99d;\r\n color: #1a2e05;\r\n}\r\n\r\n.unt-tree-debug-badge--5 {\r\n background: #ddd6fe;\r\n color: #2e1065;\r\n}\r\n\r\n.unt-tree-connections {\r\n pointer-events: none;\r\n position: absolute;\r\n inset: 0;\r\n z-index: 0;\r\n}\r\n\r\n@keyframes unt-node-enter {\r\n 0% {\r\n opacity: 0;\r\n }\r\n 100% {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.unt-node-enter {\r\n animation-name: unt-node-enter;\r\n animation-timing-function: ease-out;\r\n animation-fill-mode: both;\r\n}\r\n\r\n@keyframes unt-line-draw {\r\n 0% {\r\n opacity: 0.2;\r\n }\r\n 100% {\r\n stroke-dashoffset: 0;\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.unt-node-line {\r\n animation-name: unt-line-draw;\r\n animation-timing-function: ease-out;\r\n animation-fill-mode: both;\r\n}\r\n"],"mappings":";AAAA,CAAC;AACC,YAAU;AACV,SAAO;AACP,UAAQ;AACR,cAAY;AACZ,YAAU;AACZ;AAEA,CAAC;AACC,YAAU;AACZ;AAEA,CAAC;AACC,UAAQ;AACV;AAEA,CAAC;AACC,YAAU;AACV,WAAS;AACT,UAAQ,IAAI,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AACtC,WAAS;AACX;AAEA,CAAC;AACC,YAAU;AACV,OAAK;AACL,QAAM;AACN,WAAS;AACT,WAAS,QAAQ;AACjB,aAAW;AACX,eAAa;AACf;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,kBAAgB;AAChB,YAAU;AACV,SAAO;AACP,WAAS;AACX;AAEA,WAAW;AACT;AACE,aAAS;AACX;AACA;AACE,aAAS;AACX;AACF;AAEA,CATW;AAUT,kBAAgB;AAChB,6BAA2B;AAC3B,uBAAqB;AACvB;AAEA,WAAW;AACT;AACE,aAAS;AACX;AACA;AACE,uBAAmB;AACnB,aAAS;AACX;AACF;AAEA,CAAC;AACC,kBAAgB;AAChB,6BAA2B;AAC3B,uBAAqB;AACvB;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -49,7 +49,7 @@ function TreeConnections({
|
|
|
49
49
|
y1: segment.y1 - layoutState.svgBounds.offsetY,
|
|
50
50
|
x2: segment.x2 - layoutState.svgBounds.offsetX,
|
|
51
51
|
y2: segment.y2 - layoutState.svgBounds.offsetY,
|
|
52
|
-
className: "node-line",
|
|
52
|
+
className: "unt-node-line",
|
|
53
53
|
style: {
|
|
54
54
|
strokeDasharray: segment.length,
|
|
55
55
|
strokeDashoffset: segment.length,
|
|
@@ -87,7 +87,13 @@ function axisToFlexJustify(axis) {
|
|
|
87
87
|
}
|
|
88
88
|
return "center";
|
|
89
89
|
}
|
|
90
|
-
function NodeFrame({
|
|
90
|
+
function NodeFrame({
|
|
91
|
+
node,
|
|
92
|
+
className,
|
|
93
|
+
onRef,
|
|
94
|
+
children,
|
|
95
|
+
...props
|
|
96
|
+
}) {
|
|
91
97
|
return /* @__PURE__ */ jsx2(
|
|
92
98
|
"div",
|
|
93
99
|
{
|
|
@@ -137,7 +143,9 @@ function renderTreeNode({
|
|
|
137
143
|
flexShrink: 0,
|
|
138
144
|
flexDirection: childrenLayoutIsStack ? "column" : "row",
|
|
139
145
|
alignItems: axisToFlexAlign(childrenLayoutIsStack ? alignX : alignY),
|
|
140
|
-
justifyContent: axisToFlexJustify(
|
|
146
|
+
justifyContent: axisToFlexJustify(
|
|
147
|
+
childrenLayoutIsStack ? alignY : alignX
|
|
148
|
+
),
|
|
141
149
|
gap,
|
|
142
150
|
marginTop: flowDown || stackUnder ? gap : 0,
|
|
143
151
|
marginLeft: flowDown ? node.children?.layout === "stack" ? gap : 0 : stackUnder ? gap / 2 : gap
|
|
@@ -180,7 +188,7 @@ function renderTreeNode({
|
|
|
180
188
|
NodeFrame,
|
|
181
189
|
{
|
|
182
190
|
node,
|
|
183
|
-
className: cn("node-enter unt-tree-node-frame", nodeFrameClassName),
|
|
191
|
+
className: cn("unt-node-enter unt-tree-node-frame", nodeFrameClassName),
|
|
184
192
|
style: {
|
|
185
193
|
justifyContent: axisToFlexJustify(alignX),
|
|
186
194
|
animationDuration: `${layoutState.nodeAnimDuration}s`,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/node-tree.tsx","../src/utils/cn.ts","../src/components/tree-connections.tsx","../src/components/tree-renderer.tsx","../src/hooks/use-node-tree-layout.ts"],"sourcesContent":["import * as React from \"react\";\nimport \"../node-tree.css\";\nimport { cn } from \"../utils/cn\";\nimport { TreeConnections } from \"./tree-connections\";\nimport { TreeRenderer } from \"./tree-renderer\";\nimport { useNodeTreeLayout } from \"../hooks/use-node-tree-layout\";\nimport type { AlignAxis, NodeTreeProps } from \"../types\";\n\r\nconst NodeTree = React.forwardRef<HTMLDivElement, NodeTreeProps>(\r\n (\r\n {\r\n className,\r\n nodeTree,\r\n layout,\r\n connection,\r\n animation,\r\n nodeFrame,\r\n debug = false,\r\n style,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n const containerRef = React.useRef<HTMLDivElement | null>(null);\r\n const nodeRefs = React.useRef(new Map<string, HTMLDivElement>());\r\n const registerNode = React.useCallback(\r\n (id: string, element: HTMLDivElement | null) => {\r\n const registry = nodeRefs.current;\r\n if (element) {\r\n registry.set(id, element);\r\n } else {\r\n registry.delete(id);\r\n }\r\n },\r\n [],\r\n );\r\n\r\n const resolvedAlign = layout?.align ?? \"center\";\r\n const resolvedDirection = layout?.direction ?? \"down\";\r\n const resolvedRootLayout = layout?.root ?? \"stack\";\r\n const resolvedPaddingContainer = layout?.containerPadding ?? 128;\r\n const resolvedPadding = layout?.padding ?? 64;\r\n const resolvedGap = layout?.gap ?? 64;\r\n const resolvedStrokeColor = connection?.color ?? \"rgba(255,255,255)\";\r\n const resolvedStrokeWidth = connection?.width ?? 1;\r\n const resolvedAnimationDurationMs = animation?.durationMs ?? 2000;\r\n const resolvedNodeFrameStyle = nodeFrame?.style;\r\n\r\n const { doneNodes, layoutState } = useNodeTreeLayout({\r\n nodeTree,\r\n direction: resolvedDirection,\r\n gap: resolvedGap,\r\n padding: resolvedPadding,\r\n animationSpeed: resolvedAnimationDurationMs,\r\n debug,\r\n containerRef,\r\n nodeRefs,\r\n });\r\n\r\n const flowDown = resolvedDirection === \"down\";\r\n const alignValue = resolvedAlign;\r\n const alignX: AlignAxis =\r\n typeof alignValue === \"string\" ? alignValue : alignValue.x;\r\n const alignY: AlignAxis =\r\n typeof alignValue === \"string\" ? \"start\" : alignValue.y;\r\n const resolvedConnectionOpacity = connection?.opacity ?? (debug ? 1 : 0.1);\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={cn(\"unt-tree-root-container\", className?.root)}\r\n style={style}\r\n {...props}\r\n >\r\n <div\r\n ref={containerRef}\r\n className={cn(\"unt-tree-canvas\", className?.canvas)}\r\n style={{ padding: resolvedPaddingContainer }}\r\n >\r\n <TreeConnections\r\n layoutState={layoutState}\r\n debug={debug}\r\n strokeColor={resolvedStrokeColor}\r\n strokeWidth={resolvedStrokeWidth}\r\n opacity={resolvedConnectionOpacity}\r\n className={className?.connections}\r\n />\r\n <TreeRenderer\r\n nodeTree={nodeTree}\r\n rootLayout={resolvedRootLayout}\r\n flowDown={flowDown}\r\n alignX={alignX}\r\n alignY={alignY}\r\n gap={resolvedGap}\r\n debug={debug}\r\n layoutState={layoutState}\r\n doneNodes={doneNodes}\r\n registerNode={registerNode}\r\n rendererClassName={className?.renderer}\r\n nodeFrameClassName={className?.frame}\r\n nodeFrameStyle={resolvedNodeFrameStyle}\r\n />\r\n </div>\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nNodeTree.displayName = \"NodeTree\";\r\n\r\nexport { NodeTree };\r\n","import { clsx, type ClassValue } from \"clsx\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return clsx(inputs);\r\n}\r\n","import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport type { NodeTreeLayoutState } from \"../types\";\n\r\ntype TreeConnectionsProps = {\r\n layoutState: NodeTreeLayoutState;\r\n debug: boolean;\r\n strokeColor: string;\r\n strokeWidth: number;\r\n opacity: number;\r\n className?: string;\r\n};\r\n\r\nexport function TreeConnections({\r\n layoutState,\r\n debug,\r\n strokeColor,\r\n strokeWidth,\r\n opacity,\r\n className,\r\n}: TreeConnectionsProps) {\r\n if (!layoutState.svgBounds) {\r\n return null;\r\n }\r\n\r\n return (\r\n <svg\r\n className={cn(\"unt-tree-connections\", className)}\r\n width={layoutState.svgBounds.width}\r\n height={layoutState.svgBounds.height}\r\n viewBox={`0 0 ${layoutState.svgBounds.width} ${layoutState.svgBounds.height}`}\r\n style={{\r\n left: layoutState.svgBounds.offsetX,\r\n top: layoutState.svgBounds.offsetY,\r\n opacity,\r\n }}\r\n >\r\n {layoutState.segments.map((segment) => {\r\n const debugPalette = [\r\n \"#22d3ee\",\r\n \"#a855f7\",\r\n \"#f59e0b\",\r\n \"#10b981\",\r\n \"#f97316\",\r\n \"#38bdf8\",\r\n ];\r\n const lineColor = debug\r\n ? debugPalette[segment.colorIndex % debugPalette.length]\r\n : strokeColor;\r\n return (\r\n <line\r\n key={`${segment.x1}-${segment.y1}-${segment.x2}-${segment.y2}-${segment.delay}`}\r\n x1={segment.x1 - layoutState.svgBounds!.offsetX}\r\n y1={segment.y1 - layoutState.svgBounds!.offsetY}\r\n x2={segment.x2 - layoutState.svgBounds!.offsetX}\r\n y2={segment.y2 - layoutState.svgBounds!.offsetY}\r\n className=\"node-line\"\r\n style={{\r\n strokeDasharray: segment.length,\r\n strokeDashoffset: segment.length,\r\n animationDelay: `${segment.delay}s`,\r\n animationDuration: `${segment.duration}s`,\r\n }}\r\n stroke={lineColor}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n );\r\n })}\r\n </svg>\r\n );\r\n}\r\n","import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport type {\n AlignAxis,\n NodeFrameProps,\n NodeTreeLayoutState,\n TreeNode,\n} from \"../types\";\n\r\ntype TreeRendererProps = {\r\n nodeTree: TreeNode[];\n rootLayout: \"stack\" | \"row\";\r\n flowDown: boolean;\r\n alignX: AlignAxis;\r\n alignY: AlignAxis;\r\n gap: number;\r\n debug: boolean;\r\n layoutState: NodeTreeLayoutState;\r\n doneNodes: Set<string>;\r\n registerNode: (id: string, element: HTMLDivElement | null) => void;\r\n rendererClassName?: string;\r\n nodeFrameClassName?: string;\r\n nodeFrameStyle?: React.CSSProperties;\r\n};\r\n\r\nfunction axisToFlexAlign(axis: AlignAxis): React.CSSProperties[\"alignItems\"] {\r\n if (axis === \"start\") {\r\n return \"flex-start\";\r\n }\r\n if (axis === \"end\") {\r\n return \"flex-end\";\r\n }\r\n return \"center\";\r\n}\r\n\r\nfunction axisToFlexJustify(axis: AlignAxis): React.CSSProperties[\"justifyContent\"] {\r\n if (axis === \"start\") {\r\n return \"flex-start\";\r\n }\r\n if (axis === \"end\") {\r\n return \"flex-end\";\r\n }\r\n return \"center\";\r\n}\r\n\r\nfunction NodeFrame({ node, className, onRef, children, ...props }: NodeFrameProps) {\r\n return (\r\n <div\r\n ref={(element) => {\r\n onRef(node.id, element);\r\n }}\r\n className={cn(\"unt-tree-node-hit\", className)}\r\n data-nodeframe\r\n data-viewport-no-pan\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nfunction renderTreeNode({\r\n node,\r\n index,\r\n parentId,\r\n depth,\r\n path,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n}: {\r\n node: TreeNode;\n index: number;\r\n parentId?: string;\r\n depth: number;\r\n path: Set<string>;\r\n flowDown: boolean;\r\n alignX: AlignAxis;\r\n alignY: AlignAxis;\r\n gap: number;\r\n debug: boolean;\r\n layoutState: NodeTreeLayoutState;\r\n doneNodes: Set<string>;\r\n registerNode: (id: string, element: HTMLDivElement | null) => void;\r\n nodeFrameClassName?: string;\r\n nodeFrameStyle?: React.CSSProperties;\r\n}): React.ReactNode {\r\n const stackUnder = !flowDown && node.children?.layout === \"stack\";\r\n if (path.has(node.id)) {\r\n return null;\r\n }\r\n\r\n path.add(node.id);\r\n const childrenLayoutIsStack = node.children?.layout === \"stack\" || !flowDown;\r\n const childCount = node.children?.nodes.length ?? 0;\r\n const isLeaf = childCount === 0;\r\n const pathIds = [...path];\r\n const childrenContent =\r\n node.children?.nodes && node.children.nodes.length > 0 ? (\r\n <div\r\n className=\"unt-tree-children\"\r\n style={{\r\n display: \"flex\",\r\n flexShrink: 0,\r\n flexDirection: childrenLayoutIsStack ? \"column\" : \"row\",\r\n alignItems: axisToFlexAlign(childrenLayoutIsStack ? alignX : alignY),\r\n justifyContent: axisToFlexJustify(childrenLayoutIsStack ? alignY : alignX),\r\n gap,\r\n marginTop: flowDown || stackUnder ? gap : 0,\r\n marginLeft: flowDown\r\n ? node.children?.layout === \"stack\"\r\n ? gap\r\n : 0\r\n : stackUnder\r\n ? gap / 2\r\n : gap,\r\n }}\r\n >\r\n {node.children.nodes.map((child, childIndex) =>\r\n renderTreeNode({\r\n node: child,\r\n index: childIndex,\r\n parentId: node.id,\r\n depth: depth + 1,\r\n path,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n }),\r\n )}\r\n </div>\r\n ) : null;\r\n path.delete(node.id);\r\n\r\n return (\r\n <div\r\n key={`${node.id}-${index}`}\r\n className=\"unt-tree-node-wrap\"\r\n style={{\r\n display: \"flex\",\r\n position: \"relative\",\r\n flexDirection: flowDown || stackUnder ? \"column\" : \"row\",\r\n alignItems: axisToFlexAlign(flowDown ? alignX : alignY),\r\n justifyContent: axisToFlexJustify(flowDown ? alignY : alignX),\r\n }}\r\n >\r\n <NodeFrame\r\n node={node}\r\n className={cn(\"node-enter unt-tree-node-frame\", nodeFrameClassName)}\r\n style={{\r\n justifyContent: axisToFlexJustify(alignX),\r\n animationDuration: `${layoutState.nodeAnimDuration}s`,\r\n animationDelay: `${\r\n layoutState.nodeDelays.get(node.id) ?? depth * 0.08 + index * 0.04\r\n }s`,\r\n ...nodeFrameStyle,\r\n }}\r\n onRef={registerNode}\r\n >\r\n {debug ? (\r\n <div\r\n className={cn(\r\n \"unt-tree-debug-badge\",\r\n `unt-tree-debug-badge--${depth % 6}`,\r\n )}\r\n >\r\n <div>{`DEPTH: ${depth}`}</div>\r\n <div>{`PARENT-ID: ${parentId ?? \"root\"}`}</div>\r\n <div>{`NODE-ID: ${node.id}`}</div>\r\n <div>{`C-LAYOUT: ${node.children?.layout ?? \"N/A\"}`}</div>\r\n </div>\r\n ) : null}\r\n {node.render({\r\n node,\r\n index,\r\n depth,\r\n parentId,\r\n path: pathIds,\r\n isLeaf,\r\n childCount,\r\n isNodeAnimationDone: doneNodes.has(node.id),\r\n })}\r\n </NodeFrame>\r\n\r\n {childrenContent}\r\n </div>\r\n );\r\n}\r\n\r\nexport function TreeRenderer({\r\n nodeTree,\r\n rootLayout,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n rendererClassName,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n}: TreeRendererProps) {\r\n const rootLayoutRow = rootLayout === \"row\";\r\n return (\r\n <section\r\n className={cn(\"unt-tree-renderer\", rendererClassName)}\r\n style={{\r\n gap,\r\n display: \"flex\",\r\n width: \"100%\",\r\n overflow: \"visible\",\r\n position: \"relative\",\r\n zIndex: 10,\r\n flexDirection: rootLayoutRow ? \"row\" : \"column\",\r\n alignItems: axisToFlexAlign(rootLayoutRow ? alignY : alignX),\r\n justifyContent: axisToFlexJustify(rootLayoutRow ? alignX : alignY),\r\n }}\r\n >\r\n {nodeTree.map((node, index) =>\r\n renderTreeNode({\r\n node,\r\n index,\r\n depth: 0,\r\n path: new Set<string>(),\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n }),\r\n )}\r\n </section>\r\n );\r\n}\r\n","import * as React from \"react\";\nimport type {\n NodeTreeLayoutState,\n TreeNode,\n TreeNodeEdge,\n} from \"../types\";\n\ntype EdgeGeometry = {\n edge: TreeNodeEdge;\n fromX: number;\n fromY: number;\n fromBottom: number;\n fromCenterX: number;\n toX: number;\n toY: number;\n toLeft: number;\n toCenterY: number;\n};\n\ntype UseNodeTreeLayoutParams = {\n nodeTree: TreeNode[];\n direction: \"down\" | \"right\";\n gap: number;\n padding: number;\n animationSpeed: number;\n debug: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n nodeRefs: React.MutableRefObject<Map<string, HTMLDivElement>>;\n};\n\nconst EMPTY_LAYOUT: NodeTreeLayoutState = {\n segments: [],\n nodeDelays: new Map(),\n nodeAnimDuration: 0.42,\n animationTotal: 0,\n svgBounds: null,\n};\n\nfunction collectEdges(nodes: TreeNode[]) {\n const edges: TreeNodeEdge[] = [];\n const visiting = new Set<string>();\n const visit = (node: TreeNode) => {\n if (visiting.has(node.id)) {\n return;\n }\n visiting.add(node.id);\n if (node.children?.nodes && node.children.nodes.length > 0) {\n node.children.nodes.forEach((child, index) => {\n const key = `${node.id}=>${child.id}`;\n edges.push({\n key,\n from: node.id,\n to: child.id,\n index,\n count: node.children?.nodes.length ?? 1,\n });\n visit(child);\n });\n }\n visiting.delete(node.id);\n };\n\n nodes.forEach(visit);\n return edges;\n}\n\nfunction collectDescendants(nodes: TreeNode[]) {\n const map = new Map<string, string[]>();\n const visiting = new Set<string>();\n const visit = (node: TreeNode): string[] => {\n if (visiting.has(node.id)) {\n return [];\n }\n visiting.add(node.id);\n const descendants: string[] = [];\n node.children?.nodes.forEach((child) => {\n descendants.push(child.id);\n descendants.push(...visit(child));\n });\n map.set(node.id, descendants);\n visiting.delete(node.id);\n return descendants;\n };\n nodes.forEach(visit);\n return map;\n}\n\nexport function useNodeTreeLayout({\n nodeTree,\n direction,\n gap,\n padding,\n animationSpeed,\n debug,\n containerRef,\n nodeRefs,\n}: UseNodeTreeLayoutParams) {\n const [layoutState, setLayoutState] =\n React.useState<NodeTreeLayoutState>(EMPTY_LAYOUT);\n const [doneNodes, setDoneNodes] = React.useState<Set<string>>(\n () => new Set(),\n );\n const doneNodesRef = React.useRef<Set<string>>(new Set());\n const edges = React.useMemo(() => collectEdges(nodeTree), [nodeTree]);\n const descendantMap = React.useMemo(\n () => collectDescendants(nodeTree),\n [nodeTree],\n );\n\n const totalAnimationSec = Math.max(0.1, animationSpeed / 1000);\n\n const drawConnections = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n const flowDown = direction === \"down\";\n\n const getRelativeRect = (element: HTMLElement) => {\n let left = 0;\n let top = 0;\n let current: HTMLElement | null = element;\n while (current && current !== container) {\n left += current.offsetLeft;\n top += current.offsetTop;\n current = current.offsetParent as HTMLElement | null;\n }\n return {\n left,\n top,\n right: left + element.offsetWidth,\n bottom: top + element.offsetHeight,\n width: element.offsetWidth,\n height: element.offsetHeight,\n };\n };\n\n const rectMap = new Map<string, ReturnType<typeof getRelativeRect>>();\n nodeRefs.current.forEach((el, id) => {\n rectMap.set(id, getRelativeRect(el));\n });\n\n const nextSegments: NodeTreeLayoutState[\"segments\"] = [];\n const nextNodeDelays = new Map<string, number>();\n const baseSecondsPerPixel = 1 / 900;\n const baseNodeAnimDuration = 0.42;\n const edgeColorIndex = debug ? new Map<string, number>() : null;\n const edgeData = new Map<string, EdgeGeometry>();\n\n edges.forEach((edge) => {\n const fromRect = rectMap.get(edge.from);\n const toRect = rectMap.get(edge.to);\n if (!fromRect || !toRect) {\n return;\n }\n\n const fromX = flowDown ? fromRect.left + fromRect.width / 2 : fromRect.right;\n const fromY = flowDown\n ? fromRect.bottom\n : fromRect.top + fromRect.height / 2;\n const toX = flowDown ? toRect.left + toRect.width / 2 : toRect.left;\n const toY = flowDown ? toRect.top : toRect.top + toRect.height / 2;\n\n edgeData.set(edge.key, {\n edge,\n fromX,\n fromY,\n fromBottom: fromRect.bottom,\n fromCenterX: fromRect.left + fromRect.width / 2,\n toX,\n toY,\n toLeft: toRect.left,\n toCenterY: toRect.top + toRect.height / 2,\n });\n });\n\n const pushSegment = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n depth: number,\n delay: number,\n colorIndex: number,\n order: number,\n ) => {\n const length = Math.hypot(x2 - x1, y2 - y1);\n const duration = Math.max(0.05, length * baseSecondsPerPixel);\n nextSegments.push({\n x1,\n y1,\n x2,\n y2,\n length,\n depth,\n delay,\n duration,\n colorIndex,\n order,\n });\n return duration;\n };\n\n const visit = (node: TreeNode, depth: number, nodeDelay: number) => {\n const existing = nextNodeDelays.get(node.id) ?? 0;\n const resolvedDelay = Math.max(existing, nodeDelay);\n nextNodeDelays.set(node.id, resolvedDelay);\n\n const childEdges =\n node.children?.nodes\n .map((child) => edgeData.get(`${node.id}=>${child.id}`))\n .filter((edge): edge is EdgeGeometry => Boolean(edge)) ?? [];\n const stackLayout = node.children?.layout === \"stack\";\n const descendantIds =\n flowDown && stackLayout ? (descendantMap.get(node.id) ?? []) : [];\n const descendantLefts =\n flowDown && stackLayout\n ? descendantIds\n .map((id) => rectMap.get(id))\n .filter((rect): rect is NonNullable<typeof rect> => Boolean(rect))\n .map((rect) => rect.left)\n : [];\n const descendantMinLeft =\n descendantLefts.length > 0 ? Math.min(...descendantLefts) : undefined;\n const gutterX =\n flowDown && stackLayout\n ? (descendantMinLeft ??\n (childEdges.length > 0\n ? Math.min(...childEdges.map((edge) => edge.toLeft))\n : 0)) -\n gap / 2\n : 0;\n const gutterXRight =\n !flowDown && stackLayout\n ? (childEdges.length > 0\n ? Math.min(...childEdges.map((edge) => edge.toLeft))\n : 0) -\n gap / 2\n : 0;\n\n const orderedChildren =\n node.children?.nodes\n .map((child) => {\n const edge = edgeData.get(`${node.id}=>${child.id}`);\n if (!edge) {\n return null;\n }\n const dx = edge.toX - edge.fromX;\n const dy = edge.toY - edge.fromY;\n const length = Math.hypot(dx, dy);\n return { child, edge, length, toX: edge.toX };\n })\n .filter(\n (entry): entry is NonNullable<typeof entry> => Boolean(entry),\n ) ?? [];\n\n if (debug) {\n orderedChildren.sort((a, b) => {\n if (a.length !== b.length) {\n return a.length - b.length;\n }\n return a.toX - b.toX;\n });\n }\n\n orderedChildren.forEach((entry, index) => {\n const { child, edge } = entry;\n const edgeKey = edge.edge.key;\n let colorIndex = 0;\n if (edgeColorIndex) {\n if (!edgeColorIndex.has(edgeKey)) {\n edgeColorIndex.set(edgeKey, edgeColorIndex.size);\n }\n colorIndex = edgeColorIndex.get(edgeKey) ?? 0;\n }\n const order = orderedChildren.length - 1 - index;\n const edgeDelay = resolvedDelay + baseNodeAnimDuration + index * 0.04;\n let totalDuration = 0;\n if (flowDown && stackLayout) {\n const baseDrop = Math.max(12, gap / 2);\n const targetY = edge.toCenterY;\n const midY =\n edge.fromY + Math.min(baseDrop, (targetY - edge.fromY) * 0.6);\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n edge.fromX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromX,\n midY,\n gutterX,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterX,\n midY,\n gutterX,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterX,\n targetY,\n edge.toLeft,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else if (!flowDown && stackLayout) {\n const targetY = edge.toCenterY;\n const baseDrop = Math.max(12, gap / 2);\n const midY =\n edge.fromBottom +\n Math.min(baseDrop, (targetY - edge.fromBottom) * 0.6);\n totalDuration += pushSegment(\n edge.fromCenterX,\n edge.fromBottom,\n edge.fromCenterX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromCenterX,\n midY,\n gutterXRight,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterXRight,\n midY,\n gutterXRight,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterXRight,\n targetY,\n edge.toLeft,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else if (flowDown) {\n const midY = edge.fromY + (edge.toY - edge.fromY) * 0.5;\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n edge.fromX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromX,\n midY,\n edge.toX,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.toX,\n midY,\n edge.toX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else {\n const midX = edge.fromX + (edge.toX - edge.fromX) * 0.5;\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n midX,\n edge.fromY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n midX,\n edge.fromY,\n midX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n midX,\n edge.toY,\n edge.toX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n }\n visit(child, depth + 1, edgeDelay + totalDuration);\n });\n };\n\n nodeTree.forEach((node) => visit(node, 0, 0));\n\n if (nextSegments.length === 0) {\n setLayoutState((prev) => ({\n ...prev,\n segments: [],\n svgBounds: null,\n animationTotal: 0,\n }));\n setDoneNodes(new Set());\n doneNodesRef.current = new Set();\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n nextSegments.forEach((segment) => {\n minX = Math.min(minX, segment.x1, segment.x2);\n minY = Math.min(minY, segment.y1, segment.y2);\n maxX = Math.max(maxX, segment.x1, segment.x2);\n maxY = Math.max(maxY, segment.y1, segment.y2);\n });\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return;\n }\n\n const width = Math.max(1, maxX - minX + padding * 2);\n const height = Math.max(1, maxY - minY + padding * 2);\n const offsetX = minX - padding;\n const offsetY = minY - padding;\n\n const maxLineEnd = Math.max(\n 0,\n ...nextSegments.map((segment) => segment.delay + segment.duration),\n );\n const maxNodeEnd =\n Math.max(0, ...Array.from(nextNodeDelays.values())) + baseNodeAnimDuration;\n const animationMax = Math.max(maxLineEnd, maxNodeEnd);\n const scale = animationMax > 0 ? totalAnimationSec / animationMax : 1;\n const scaledSegments = nextSegments\n .map((segment) => ({\n ...segment,\n delay: segment.delay * scale,\n duration: segment.duration * scale,\n }))\n .sort((a, b) => a.order - b.order);\n const scaledNodeDelays = new Map<string, number>();\n nextNodeDelays.forEach((value, key) => {\n scaledNodeDelays.set(key, value * scale);\n });\n\n setLayoutState({\n segments: scaledSegments,\n nodeDelays: scaledNodeDelays,\n nodeAnimDuration: baseNodeAnimDuration * scale,\n animationTotal: animationMax * scale,\n svgBounds: { width, height, offsetX, offsetY },\n });\n setDoneNodes(new Set());\n doneNodesRef.current = new Set();\n }, [\n animationSpeed,\n containerRef,\n debug,\n descendantMap,\n direction,\n edges,\n gap,\n nodeRefs,\n nodeTree,\n padding,\n totalAnimationSec,\n ]);\n\n React.useLayoutEffect(() => {\n const rafId = requestAnimationFrame(drawConnections);\n return () => cancelAnimationFrame(rafId);\n }, [drawConnections, nodeTree]);\n\n React.useEffect(() => {\n if (layoutState.animationTotal <= 0 || layoutState.nodeDelays.size === 0) {\n return;\n }\n\n const entries = Array.from(layoutState.nodeDelays.entries())\n .map(([id, delay]) => ({\n id,\n end: delay + layoutState.nodeAnimDuration,\n }))\n .sort((a, b) => a.end - b.end);\n\n doneNodesRef.current = new Set();\n setDoneNodes(new Set());\n\n const start = performance.now();\n let rafId = 0;\n let index = 0;\n\n const tick = () => {\n const elapsed = (performance.now() - start) / 1000;\n let updated = false;\n\n while (index < entries.length && elapsed >= entries[index].end) {\n doneNodesRef.current.add(entries[index].id);\n index += 1;\n updated = true;\n }\n\n if (updated) {\n setDoneNodes(new Set(doneNodesRef.current));\n }\n\n if (index < entries.length) {\n rafId = requestAnimationFrame(tick);\n }\n };\n\n rafId = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(rafId);\n }, [\n layoutState.animationTotal,\n layoutState.nodeAnimDuration,\n layoutState.nodeDelays,\n ]);\n\n return { doneNodes, layoutState };\n}\n"],"mappings":"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","names":["React","jsx","jsx","jsxs"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/node-tree.tsx","../src/utils/cn.ts","../src/components/tree-connections.tsx","../src/components/tree-renderer.tsx","../src/hooks/use-node-tree-layout.ts"],"sourcesContent":["import * as React from \"react\";\nimport \"../node-tree.css\";\nimport { cn } from \"../utils/cn\";\nimport { TreeConnections } from \"./tree-connections\";\nimport { TreeRenderer } from \"./tree-renderer\";\nimport { useNodeTreeLayout } from \"../hooks/use-node-tree-layout\";\nimport type { AlignAxis, NodeTreeProps } from \"../types\";\n\r\nconst NodeTree = React.forwardRef<HTMLDivElement, NodeTreeProps>(\r\n (\r\n {\r\n className,\r\n nodeTree,\r\n layout,\r\n connection,\r\n animation,\r\n nodeFrame,\r\n debug = false,\r\n style,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n const containerRef = React.useRef<HTMLDivElement | null>(null);\r\n const nodeRefs = React.useRef(new Map<string, HTMLDivElement>());\r\n const registerNode = React.useCallback(\r\n (id: string, element: HTMLDivElement | null) => {\r\n const registry = nodeRefs.current;\r\n if (element) {\r\n registry.set(id, element);\r\n } else {\r\n registry.delete(id);\r\n }\r\n },\r\n [],\r\n );\r\n\r\n const resolvedAlign = layout?.align ?? \"center\";\r\n const resolvedDirection = layout?.direction ?? \"down\";\r\n const resolvedRootLayout = layout?.root ?? \"stack\";\r\n const resolvedPaddingContainer = layout?.containerPadding ?? 128;\r\n const resolvedPadding = layout?.padding ?? 64;\r\n const resolvedGap = layout?.gap ?? 64;\r\n const resolvedStrokeColor = connection?.color ?? \"rgba(255,255,255)\";\r\n const resolvedStrokeWidth = connection?.width ?? 1;\r\n const resolvedAnimationDurationMs = animation?.durationMs ?? 2000;\r\n const resolvedNodeFrameStyle = nodeFrame?.style;\r\n\r\n const { doneNodes, layoutState } = useNodeTreeLayout({\r\n nodeTree,\r\n direction: resolvedDirection,\r\n gap: resolvedGap,\r\n padding: resolvedPadding,\r\n animationSpeed: resolvedAnimationDurationMs,\r\n debug,\r\n containerRef,\r\n nodeRefs,\r\n });\r\n\r\n const flowDown = resolvedDirection === \"down\";\r\n const alignValue = resolvedAlign;\r\n const alignX: AlignAxis =\r\n typeof alignValue === \"string\" ? alignValue : alignValue.x;\r\n const alignY: AlignAxis =\r\n typeof alignValue === \"string\" ? \"start\" : alignValue.y;\r\n const resolvedConnectionOpacity = connection?.opacity ?? (debug ? 1 : 0.1);\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={cn(\"unt-tree-root-container\", className?.root)}\r\n style={style}\r\n {...props}\r\n >\r\n <div\r\n ref={containerRef}\r\n className={cn(\"unt-tree-canvas\", className?.canvas)}\r\n style={{ padding: resolvedPaddingContainer }}\r\n >\r\n <TreeConnections\r\n layoutState={layoutState}\r\n debug={debug}\r\n strokeColor={resolvedStrokeColor}\r\n strokeWidth={resolvedStrokeWidth}\r\n opacity={resolvedConnectionOpacity}\r\n className={className?.connections}\r\n />\r\n <TreeRenderer\r\n nodeTree={nodeTree}\r\n rootLayout={resolvedRootLayout}\r\n flowDown={flowDown}\r\n alignX={alignX}\r\n alignY={alignY}\r\n gap={resolvedGap}\r\n debug={debug}\r\n layoutState={layoutState}\r\n doneNodes={doneNodes}\r\n registerNode={registerNode}\r\n rendererClassName={className?.renderer}\r\n nodeFrameClassName={className?.frame}\r\n nodeFrameStyle={resolvedNodeFrameStyle}\r\n />\r\n </div>\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nNodeTree.displayName = \"NodeTree\";\r\n\r\nexport { NodeTree };\r\n","import { clsx, type ClassValue } from \"clsx\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return clsx(inputs);\r\n}\r\n","import * as React from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\nimport type { NodeTreeLayoutState } from \"../types\";\r\n\r\ntype TreeConnectionsProps = {\r\n layoutState: NodeTreeLayoutState;\r\n debug: boolean;\r\n strokeColor: string;\r\n strokeWidth: number;\r\n opacity: number;\r\n className?: string;\r\n};\r\n\r\nexport function TreeConnections({\r\n layoutState,\r\n debug,\r\n strokeColor,\r\n strokeWidth,\r\n opacity,\r\n className,\r\n}: TreeConnectionsProps) {\r\n if (!layoutState.svgBounds) {\r\n return null;\r\n }\r\n\r\n return (\r\n <svg\r\n className={cn(\"unt-tree-connections\", className)}\r\n width={layoutState.svgBounds.width}\r\n height={layoutState.svgBounds.height}\r\n viewBox={`0 0 ${layoutState.svgBounds.width} ${layoutState.svgBounds.height}`}\r\n style={{\r\n left: layoutState.svgBounds.offsetX,\r\n top: layoutState.svgBounds.offsetY,\r\n opacity,\r\n }}\r\n >\r\n {layoutState.segments.map((segment) => {\r\n const debugPalette = [\r\n \"#22d3ee\",\r\n \"#a855f7\",\r\n \"#f59e0b\",\r\n \"#10b981\",\r\n \"#f97316\",\r\n \"#38bdf8\",\r\n ];\r\n const lineColor = debug\r\n ? debugPalette[segment.colorIndex % debugPalette.length]\r\n : strokeColor;\r\n return (\r\n <line\r\n key={`${segment.x1}-${segment.y1}-${segment.x2}-${segment.y2}-${segment.delay}`}\r\n x1={segment.x1 - layoutState.svgBounds!.offsetX}\r\n y1={segment.y1 - layoutState.svgBounds!.offsetY}\r\n x2={segment.x2 - layoutState.svgBounds!.offsetX}\r\n y2={segment.y2 - layoutState.svgBounds!.offsetY}\r\n className=\"unt-node-line\"\r\n style={{\r\n strokeDasharray: segment.length,\r\n strokeDashoffset: segment.length,\r\n animationDelay: `${segment.delay}s`,\r\n animationDuration: `${segment.duration}s`,\r\n }}\r\n stroke={lineColor}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n );\r\n })}\r\n </svg>\r\n );\r\n}\r\n","import * as React from \"react\";\r\nimport { cn } from \"../utils/cn\";\r\nimport type {\r\n AlignAxis,\r\n NodeFrameProps,\r\n NodeTreeLayoutState,\r\n TreeNode,\r\n} from \"../types\";\r\n\r\ntype TreeRendererProps = {\r\n nodeTree: TreeNode[];\r\n rootLayout: \"stack\" | \"row\";\r\n flowDown: boolean;\r\n alignX: AlignAxis;\r\n alignY: AlignAxis;\r\n gap: number;\r\n debug: boolean;\r\n layoutState: NodeTreeLayoutState;\r\n doneNodes: Set<string>;\r\n registerNode: (id: string, element: HTMLDivElement | null) => void;\r\n rendererClassName?: string;\r\n nodeFrameClassName?: string;\r\n nodeFrameStyle?: React.CSSProperties;\r\n};\r\n\r\nfunction axisToFlexAlign(axis: AlignAxis): React.CSSProperties[\"alignItems\"] {\r\n if (axis === \"start\") {\r\n return \"flex-start\";\r\n }\r\n if (axis === \"end\") {\r\n return \"flex-end\";\r\n }\r\n return \"center\";\r\n}\r\n\r\nfunction axisToFlexJustify(\r\n axis: AlignAxis,\r\n): React.CSSProperties[\"justifyContent\"] {\r\n if (axis === \"start\") {\r\n return \"flex-start\";\r\n }\r\n if (axis === \"end\") {\r\n return \"flex-end\";\r\n }\r\n return \"center\";\r\n}\r\n\r\nfunction NodeFrame({\r\n node,\r\n className,\r\n onRef,\r\n children,\r\n ...props\r\n}: NodeFrameProps) {\r\n return (\r\n <div\r\n ref={(element) => {\r\n onRef(node.id, element);\r\n }}\r\n className={cn(\"unt-tree-node-hit\", className)}\r\n data-nodeframe\r\n data-viewport-no-pan\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n );\r\n}\r\n\r\nfunction renderTreeNode({\r\n node,\r\n index,\r\n parentId,\r\n depth,\r\n path,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n}: {\r\n node: TreeNode;\r\n index: number;\r\n parentId?: string;\r\n depth: number;\r\n path: Set<string>;\r\n flowDown: boolean;\r\n alignX: AlignAxis;\r\n alignY: AlignAxis;\r\n gap: number;\r\n debug: boolean;\r\n layoutState: NodeTreeLayoutState;\r\n doneNodes: Set<string>;\r\n registerNode: (id: string, element: HTMLDivElement | null) => void;\r\n nodeFrameClassName?: string;\r\n nodeFrameStyle?: React.CSSProperties;\r\n}): React.ReactNode {\r\n const stackUnder = !flowDown && node.children?.layout === \"stack\";\r\n if (path.has(node.id)) {\r\n return null;\r\n }\r\n\r\n path.add(node.id);\r\n const childrenLayoutIsStack = node.children?.layout === \"stack\" || !flowDown;\r\n const childCount = node.children?.nodes.length ?? 0;\r\n const isLeaf = childCount === 0;\r\n const pathIds = [...path];\r\n const childrenContent =\r\n node.children?.nodes && node.children.nodes.length > 0 ? (\r\n <div\r\n className=\"unt-tree-children\"\r\n style={{\r\n display: \"flex\",\r\n flexShrink: 0,\r\n flexDirection: childrenLayoutIsStack ? \"column\" : \"row\",\r\n alignItems: axisToFlexAlign(childrenLayoutIsStack ? alignX : alignY),\r\n justifyContent: axisToFlexJustify(\r\n childrenLayoutIsStack ? alignY : alignX,\r\n ),\r\n gap,\r\n marginTop: flowDown || stackUnder ? gap : 0,\r\n marginLeft: flowDown\r\n ? node.children?.layout === \"stack\"\r\n ? gap\r\n : 0\r\n : stackUnder\r\n ? gap / 2\r\n : gap,\r\n }}\r\n >\r\n {node.children.nodes.map((child, childIndex) =>\r\n renderTreeNode({\r\n node: child,\r\n index: childIndex,\r\n parentId: node.id,\r\n depth: depth + 1,\r\n path,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n }),\r\n )}\r\n </div>\r\n ) : null;\r\n path.delete(node.id);\r\n\r\n return (\r\n <div\r\n key={`${node.id}-${index}`}\r\n className=\"unt-tree-node-wrap\"\r\n style={{\r\n display: \"flex\",\r\n position: \"relative\",\r\n flexDirection: flowDown || stackUnder ? \"column\" : \"row\",\r\n alignItems: axisToFlexAlign(flowDown ? alignX : alignY),\r\n justifyContent: axisToFlexJustify(flowDown ? alignY : alignX),\r\n }}\r\n >\r\n <NodeFrame\r\n node={node}\r\n className={cn(\"unt-node-enter unt-tree-node-frame\", nodeFrameClassName)}\r\n style={{\r\n justifyContent: axisToFlexJustify(alignX),\r\n animationDuration: `${layoutState.nodeAnimDuration}s`,\r\n animationDelay: `${\r\n layoutState.nodeDelays.get(node.id) ?? depth * 0.08 + index * 0.04\r\n }s`,\r\n ...nodeFrameStyle,\r\n }}\r\n onRef={registerNode}\r\n >\r\n {debug ? (\r\n <div\r\n className={cn(\r\n \"unt-tree-debug-badge\",\r\n `unt-tree-debug-badge--${depth % 6}`,\r\n )}\r\n >\r\n <div>{`DEPTH: ${depth}`}</div>\r\n <div>{`PARENT-ID: ${parentId ?? \"root\"}`}</div>\r\n <div>{`NODE-ID: ${node.id}`}</div>\r\n <div>{`C-LAYOUT: ${node.children?.layout ?? \"N/A\"}`}</div>\r\n </div>\r\n ) : null}\r\n {node.render({\r\n node,\r\n index,\r\n depth,\r\n parentId,\r\n path: pathIds,\r\n isLeaf,\r\n childCount,\r\n isNodeAnimationDone: doneNodes.has(node.id),\r\n })}\r\n </NodeFrame>\r\n\r\n {childrenContent}\r\n </div>\r\n );\r\n}\r\n\r\nexport function TreeRenderer({\r\n nodeTree,\r\n rootLayout,\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n rendererClassName,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n}: TreeRendererProps) {\r\n const rootLayoutRow = rootLayout === \"row\";\r\n return (\r\n <section\r\n className={cn(\"unt-tree-renderer\", rendererClassName)}\r\n style={{\r\n gap,\r\n display: \"flex\",\r\n width: \"100%\",\r\n overflow: \"visible\",\r\n position: \"relative\",\r\n zIndex: 10,\r\n flexDirection: rootLayoutRow ? \"row\" : \"column\",\r\n alignItems: axisToFlexAlign(rootLayoutRow ? alignY : alignX),\r\n justifyContent: axisToFlexJustify(rootLayoutRow ? alignX : alignY),\r\n }}\r\n >\r\n {nodeTree.map((node, index) =>\r\n renderTreeNode({\r\n node,\r\n index,\r\n depth: 0,\r\n path: new Set<string>(),\r\n flowDown,\r\n alignX,\r\n alignY,\r\n gap,\r\n debug,\r\n layoutState,\r\n doneNodes,\r\n registerNode,\r\n nodeFrameClassName,\r\n nodeFrameStyle,\r\n }),\r\n )}\r\n </section>\r\n );\r\n}\r\n","import * as React from \"react\";\nimport type {\n NodeTreeLayoutState,\n TreeNode,\n TreeNodeEdge,\n} from \"../types\";\n\ntype EdgeGeometry = {\n edge: TreeNodeEdge;\n fromX: number;\n fromY: number;\n fromBottom: number;\n fromCenterX: number;\n toX: number;\n toY: number;\n toLeft: number;\n toCenterY: number;\n};\n\ntype UseNodeTreeLayoutParams = {\n nodeTree: TreeNode[];\n direction: \"down\" | \"right\";\n gap: number;\n padding: number;\n animationSpeed: number;\n debug: boolean;\n containerRef: React.RefObject<HTMLDivElement | null>;\n nodeRefs: React.MutableRefObject<Map<string, HTMLDivElement>>;\n};\n\nconst EMPTY_LAYOUT: NodeTreeLayoutState = {\n segments: [],\n nodeDelays: new Map(),\n nodeAnimDuration: 0.42,\n animationTotal: 0,\n svgBounds: null,\n};\n\nfunction collectEdges(nodes: TreeNode[]) {\n const edges: TreeNodeEdge[] = [];\n const visiting = new Set<string>();\n const visit = (node: TreeNode) => {\n if (visiting.has(node.id)) {\n return;\n }\n visiting.add(node.id);\n if (node.children?.nodes && node.children.nodes.length > 0) {\n node.children.nodes.forEach((child, index) => {\n const key = `${node.id}=>${child.id}`;\n edges.push({\n key,\n from: node.id,\n to: child.id,\n index,\n count: node.children?.nodes.length ?? 1,\n });\n visit(child);\n });\n }\n visiting.delete(node.id);\n };\n\n nodes.forEach(visit);\n return edges;\n}\n\nfunction collectDescendants(nodes: TreeNode[]) {\n const map = new Map<string, string[]>();\n const visiting = new Set<string>();\n const visit = (node: TreeNode): string[] => {\n if (visiting.has(node.id)) {\n return [];\n }\n visiting.add(node.id);\n const descendants: string[] = [];\n node.children?.nodes.forEach((child) => {\n descendants.push(child.id);\n descendants.push(...visit(child));\n });\n map.set(node.id, descendants);\n visiting.delete(node.id);\n return descendants;\n };\n nodes.forEach(visit);\n return map;\n}\n\nexport function useNodeTreeLayout({\n nodeTree,\n direction,\n gap,\n padding,\n animationSpeed,\n debug,\n containerRef,\n nodeRefs,\n}: UseNodeTreeLayoutParams) {\n const [layoutState, setLayoutState] =\n React.useState<NodeTreeLayoutState>(EMPTY_LAYOUT);\n const [doneNodes, setDoneNodes] = React.useState<Set<string>>(\n () => new Set(),\n );\n const doneNodesRef = React.useRef<Set<string>>(new Set());\n const edges = React.useMemo(() => collectEdges(nodeTree), [nodeTree]);\n const descendantMap = React.useMemo(\n () => collectDescendants(nodeTree),\n [nodeTree],\n );\n\n const totalAnimationSec = Math.max(0.1, animationSpeed / 1000);\n\n const drawConnections = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n const flowDown = direction === \"down\";\n\n const getRelativeRect = (element: HTMLElement) => {\n let left = 0;\n let top = 0;\n let current: HTMLElement | null = element;\n while (current && current !== container) {\n left += current.offsetLeft;\n top += current.offsetTop;\n current = current.offsetParent as HTMLElement | null;\n }\n return {\n left,\n top,\n right: left + element.offsetWidth,\n bottom: top + element.offsetHeight,\n width: element.offsetWidth,\n height: element.offsetHeight,\n };\n };\n\n const rectMap = new Map<string, ReturnType<typeof getRelativeRect>>();\n nodeRefs.current.forEach((el, id) => {\n rectMap.set(id, getRelativeRect(el));\n });\n\n const nextSegments: NodeTreeLayoutState[\"segments\"] = [];\n const nextNodeDelays = new Map<string, number>();\n const baseSecondsPerPixel = 1 / 900;\n const baseNodeAnimDuration = 0.42;\n const edgeColorIndex = debug ? new Map<string, number>() : null;\n const edgeData = new Map<string, EdgeGeometry>();\n\n edges.forEach((edge) => {\n const fromRect = rectMap.get(edge.from);\n const toRect = rectMap.get(edge.to);\n if (!fromRect || !toRect) {\n return;\n }\n\n const fromX = flowDown ? fromRect.left + fromRect.width / 2 : fromRect.right;\n const fromY = flowDown\n ? fromRect.bottom\n : fromRect.top + fromRect.height / 2;\n const toX = flowDown ? toRect.left + toRect.width / 2 : toRect.left;\n const toY = flowDown ? toRect.top : toRect.top + toRect.height / 2;\n\n edgeData.set(edge.key, {\n edge,\n fromX,\n fromY,\n fromBottom: fromRect.bottom,\n fromCenterX: fromRect.left + fromRect.width / 2,\n toX,\n toY,\n toLeft: toRect.left,\n toCenterY: toRect.top + toRect.height / 2,\n });\n });\n\n const pushSegment = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n depth: number,\n delay: number,\n colorIndex: number,\n order: number,\n ) => {\n const length = Math.hypot(x2 - x1, y2 - y1);\n const duration = Math.max(0.05, length * baseSecondsPerPixel);\n nextSegments.push({\n x1,\n y1,\n x2,\n y2,\n length,\n depth,\n delay,\n duration,\n colorIndex,\n order,\n });\n return duration;\n };\n\n const visit = (node: TreeNode, depth: number, nodeDelay: number) => {\n const existing = nextNodeDelays.get(node.id) ?? 0;\n const resolvedDelay = Math.max(existing, nodeDelay);\n nextNodeDelays.set(node.id, resolvedDelay);\n\n const childEdges =\n node.children?.nodes\n .map((child) => edgeData.get(`${node.id}=>${child.id}`))\n .filter((edge): edge is EdgeGeometry => Boolean(edge)) ?? [];\n const stackLayout = node.children?.layout === \"stack\";\n const descendantIds =\n flowDown && stackLayout ? (descendantMap.get(node.id) ?? []) : [];\n const descendantLefts =\n flowDown && stackLayout\n ? descendantIds\n .map((id) => rectMap.get(id))\n .filter((rect): rect is NonNullable<typeof rect> => Boolean(rect))\n .map((rect) => rect.left)\n : [];\n const descendantMinLeft =\n descendantLefts.length > 0 ? Math.min(...descendantLefts) : undefined;\n const gutterX =\n flowDown && stackLayout\n ? (descendantMinLeft ??\n (childEdges.length > 0\n ? Math.min(...childEdges.map((edge) => edge.toLeft))\n : 0)) -\n gap / 2\n : 0;\n const gutterXRight =\n !flowDown && stackLayout\n ? (childEdges.length > 0\n ? Math.min(...childEdges.map((edge) => edge.toLeft))\n : 0) -\n gap / 2\n : 0;\n\n const orderedChildren =\n node.children?.nodes\n .map((child) => {\n const edge = edgeData.get(`${node.id}=>${child.id}`);\n if (!edge) {\n return null;\n }\n const dx = edge.toX - edge.fromX;\n const dy = edge.toY - edge.fromY;\n const length = Math.hypot(dx, dy);\n return { child, edge, length, toX: edge.toX };\n })\n .filter(\n (entry): entry is NonNullable<typeof entry> => Boolean(entry),\n ) ?? [];\n\n if (debug) {\n orderedChildren.sort((a, b) => {\n if (a.length !== b.length) {\n return a.length - b.length;\n }\n return a.toX - b.toX;\n });\n }\n\n orderedChildren.forEach((entry, index) => {\n const { child, edge } = entry;\n const edgeKey = edge.edge.key;\n let colorIndex = 0;\n if (edgeColorIndex) {\n if (!edgeColorIndex.has(edgeKey)) {\n edgeColorIndex.set(edgeKey, edgeColorIndex.size);\n }\n colorIndex = edgeColorIndex.get(edgeKey) ?? 0;\n }\n const order = orderedChildren.length - 1 - index;\n const edgeDelay = resolvedDelay + baseNodeAnimDuration + index * 0.04;\n let totalDuration = 0;\n if (flowDown && stackLayout) {\n const baseDrop = Math.max(12, gap / 2);\n const targetY = edge.toCenterY;\n const midY =\n edge.fromY + Math.min(baseDrop, (targetY - edge.fromY) * 0.6);\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n edge.fromX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromX,\n midY,\n gutterX,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterX,\n midY,\n gutterX,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterX,\n targetY,\n edge.toLeft,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else if (!flowDown && stackLayout) {\n const targetY = edge.toCenterY;\n const baseDrop = Math.max(12, gap / 2);\n const midY =\n edge.fromBottom +\n Math.min(baseDrop, (targetY - edge.fromBottom) * 0.6);\n totalDuration += pushSegment(\n edge.fromCenterX,\n edge.fromBottom,\n edge.fromCenterX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromCenterX,\n midY,\n gutterXRight,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterXRight,\n midY,\n gutterXRight,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n gutterXRight,\n targetY,\n edge.toLeft,\n targetY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else if (flowDown) {\n const midY = edge.fromY + (edge.toY - edge.fromY) * 0.5;\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n edge.fromX,\n midY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.fromX,\n midY,\n edge.toX,\n midY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n edge.toX,\n midY,\n edge.toX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n } else {\n const midX = edge.fromX + (edge.toX - edge.fromX) * 0.5;\n totalDuration += pushSegment(\n edge.fromX,\n edge.fromY,\n midX,\n edge.fromY,\n depth,\n edgeDelay,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n midX,\n edge.fromY,\n midX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n totalDuration += pushSegment(\n midX,\n edge.toY,\n edge.toX,\n edge.toY,\n depth,\n edgeDelay + totalDuration,\n colorIndex,\n order,\n );\n }\n visit(child, depth + 1, edgeDelay + totalDuration);\n });\n };\n\n nodeTree.forEach((node) => visit(node, 0, 0));\n\n if (nextSegments.length === 0) {\n setLayoutState((prev) => ({\n ...prev,\n segments: [],\n svgBounds: null,\n animationTotal: 0,\n }));\n setDoneNodes(new Set());\n doneNodesRef.current = new Set();\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n nextSegments.forEach((segment) => {\n minX = Math.min(minX, segment.x1, segment.x2);\n minY = Math.min(minY, segment.y1, segment.y2);\n maxX = Math.max(maxX, segment.x1, segment.x2);\n maxY = Math.max(maxY, segment.y1, segment.y2);\n });\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return;\n }\n\n const width = Math.max(1, maxX - minX + padding * 2);\n const height = Math.max(1, maxY - minY + padding * 2);\n const offsetX = minX - padding;\n const offsetY = minY - padding;\n\n const maxLineEnd = Math.max(\n 0,\n ...nextSegments.map((segment) => segment.delay + segment.duration),\n );\n const maxNodeEnd =\n Math.max(0, ...Array.from(nextNodeDelays.values())) + baseNodeAnimDuration;\n const animationMax = Math.max(maxLineEnd, maxNodeEnd);\n const scale = animationMax > 0 ? totalAnimationSec / animationMax : 1;\n const scaledSegments = nextSegments\n .map((segment) => ({\n ...segment,\n delay: segment.delay * scale,\n duration: segment.duration * scale,\n }))\n .sort((a, b) => a.order - b.order);\n const scaledNodeDelays = new Map<string, number>();\n nextNodeDelays.forEach((value, key) => {\n scaledNodeDelays.set(key, value * scale);\n });\n\n setLayoutState({\n segments: scaledSegments,\n nodeDelays: scaledNodeDelays,\n nodeAnimDuration: baseNodeAnimDuration * scale,\n animationTotal: animationMax * scale,\n svgBounds: { width, height, offsetX, offsetY },\n });\n setDoneNodes(new Set());\n doneNodesRef.current = new Set();\n }, [\n animationSpeed,\n containerRef,\n debug,\n descendantMap,\n direction,\n edges,\n gap,\n nodeRefs,\n nodeTree,\n padding,\n totalAnimationSec,\n ]);\n\n React.useLayoutEffect(() => {\n const rafId = requestAnimationFrame(drawConnections);\n return () => cancelAnimationFrame(rafId);\n }, [drawConnections, nodeTree]);\n\n React.useEffect(() => {\n if (layoutState.animationTotal <= 0 || layoutState.nodeDelays.size === 0) {\n return;\n }\n\n const entries = Array.from(layoutState.nodeDelays.entries())\n .map(([id, delay]) => ({\n id,\n end: delay + layoutState.nodeAnimDuration,\n }))\n .sort((a, b) => a.end - b.end);\n\n doneNodesRef.current = new Set();\n setDoneNodes(new Set());\n\n const start = performance.now();\n let rafId = 0;\n let index = 0;\n\n const tick = () => {\n const elapsed = (performance.now() - start) / 1000;\n let updated = false;\n\n while (index < entries.length && elapsed >= entries[index].end) {\n doneNodesRef.current.add(entries[index].id);\n index += 1;\n updated = true;\n }\n\n if (updated) {\n setDoneNodes(new Set(doneNodesRef.current));\n }\n\n if (index < entries.length) {\n rafId = requestAnimationFrame(tick);\n }\n };\n\n rafId = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(rafId);\n }, [\n layoutState.animationTotal,\n layoutState.nodeAnimDuration,\n layoutState.nodeDelays,\n ]);\n\n return { doneNodes, layoutState };\n}\n"],"mappings":"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","names":["React","jsx","jsx","jsxs"]}
|
package/dist/node-tree.css
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
/* src/node-tree.css */
|
|
2
|
-
@keyframes unt-node-enter {
|
|
3
|
-
0% {
|
|
4
|
-
opacity: 0;
|
|
5
|
-
}
|
|
6
|
-
100% {
|
|
7
|
-
opacity: 1;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
2
|
.unt-tree-root-container {
|
|
11
3
|
position: relative;
|
|
12
4
|
width: 100%;
|
|
@@ -65,7 +57,15 @@
|
|
|
65
57
|
inset: 0;
|
|
66
58
|
z-index: 0;
|
|
67
59
|
}
|
|
68
|
-
|
|
60
|
+
@keyframes unt-node-enter {
|
|
61
|
+
0% {
|
|
62
|
+
opacity: 0;
|
|
63
|
+
}
|
|
64
|
+
100% {
|
|
65
|
+
opacity: 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
.unt-node-enter {
|
|
69
69
|
animation-name: unt-node-enter;
|
|
70
70
|
animation-timing-function: ease-out;
|
|
71
71
|
animation-fill-mode: both;
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
opacity: 1;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
.node-line {
|
|
82
|
+
.unt-node-line {
|
|
83
83
|
animation-name: unt-line-draw;
|
|
84
84
|
animation-timing-function: ease-out;
|
|
85
85
|
animation-fill-mode: both;
|
package/dist/node-tree.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/node-tree.css"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../src/node-tree.css"],"sourcesContent":[".unt-tree-root-container {\r\n position: relative;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.unt-tree-canvas {\r\n position: relative;\r\n}\r\n\r\n.unt-tree-node-hit {\r\n cursor: auto;\r\n}\r\n\r\n.unt-tree-node-frame {\r\n position: relative;\r\n display: flex;\r\n border: 1px solid rgba(255, 255, 255, 0.2);\r\n padding: 1rem;\r\n}\r\n\r\n.unt-tree-debug-badge {\r\n position: absolute;\r\n top: 0.5rem;\r\n left: 0.5rem;\r\n z-index: 10;\r\n padding: 0.25rem 0.5rem;\r\n font-size: 0.75rem;\r\n line-height: 1rem;\r\n}\r\n\r\n.unt-tree-debug-badge--0 {\r\n background: #a7f3d0;\r\n color: #042f2e;\r\n}\r\n\r\n.unt-tree-debug-badge--1 {\r\n background: #bae6fd;\r\n color: #082f49;\r\n}\r\n\r\n.unt-tree-debug-badge--2 {\r\n background: #fde68a;\r\n color: #451a03;\r\n}\r\n\r\n.unt-tree-debug-badge--3 {\r\n background: #fecdd3;\r\n color: #4c0519;\r\n}\r\n\r\n.unt-tree-debug-badge--4 {\r\n background: #d9f99d;\r\n color: #1a2e05;\r\n}\r\n\r\n.unt-tree-debug-badge--5 {\r\n background: #ddd6fe;\r\n color: #2e1065;\r\n}\r\n\r\n.unt-tree-connections {\r\n pointer-events: none;\r\n position: absolute;\r\n inset: 0;\r\n z-index: 0;\r\n}\r\n\r\n@keyframes unt-node-enter {\r\n 0% {\r\n opacity: 0;\r\n }\r\n 100% {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.unt-node-enter {\r\n animation-name: unt-node-enter;\r\n animation-timing-function: ease-out;\r\n animation-fill-mode: both;\r\n}\r\n\r\n@keyframes unt-line-draw {\r\n 0% {\r\n opacity: 0.2;\r\n }\r\n 100% {\r\n stroke-dashoffset: 0;\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.unt-node-line {\r\n animation-name: unt-line-draw;\r\n animation-timing-function: ease-out;\r\n animation-fill-mode: both;\r\n}\r\n"],"mappings":";AAAA,CAAC;AACC,YAAU;AACV,SAAO;AACP,UAAQ;AACR,cAAY;AACZ,YAAU;AACZ;AAEA,CAAC;AACC,YAAU;AACZ;AAEA,CAAC;AACC,UAAQ;AACV;AAEA,CAAC;AACC,YAAU;AACV,WAAS;AACT,UAAQ,IAAI,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AACtC,WAAS;AACX;AAEA,CAAC;AACC,YAAU;AACV,OAAK;AACL,QAAM;AACN,WAAS;AACT,WAAS,QAAQ;AACjB,aAAW;AACX,eAAa;AACf;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACT;AAEA,CAAC;AACC,kBAAgB;AAChB,YAAU;AACV,SAAO;AACP,WAAS;AACX;AAEA,WAAW;AACT;AACE,aAAS;AACX;AACA;AACE,aAAS;AACX;AACF;AAEA,CATW;AAUT,kBAAgB;AAChB,6BAA2B;AAC3B,uBAAqB;AACvB;AAEA,WAAW;AACT;AACE,aAAS;AACX;AACA;AACE,uBAAmB;AACnB,aAAS;AACX;AACF;AAEA,CAAC;AACC,kBAAgB;AAChB,6BAA2B;AAC3B,uBAAqB;AACvB;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@ii_elif_ii/ui-node-tree",
|
|
3
|
-
"version": "1.0.
|
|
2
|
+
"name": "@ii_elif_ii/ui-node-tree",
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Animated React node tree component with configurable layouts and connection lines.",
|
|
5
5
|
"author": "II-ELIF-II",
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/II-ELIF-II/ui-node-tree.git"
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"typecheck": "tsc --noEmit",
|
|
41
41
|
"prepublishOnly": "npm run build"
|
|
42
42
|
},
|
|
43
|
-
"publishConfig": {
|
|
44
|
-
"access": "public"
|
|
45
|
-
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"react": "^18.0.0 || ^19.0.0",
|
|
48
48
|
"react-dom": "^18.0.0 || ^19.0.0"
|