|
1 |
| -<script |
2 |
| - lang="ts" |
3 |
| - generics="TFile extends FileNode = FileNode, TFolder extends FolderNode<TFile | TFolder> = DefaultTFolder<TFile>, TTree extends FileTree<TFile | TFolder> = FileTree<TFile | TFolder>" |
4 |
| -> |
| 1 | +<script lang="ts" module> |
5 | 2 | import type { DragLocation } from "@atlaskit/pragmatic-drag-and-drop/dist/types/internal-types.js";
|
6 | 3 | import {
|
7 | 4 | dropTargetForElements,
|
8 | 5 | type ElementDropTargetGetFeedbackArgs,
|
| 6 | + type ElementEventBasePayload, |
| 7 | + type ElementGetFeedbackArgs, |
9 | 8 | } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
10 | 9 | import {
|
11 | 10 | dropTargetForExternal,
|
12 | 11 | type ExternalDropTargetGetFeedbackArgs,
|
13 | 12 | } from "@atlaskit/pragmatic-drag-and-drop/external/adapter";
|
14 | 13 | import { DEV } from "esm-env";
|
| 14 | + import { getContext, hasContext, setContext } from "svelte"; |
15 | 15 | import { SvelteSet } from "svelte/reactivity";
|
16 | 16 | import { falsePredicate, isControlOrMeta, noop, truePredicate } from "$lib/internal/helpers.js";
|
17 | 17 | import {
|
|
21 | 21 | TreeItemState,
|
22 | 22 | type DefaultTFolder,
|
23 | 23 | } from "$lib/tree.svelte.js";
|
24 |
| - import { setTreeContext } from "./context.js"; |
25 | 24 | import { DragData } from "./data.js";
|
26 | 25 | import type {
|
27 | 26 | TreeCopyToClipboardMethodOptions,
|
28 | 27 | TreeProps,
|
29 | 28 | TreeRemoveMethodOptions,
|
30 | 29 | } from "./types.js";
|
31 | 30 |
|
| 31 | + export type TreeItemEvent<TEvent extends Event = Event> = TEvent & { |
| 32 | + currentTarget: HTMLDivElement; |
| 33 | + }; |
| 34 | +
|
| 35 | + export type TreeContext< |
| 36 | + TFile extends FileNode = FileNode, |
| 37 | + TFolder extends FolderNode<TFile | TFolder> = DefaultTFolder<TFile>, |
| 38 | + TTree extends FileTree<TFile | TFolder> = FileTree<TFile | TFolder>, |
| 39 | + > = { |
| 40 | + root: () => TTree; |
| 41 | + tabbableId: () => string; |
| 42 | + getItemElementId: (itemId: string) => string; |
| 43 | + onFocusIn: (item: TreeItemState<TFile, TFolder>, event: TreeItemEvent<FocusEvent>) => void; |
| 44 | + onKeyDown: (item: TreeItemState<TFile, TFolder>, event: TreeItemEvent<KeyboardEvent>) => void; |
| 45 | + onClick: (item: TreeItemState<TFile, TFolder>, event: TreeItemEvent<MouseEvent>) => void; |
| 46 | + getDropDestination: (item: TreeItemState<TFile, TFolder>) => TFolder | TTree; |
| 47 | + canDrag: (item: TreeItemState<TFile, TFolder>, args: ElementGetFeedbackArgs) => boolean; |
| 48 | + canDropElement: ( |
| 49 | + item: TreeItemState<TFile, TFolder>, |
| 50 | + args: ElementDropTargetGetFeedbackArgs, |
| 51 | + ) => boolean; |
| 52 | + canDropExternal: ( |
| 53 | + item: TreeItemState<TFile, TFolder>, |
| 54 | + args: ExternalDropTargetGetFeedbackArgs, |
| 55 | + ) => boolean; |
| 56 | + onDragStart: (item: TreeItemState<TFile, TFolder>, args: ElementEventBasePayload) => void; |
| 57 | + onDestroyItem: (item: TreeItemState<TFile, TFolder>) => void; |
| 58 | + }; |
| 59 | +
|
| 60 | + const CONTEXT_KEY = Symbol("TreeContext"); |
| 61 | +
|
| 62 | + export function getTreeContext< |
| 63 | + TFile extends FileNode = FileNode, |
| 64 | + TFolder extends FolderNode<TFile | TFolder> = DefaultTFolder<TFile>, |
| 65 | + TTree extends FileTree<TFile | TFolder> = FileTree<TFile | TFolder>, |
| 66 | + >(): TreeContext<TFile, TFolder, TTree> { |
| 67 | + if (DEV && !hasContext(CONTEXT_KEY)) { |
| 68 | + throw new Error("No parent <Tree> found"); |
| 69 | + } |
| 70 | + return getContext(CONTEXT_KEY); |
| 71 | + } |
| 72 | +</script> |
| 73 | + |
| 74 | +<script |
| 75 | + lang="ts" |
| 76 | + generics="TFile extends FileNode = FileNode, TFolder extends FolderNode<TFile | TFolder> = DefaultTFolder<TFile>, TTree extends FileTree<TFile | TFolder> = FileTree<TFile | TFolder>" |
| 77 | +> |
32 | 78 | let {
|
33 | 79 | children,
|
34 | 80 | root,
|
|
64 | 110 | }
|
65 | 111 | }
|
66 | 112 | },
|
67 |
| - onClipboardChange = noop, |
68 |
| - onChildrenChange = noop, |
69 | 113 | onResolveNameConflict = () => "cancel",
|
70 | 114 | onCircularReference = noop,
|
71 | 115 | canCopy = truePredicate,
|
|
269 | 313 | }
|
270 | 314 | clipboardIds.add(itemId);
|
271 | 315 | pasteOperation = newPasteOperation;
|
272 |
| - onClipboardChange({ clipboardIds, pasteOperation }); |
273 | 316 | }
|
274 | 317 |
|
275 | 318 | export function clearClipboard() {
|
276 | 319 | clipboardIds.clear();
|
277 | 320 | pasteOperation = undefined;
|
278 |
| - onClipboardChange({ clipboardIds, pasteOperation }); |
279 | 321 | }
|
280 | 322 |
|
281 | 323 | async function copy(destination: TFolder | TTree) {
|
|
334 | 376 | for (const copy of copies) {
|
335 | 377 | destinationChildren.push(copy);
|
336 | 378 | }
|
337 |
| - onChildrenChange({ |
338 |
| - operation: "insert", |
339 |
| - target: destination, |
340 |
| - children: destinationChildren, |
341 |
| - }); |
342 | 379 |
|
343 | 380 | onCopy({ sources, copies, destination });
|
344 | 381 | return true;
|
|
409 | 446 |
|
410 | 447 | for (const owner of sourceOwners) {
|
411 | 448 | owner.children = owner.children.filter((child) => !sourceIds.has(child.id));
|
412 |
| - onChildrenChange({ |
413 |
| - operation: "remove", |
414 |
| - target: owner, |
415 |
| - children: owner.children, |
416 |
| - }); |
417 | 449 | }
|
418 | 450 |
|
419 | 451 | const destinationChildren = destination.children;
|
420 | 452 | for (const source of sources) {
|
421 | 453 | destinationChildren.push(source.node);
|
422 | 454 | }
|
423 |
| - onChildrenChange({ |
424 |
| - operation: "insert", |
425 |
| - target: destination, |
426 |
| - children: destinationChildren, |
427 |
| - }); |
428 | 455 |
|
429 | 456 | onMove({ sources, destination });
|
430 | 457 | return true;
|
|
547 | 574 | owner.children = owner.children.filter(
|
548 | 575 | (child) => !selectedIds.has(child.id) && child !== node,
|
549 | 576 | );
|
550 |
| - onChildrenChange({ |
551 |
| - operation: "remove", |
552 |
| - target: owner, |
553 |
| - children: owner.children, |
554 |
| - }); |
555 | 577 | }
|
556 | 578 | } else {
|
557 | 579 | const owner = item.parent?.node ?? root;
|
558 | 580 | owner.children = owner.children.filter((child) => child !== node);
|
559 |
| - onChildrenChange({ |
560 |
| - operation: "remove", |
561 |
| - target: owner, |
562 |
| - children: owner.children, |
563 |
| - }); |
564 | 581 | }
|
565 | 582 |
|
566 |
| - const currentClipboardSize = clipboardIds.size; |
567 | 583 | for (const item of removed) {
|
568 | 584 | onRemoveNode(item.node);
|
569 | 585 | }
|
570 | 586 |
|
571 |
| - if (clipboardIds.size !== currentClipboardSize) { |
572 |
| - onClipboardChange({ clipboardIds, pasteOperation }); |
573 |
| - } |
574 |
| -
|
575 | 587 | onRemove({ removed });
|
576 | 588 | return true;
|
577 | 589 | }
|
|
665 | 677 | }
|
666 | 678 | }
|
667 | 679 |
|
668 |
| - setTreeContext<TFile, TFolder, TTree>({ |
| 680 | + const context: TreeContext<TFile, TFolder, TTree> = { |
669 | 681 | root: () => root,
|
670 | 682 | tabbableId: () => tabbableId ?? root.children[0].id,
|
671 | 683 | getItemElementId,
|
|
1000 | 1012 | tabbableId = undefined;
|
1001 | 1013 | }
|
1002 | 1014 | },
|
1003 |
| - }); |
| 1015 | + }; |
| 1016 | + setContext(CONTEXT_KEY, context); |
1004 | 1017 |
|
1005 | 1018 | $effect(() => {
|
1006 | 1019 | return dropTargetForElements({
|
|
0 commit comments