@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/dist/index.cjs +217 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +217 -26
- package/dist/index.js.map +1 -1
- package/docs/TreeNav.md +78 -0
- package/package.json +1 -1
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