|
1 | 1 | <script lang="ts"> |
2 | 2 | import { FileNode, FolderNode, type FileTree, type FileTreeNode } from "$lib/tree.svelte"; |
3 | | - import { formatSize } from "$lib/utils.js"; |
| 3 | + import { composeEventHandlers, formatSize } from "$lib/utils.js"; |
4 | 4 | import { |
5 | 5 | Tree, |
6 | 6 | type CircularReferenceErrorArgs, |
|
11 | 11 | type TreeProps, |
12 | 12 | } from "svelte-file-tree"; |
13 | 13 | import { toast } from "svelte-sonner"; |
| 14 | + import type { EventHandler } from "svelte/elements"; |
14 | 15 | import { SvelteSet } from "svelte/reactivity"; |
15 | 16 | import ContextMenu from "./ContextMenu.svelte"; |
16 | 17 | import NameConflictDialog from "./NameConflictDialog.svelte"; |
|
50 | 51 | clipboardIds = new SvelteSet(defaultClipboardIds), |
51 | 52 | pasteOperation = $bindable(), |
52 | 53 | ref = $bindable(null), |
| 54 | + onfocusout, |
| 55 | + ondragover, |
| 56 | + ondrop, |
53 | 57 | ...rest |
54 | 58 | }: Props = $props(); |
55 | 59 |
|
|
210 | 214 | }, |
211 | 215 | }); |
212 | 216 | } |
| 217 | +
|
| 218 | + function handleExpand(target: TreeItemState<FileTreeNode>): void { |
| 219 | + expandedIds.add(target.node.id); |
| 220 | + } |
| 221 | +
|
| 222 | + function handleCollapse(target: TreeItemState<FileTreeNode>): void { |
| 223 | + expandedIds.delete(target.node.id); |
| 224 | + } |
| 225 | +
|
| 226 | + function handleFocusOut(): void { |
| 227 | + focusedItem = undefined; |
| 228 | + } |
| 229 | +
|
| 230 | + function handleFocusInItem(target: TreeItemState<FileTreeNode>): void { |
| 231 | + focusedItem = target; |
| 232 | + } |
| 233 | +
|
| 234 | + const handleDragOver: EventHandler<DragEvent, HTMLDivElement> = (event) => { |
| 235 | + event.preventDefault(); |
| 236 | + }; |
| 237 | +
|
| 238 | + const handleDrop: EventHandler<DragEvent, HTMLDivElement> = (event) => { |
| 239 | + if (event.defaultPrevented) { |
| 240 | + return; |
| 241 | + } |
| 242 | +
|
| 243 | + if (event.dataTransfer === null) { |
| 244 | + return; |
| 245 | + } |
| 246 | +
|
| 247 | + handleUploadFiles(tree, event.dataTransfer.files); |
| 248 | + event.preventDefault(); |
| 249 | + }; |
213 | 250 | </script> |
214 | 251 |
|
215 | 252 | <div class="root flex h-full flex-col"> |
|
240 | 277 | bind:this={treeComponent} |
241 | 278 | bind:pasteOperation |
242 | 279 | bind:ref |
243 | | - class="px-(--tree-inline-padding) py-2" |
| 280 | + class="h-full px-(--tree-inline-padding) py-2" |
244 | 281 | copyNode={(node) => node.copy()} |
245 | 282 | onResolveNameConflict={handleResolveNameConflict} |
246 | 283 | onCircularReferenceError={handleCircularReferenceError} |
247 | | - onfocusout={() => { |
248 | | - focusedItem = undefined; |
249 | | - }} |
| 284 | + onfocusout={composeEventHandlers(onfocusout, handleFocusOut)} |
| 285 | + ondragover={composeEventHandlers(ondragover, handleDragOver)} |
| 286 | + ondrop={composeEventHandlers(ondrop, handleDrop)} |
250 | 287 | > |
251 | 288 | {#snippet item({ item })} |
252 | 289 | <TreeItem |
253 | 290 | {item} |
254 | 291 | {contextMenu} |
255 | | - onExpand={() => expandedIds.add(item.node.id)} |
256 | | - onCollapse={() => expandedIds.delete(item.node.id)} |
257 | | - onRename={() => handleRename(item)} |
258 | | - onfocusin={() => { |
259 | | - focusedItem = item; |
260 | | - }} |
| 292 | + onExpand={handleExpand} |
| 293 | + onCollapse={handleCollapse} |
| 294 | + onRename={handleRename} |
| 295 | + onUploadFiles={handleUploadFiles} |
| 296 | + onfocusin={() => handleFocusInItem(item)} |
261 | 297 | /> |
262 | 298 | {/snippet} |
263 | 299 | </Tree> |
|
0 commit comments