@particle-academy/react-fancy 1.9.0 → 2.0.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/docs/TreeNav.md CHANGED
@@ -48,6 +48,9 @@ const files: TreeNodeData[] = [
48
48
  | nodes | `TreeNodeData[]` | - | Tree data (required) |
49
49
  | selectedId | `string` | - | Currently selected node ID |
50
50
  | onSelect | `(id: string, node: TreeNodeData) => void` | - | Selection callback |
51
+ | onNodeContextMenu | `(e: React.MouseEvent, node: TreeNodeData) => void` | - | Right-click callback per node |
52
+ | draggable | `boolean` | `false` | Enable drag-and-drop reordering |
53
+ | onNodeMove | `(sourceId: string, targetId: string, position: DropPosition) => void` | - | Callback when a node is moved via drag-and-drop |
51
54
  | expandedIds | `string[]` | - | Controlled expanded node IDs |
52
55
  | defaultExpandedIds | `string[]` | - | Initial expanded nodes (uncontrolled) |
53
56
  | onExpandedChange | `(ids: string[]) => void` | - | Callback when expanded state changes |
@@ -141,6 +144,81 @@ Override with the `icon` field on any node:
141
144
  { id: "special", label: "config", icon: <GearIcon /> }
142
145
  ```
143
146
 
147
+ ## Drag and Drop
148
+
149
+ Enable drag-and-drop reordering with the `draggable` prop. The tree itself is never mutated — your `onNodeMove` callback receives the source, target, and position, and you update state accordingly.
150
+
151
+ ```tsx
152
+ import { TreeNav } from "@particle-academy/react-fancy";
153
+ import type { TreeNodeData, DropPosition } from "@particle-academy/react-fancy";
154
+
155
+ const [files, setFiles] = useState<TreeNodeData[]>(initialFiles);
156
+
157
+ function handleNodeMove(sourceId: string, targetId: string, position: DropPosition) {
158
+ // position is "before", "after", or "inside" (folders only)
159
+ setFiles((prev) => moveNode(prev, sourceId, targetId, position));
160
+ }
161
+
162
+ <TreeNav
163
+ nodes={files}
164
+ draggable
165
+ onNodeMove={handleNodeMove}
166
+ />
167
+ ```
168
+
169
+ **Drop positions:**
170
+ - `"before"` — insert above the target node (thin blue line indicator)
171
+ - `"after"` — insert below the target node (thin blue line indicator)
172
+ - `"inside"` — drop into a folder (blue highlight on the folder)
173
+
174
+ **Built-in safety:**
175
+ - Cannot drop a node onto itself
176
+ - Cannot drop a node into its own descendants
177
+ - Folders auto-expand after 500ms when dragging over them
178
+ - Disabled nodes cannot be dragged
179
+
180
+ ## Context Menu
181
+
182
+ Use `onNodeContextMenu` with the `ContextMenu` component to add right-click menus per node:
183
+
184
+ ```tsx
185
+ import { TreeNav, ContextMenu } from "@particle-academy/react-fancy";
186
+
187
+ const [ctxNode, setCtxNode] = useState<TreeNodeData | null>(null);
188
+
189
+ <ContextMenu>
190
+ <ContextMenu.Trigger>
191
+ <TreeNav
192
+ nodes={files}
193
+ selectedId={selectedFile}
194
+ onSelect={handleSelect}
195
+ onNodeContextMenu={(e, node) => setCtxNode(node)}
196
+ />
197
+ </ContextMenu.Trigger>
198
+ <ContextMenu.Content>
199
+ {ctxNode?.type === "folder" ? (
200
+ <>
201
+ <ContextMenu.Item>New File</ContextMenu.Item>
202
+ <ContextMenu.Item>New Folder</ContextMenu.Item>
203
+ </>
204
+ ) : (
205
+ <>
206
+ <ContextMenu.Item onClick={() => openFile(ctxNode)}>
207
+ Open File
208
+ </ContextMenu.Item>
209
+ <ContextMenu.Item onClick={() => copyName(ctxNode)}>
210
+ Copy File Name
211
+ </ContextMenu.Item>
212
+ <ContextMenu.Separator />
213
+ <ContextMenu.Item danger>Delete</ContextMenu.Item>
214
+ </>
215
+ )}
216
+ </ContextMenu.Content>
217
+ </ContextMenu>
218
+ ```
219
+
220
+ The `onNodeContextMenu` callback fires with the mouse event and the node data. Wrap TreeNav in `ContextMenu.Trigger` to let the ContextMenu handle positioning and open/close — the callback just tracks which node was right-clicked so you can render different menu items for files vs folders.
221
+
144
222
  ## IDE Layout Example
145
223
 
146
224
  Pair with `@particle-academy/fancy-code` for a full IDE:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "1.9.0",
3
+ "version": "2.0.0",
4
4
  "description": "React UI component library — React port of the fancy-flux Blade component library",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",