|
1 |
| -<script lang="ts" generics="TData extends FileTreeNodeData = FileTreeNodeData"> |
2 |
| - import type { FileTreeNodeData } from "$lib/tree.svelte.js"; |
| 1 | +<script lang="ts" generics="TNode extends FileNode | FolderNode<TNode> = FileTreeNode"> |
| 2 | + import { FileNode, FolderNode, type FileTreeNode } from "$lib/tree.svelte.js"; |
| 3 | + import { DEV } from "esm-env"; |
3 | 4 | import { SvelteSet } from "svelte/reactivity";
|
4 | 5 | import TreeItemProvider from "./TreeItemProvider.svelte";
|
5 | 6 | import { createTreeState } from "./state.svelte.js";
|
|
16 | 17 | defaultClipboardIds,
|
17 | 18 | clipboardIds = new SvelteSet(defaultClipboardIds),
|
18 | 19 | pasteOperation = $bindable(),
|
19 |
| - isItemEditable = false, |
| 20 | + isItemEditable = true, |
20 | 21 | isItemDisabled = false,
|
21 | 22 | id = defaultId,
|
22 | 23 | ref = $bindable(null),
|
23 |
| - generateCopyId = () => crypto.randomUUID(), |
| 24 | + copyNode = function copyNode(node): TNode { |
| 25 | + if (DEV && node.constructor !== FileNode && node.constructor !== FolderNode) { |
| 26 | + throw new Error( |
| 27 | + "Cannot copy an object that extends from `FileNode` or `FolderNode`. Pass a `copyNode` prop to specify how the object should be copied.", |
| 28 | + ); |
| 29 | + } |
| 30 | +
|
| 31 | + switch (node.type) { |
| 32 | + case "file": { |
| 33 | + return new FileNode({ |
| 34 | + id: crypto.randomUUID(), |
| 35 | + name: node.name, |
| 36 | + }) as TNode; |
| 37 | + } |
| 38 | + case "folder": { |
| 39 | + return new FolderNode({ |
| 40 | + id: crypto.randomUUID(), |
| 41 | + name: node.name, |
| 42 | + children: node.children.map(copyNode), |
| 43 | + }) as TNode; |
| 44 | + } |
| 45 | + } |
| 46 | + }, |
24 | 47 | onRenameItem = ({ target, name }) => {
|
25 |
| - target.data.name = name; |
| 48 | + target.name = name; |
26 | 49 | return true;
|
27 | 50 | },
|
28 | 51 | onMoveItems = ({ updates }) => {
|
|
45 | 68 | onAlreadyExistsError,
|
46 | 69 | onCircularReferenceError,
|
47 | 70 | ...rest
|
48 |
| - }: TreeProps<TData> = $props(); |
| 71 | + }: TreeProps<TNode> = $props(); |
49 | 72 |
|
50 | 73 | const treeState = createTreeState({
|
51 | 74 | tree: () => tree,
|
|
71 | 94 | return isItemDisabled;
|
72 | 95 | },
|
73 | 96 | id: () => id,
|
74 |
| - generateCopyId: () => generateCopyId(), |
| 97 | + copyNode: (node) => copyNode(node), |
75 | 98 | onRenameItem: (args) => onRenameItem(args),
|
76 | 99 | onMoveItems: (args) => onMoveItems(args),
|
77 | 100 | onCopyPasteItems: (args) => onCopyPasteItems(args),
|
|
80 | 103 | onAlreadyExistsError: (args) => onAlreadyExistsError?.(args),
|
81 | 104 | onCircularReferenceError: (args) => onCircularReferenceError?.(args),
|
82 | 105 | });
|
| 106 | +
|
| 107 | + export const { rename, copy, paste, remove } = treeState; |
83 | 108 | </script>
|
84 | 109 |
|
85 | 110 | <div {...rest} bind:this={ref} {id} role="tree" aria-multiselectable="true">
|
86 | 111 | {#each treeState.items() as i (i.node.id)}
|
87 | 112 | <TreeItemProvider {treeState} item={i}>
|
88 | 113 | {#if i.visible()}
|
89 |
| - {@render item({ |
90 |
| - item: i, |
91 |
| - select: () => selectedIds.add(i.node.id), |
92 |
| - deselect: () => selectedIds.delete(i.node.id), |
93 |
| - expand: () => expandedIds.add(i.node.id), |
94 |
| - collapse: () => expandedIds.delete(i.node.id), |
95 |
| - rename: (name) => treeState.rename(i, name), |
96 |
| - copy: (operation) => treeState.copy(i, operation), |
97 |
| - paste: (position) => treeState.paste(i, position), |
98 |
| - remove: () => treeState.remove(i), |
99 |
| - })} |
| 114 | + {@render item({ item: i })} |
100 | 115 | {/if}
|
101 | 116 | </TreeItemProvider>
|
102 | 117 | {/each}
|
|
0 commit comments