|
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