@particle-academy/react-fancy 2.8.1 → 2.9.0
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/dist/index.cjs +56 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -2
- package/dist/index.d.ts +27 -2
- package/dist/index.js +56 -25
- package/dist/index.js.map +1 -1
- package/docs/Canvas.md +5 -2
- package/docs/TreeNav.md +27 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -11771,7 +11771,7 @@ function useCanvas() {
|
|
|
11771
11771
|
return ctx;
|
|
11772
11772
|
}
|
|
11773
11773
|
function CanvasNode({ children, id, x, y, draggable, onPositionChange, className, style }) {
|
|
11774
|
-
const { registerNode, unregisterNode, viewport } = useCanvas();
|
|
11774
|
+
const { registerNode, unregisterNode, viewport, gridSize, snapToGrid } = useCanvas();
|
|
11775
11775
|
const nodeRef = react.useRef(null);
|
|
11776
11776
|
const isDragging = react.useRef(false);
|
|
11777
11777
|
const dragStart = react.useRef({ mouseX: 0, mouseY: 0, nodeX: 0, nodeY: 0 });
|
|
@@ -11804,9 +11804,15 @@ function CanvasNode({ children, id, x, y, draggable, onPositionChange, className
|
|
|
11804
11804
|
if (!isDragging.current) return;
|
|
11805
11805
|
const dx = (e.clientX - dragStart.current.mouseX) / viewport.zoom;
|
|
11806
11806
|
const dy = (e.clientY - dragStart.current.mouseY) / viewport.zoom;
|
|
11807
|
-
|
|
11807
|
+
let nx = dragStart.current.nodeX + dx;
|
|
11808
|
+
let ny = dragStart.current.nodeY + dy;
|
|
11809
|
+
if (snapToGrid && gridSize > 0) {
|
|
11810
|
+
nx = Math.round(nx / gridSize) * gridSize;
|
|
11811
|
+
ny = Math.round(ny / gridSize) * gridSize;
|
|
11812
|
+
}
|
|
11813
|
+
onPositionChange?.(nx, ny);
|
|
11808
11814
|
},
|
|
11809
|
-
[viewport.zoom, onPositionChange]
|
|
11815
|
+
[viewport.zoom, onPositionChange, snapToGrid, gridSize]
|
|
11810
11816
|
);
|
|
11811
11817
|
const handlePointerUp = react.useCallback(() => {
|
|
11812
11818
|
isDragging.current = false;
|
|
@@ -12054,6 +12060,10 @@ function CanvasRoot({
|
|
|
12054
12060
|
pannable = true,
|
|
12055
12061
|
zoomable = true,
|
|
12056
12062
|
showGrid = false,
|
|
12063
|
+
gridStyle = "dots",
|
|
12064
|
+
gridSize = 20,
|
|
12065
|
+
gridColor = "rgb(161 161 170 / 0.3)",
|
|
12066
|
+
snapToGrid = false,
|
|
12057
12067
|
fitOnMount = false,
|
|
12058
12068
|
className,
|
|
12059
12069
|
style
|
|
@@ -12071,8 +12081,8 @@ function CanvasRoot({
|
|
|
12071
12081
|
containerRef
|
|
12072
12082
|
});
|
|
12073
12083
|
const ctx = react.useMemo(
|
|
12074
|
-
() => ({ viewport, setViewport, registerNode, unregisterNode, nodeRects, registryVersion, containerRef }),
|
|
12075
|
-
[viewport, setViewport, registerNode, unregisterNode, nodeRects, registryVersion]
|
|
12084
|
+
() => ({ viewport, setViewport, registerNode, unregisterNode, nodeRects, registryVersion, containerRef, gridSize, snapToGrid }),
|
|
12085
|
+
[viewport, setViewport, registerNode, unregisterNode, nodeRects, registryVersion, gridSize, snapToGrid]
|
|
12076
12086
|
);
|
|
12077
12087
|
const hasFitted = react.useRef(false);
|
|
12078
12088
|
react.useEffect(() => {
|
|
@@ -12128,9 +12138,13 @@ function CanvasRoot({
|
|
|
12128
12138
|
{
|
|
12129
12139
|
"data-canvas-bg": "",
|
|
12130
12140
|
className: "absolute inset-0",
|
|
12131
|
-
style: showGrid ? {
|
|
12132
|
-
backgroundImage: `
|
|
12133
|
-
backgroundSize: `${
|
|
12141
|
+
style: showGrid && gridStyle !== "none" ? gridStyle === "lines" ? {
|
|
12142
|
+
backgroundImage: `linear-gradient(to right, ${gridColor} 1px, transparent 1px), linear-gradient(to bottom, ${gridColor} 1px, transparent 1px)`,
|
|
12143
|
+
backgroundSize: `${gridSize * viewport.zoom}px ${gridSize * viewport.zoom}px`,
|
|
12144
|
+
backgroundPosition: `${viewport.panX}px ${viewport.panY}px`
|
|
12145
|
+
} : {
|
|
12146
|
+
backgroundImage: `radial-gradient(circle, ${gridColor} 1px, transparent 1px)`,
|
|
12147
|
+
backgroundSize: `${gridSize * viewport.zoom}px ${gridSize * viewport.zoom}px`,
|
|
12134
12148
|
backgroundPosition: `${viewport.panX}px ${viewport.panY}px`
|
|
12135
12149
|
} : void 0
|
|
12136
12150
|
}
|
|
@@ -12847,6 +12861,8 @@ function TreeNode({ node, depth }) {
|
|
|
12847
12861
|
dragState,
|
|
12848
12862
|
setDragState,
|
|
12849
12863
|
onNodeMove,
|
|
12864
|
+
acceptExternalDrops,
|
|
12865
|
+
onExternalDrop,
|
|
12850
12866
|
nodes,
|
|
12851
12867
|
expandNode
|
|
12852
12868
|
} = useTreeNav();
|
|
@@ -12889,14 +12905,18 @@ function TreeNode({ node, depth }) {
|
|
|
12889
12905
|
clearAutoExpand();
|
|
12890
12906
|
setDragState({ draggedNodeId: null, dropTargetId: null, dropPosition: null });
|
|
12891
12907
|
}, [clearAutoExpand, setDragState]);
|
|
12908
|
+
const isExternalDrag = !dragState.draggedNodeId;
|
|
12892
12909
|
const handleDragOver = react.useCallback((e) => {
|
|
12893
|
-
if (
|
|
12894
|
-
|
|
12895
|
-
|
|
12896
|
-
|
|
12910
|
+
if (isExternalDrag) {
|
|
12911
|
+
if (!acceptExternalDrops) return;
|
|
12912
|
+
} else {
|
|
12913
|
+
const sourceId = dragState.draggedNodeId;
|
|
12914
|
+
if (sourceId === node.id) return;
|
|
12915
|
+
if (isDescendantOf(nodes, sourceId, node.id)) return;
|
|
12916
|
+
}
|
|
12897
12917
|
e.preventDefault();
|
|
12898
12918
|
e.stopPropagation();
|
|
12899
|
-
e.dataTransfer.dropEffect = "move";
|
|
12919
|
+
e.dataTransfer.dropEffect = isExternalDrag ? "copy" : "move";
|
|
12900
12920
|
const position = computeDropPosition(e, !!isFolder);
|
|
12901
12921
|
if (isFolder && !isExpanded && position === "inside") {
|
|
12902
12922
|
if (!autoExpandTimer.current) {
|
|
@@ -12909,9 +12929,9 @@ function TreeNode({ node, depth }) {
|
|
|
12909
12929
|
clearAutoExpand();
|
|
12910
12930
|
}
|
|
12911
12931
|
if (dragState.dropTargetId !== node.id || dragState.dropPosition !== position) {
|
|
12912
|
-
setDragState({ draggedNodeId:
|
|
12932
|
+
setDragState({ draggedNodeId: dragState.draggedNodeId, dropTargetId: node.id, dropPosition: position });
|
|
12913
12933
|
}
|
|
12914
|
-
}, [dragState, node.id, isFolder, isExpanded, nodes, setDragState, expandNode, clearAutoExpand]);
|
|
12934
|
+
}, [dragState, isExternalDrag, acceptExternalDrops, node.id, isFolder, isExpanded, nodes, setDragState, expandNode, clearAutoExpand]);
|
|
12915
12935
|
const handleDragLeave = react.useCallback((e) => {
|
|
12916
12936
|
if (!e.currentTarget.contains(e.relatedTarget)) {
|
|
12917
12937
|
clearAutoExpand();
|
|
@@ -12925,21 +12945,25 @@ function TreeNode({ node, depth }) {
|
|
|
12925
12945
|
e.stopPropagation();
|
|
12926
12946
|
clearAutoExpand();
|
|
12927
12947
|
const sourceId = dragState.draggedNodeId;
|
|
12928
|
-
const position = dragState.dropPosition;
|
|
12929
|
-
if (
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
|
|
12948
|
+
const position = dragState.dropPosition ?? computeDropPosition(e, !!isFolder);
|
|
12949
|
+
if (sourceId) {
|
|
12950
|
+
if (sourceId === node.id) return;
|
|
12951
|
+
if (isDescendantOf(nodes, sourceId, node.id)) return;
|
|
12952
|
+
onNodeMove?.(sourceId, node.id, position);
|
|
12953
|
+
} else if (acceptExternalDrops) {
|
|
12954
|
+
onExternalDrop?.(e, node, position);
|
|
12955
|
+
}
|
|
12933
12956
|
setDragState({ draggedNodeId: null, dropTargetId: null, dropPosition: null });
|
|
12934
|
-
}, [dragState, node
|
|
12957
|
+
}, [dragState, node, isFolder, nodes, onNodeMove, acceptExternalDrops, onExternalDrop, setDragState, clearAutoExpand]);
|
|
12935
12958
|
const canDrag = draggable && !node.disabled;
|
|
12959
|
+
const dropEnabled = draggable || acceptExternalDrops;
|
|
12936
12960
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12937
12961
|
"div",
|
|
12938
12962
|
{
|
|
12939
12963
|
"data-react-fancy-tree-node": "",
|
|
12940
|
-
onDragOver:
|
|
12941
|
-
onDragLeave:
|
|
12942
|
-
onDrop:
|
|
12964
|
+
onDragOver: dropEnabled ? handleDragOver : void 0,
|
|
12965
|
+
onDragLeave: dropEnabled ? handleDragLeave : void 0,
|
|
12966
|
+
onDrop: dropEnabled ? handleDrop : void 0,
|
|
12943
12967
|
children: [
|
|
12944
12968
|
isDropTarget && dropPosition === "before" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12945
12969
|
"div",
|
|
@@ -13012,6 +13036,8 @@ function TreeNavRoot({
|
|
|
13012
13036
|
onNodeContextMenu,
|
|
13013
13037
|
draggable = false,
|
|
13014
13038
|
onNodeMove,
|
|
13039
|
+
acceptExternalDrops = false,
|
|
13040
|
+
onExternalDrop,
|
|
13015
13041
|
expandedIds: controlledExpanded,
|
|
13016
13042
|
defaultExpandedIds,
|
|
13017
13043
|
onExpandedChange,
|
|
@@ -13065,6 +13091,8 @@ function TreeNavRoot({
|
|
|
13065
13091
|
dragState,
|
|
13066
13092
|
setDragState,
|
|
13067
13093
|
onNodeMove,
|
|
13094
|
+
acceptExternalDrops,
|
|
13095
|
+
onExternalDrop,
|
|
13068
13096
|
nodes,
|
|
13069
13097
|
expandNode
|
|
13070
13098
|
}),
|
|
@@ -13079,16 +13107,19 @@ function TreeNavRoot({
|
|
|
13079
13107
|
draggable,
|
|
13080
13108
|
dragState,
|
|
13081
13109
|
onNodeMove,
|
|
13110
|
+
acceptExternalDrops,
|
|
13111
|
+
onExternalDrop,
|
|
13082
13112
|
nodes,
|
|
13083
13113
|
expandNode
|
|
13084
13114
|
]
|
|
13085
13115
|
);
|
|
13116
|
+
const dropEnabled = draggable || acceptExternalDrops;
|
|
13086
13117
|
return /* @__PURE__ */ jsxRuntime.jsx(TreeNavContext.Provider, { value: ctx, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13087
13118
|
"nav",
|
|
13088
13119
|
{
|
|
13089
13120
|
"data-react-fancy-tree-nav": "",
|
|
13090
13121
|
className: cn("flex flex-col gap-0.5 py-1 text-sm", className),
|
|
13091
|
-
onDragEnd:
|
|
13122
|
+
onDragEnd: dropEnabled ? handleDragEnd : void 0,
|
|
13092
13123
|
children: nodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx(TreeNode, { node, depth: 0 }, node.id))
|
|
13093
13124
|
}
|
|
13094
13125
|
) });
|