diff --git a/packages/svelte-file-tree/package.json b/packages/svelte-file-tree/package.json
index d278f73..1ec1c38 100644
--- a/packages/svelte-file-tree/package.json
+++ b/packages/svelte-file-tree/package.json
@@ -38,19 +38,19 @@
"svelte-signals": "^0.0.2"
},
"devDependencies": {
- "@sveltejs/kit": "^2.20.2",
+ "@sveltejs/kit": "^2.20.4",
"@sveltejs/package": "^2.3.10",
"@sveltejs/vite-plugin-svelte": "5.0.3",
- "@types/node": "^22.13.14",
- "@vitest/browser": "^3.0.9",
+ "@types/node": "^22.14.0",
+ "@vitest/browser": "^3.1.1",
"jsdom": "^26.0.0",
"prettier": "^3.5.3",
"prettier-plugin-svelte": "^3.3.3",
- "publint": "^0.3.9",
- "svelte": "5.25.3",
+ "publint": "^0.3.10",
+ "svelte": "5.25.6",
"svelte-check": "^4.1.5",
- "vite": "^6.2.3",
- "vitest": "3.0.9",
+ "vite": "^6.2.5",
+ "vitest": "3.1.1",
"vitest-browser-svelte": "^0.1.0"
},
"repository": {
diff --git a/packages/svelte-file-tree/src/lib/components/Tree/Tree.svelte b/packages/svelte-file-tree/src/lib/components/Tree/Tree.svelte
index 292f6b9..ff5f3c7 100644
--- a/packages/svelte-file-tree/src/lib/components/Tree/Tree.svelte
+++ b/packages/svelte-file-tree/src/lib/components/Tree/Tree.svelte
@@ -1,5 +1,6 @@
-
{#each treeState.items() as i (i.node.id)}
{#if i.visible()}
- {@render item({
- item: i,
- select: () => selectedIds.add(i.node.id),
- deselect: () => selectedIds.delete(i.node.id),
- expand: () => expandedIds.add(i.node.id),
- collapse: () => expandedIds.delete(i.node.id),
- rename: (name) => treeState.rename(i, name),
- copy: (operation) => treeState.copy(i, operation),
- paste: (position) => treeState.paste(i, position),
- remove: () => treeState.remove(i),
- })}
+ {@render item({ item: i })}
{/if}
{/each}
diff --git a/packages/svelte-file-tree/src/lib/components/Tree/TreeItemProvider.svelte b/packages/svelte-file-tree/src/lib/components/Tree/TreeItemProvider.svelte
index c279bfe..f800d89 100644
--- a/packages/svelte-file-tree/src/lib/components/Tree/TreeItemProvider.svelte
+++ b/packages/svelte-file-tree/src/lib/components/Tree/TreeItemProvider.svelte
@@ -1,5 +1,5 @@
-
-
-
-
-
diff --git a/sites/preview/src/lib/components/TreeContextMenu.svelte b/sites/preview/src/lib/components/TreeContextMenu.svelte
deleted file mode 100644
index bde4787..0000000
--- a/sites/preview/src/lib/components/TreeContextMenu.svelte
+++ /dev/null
@@ -1,284 +0,0 @@
-
-
-
-
-
menuState !== undefined, handleOpenChange}>
- {@render children()}
-
-
-
- {#if menuState?.type === "item"}
- {#if menuState.item().editable()}
-
-
- Rename
-
- {/if}
-
-
-
- Copy
-
-
-
-
- Cut
-
-
-
-
- Paste
-
-
-
-
- Delete
-
- {/if}
-
- {@const isFolder = menuState?.type === "item" && menuState.item().node.type === "folder"}
- {#if menuState?.type === "tree" || isFolder}
-
-
- New Folder
-
-
-
-
- Upload Files
-
- {/if}
-
-
-
-
-
-
-
diff --git a/sites/preview/src/lib/components/TreeContextMenuTrigger.svelte b/sites/preview/src/lib/components/TreeContextMenuTrigger.svelte
deleted file mode 100644
index b333473..0000000
--- a/sites/preview/src/lib/components/TreeContextMenuTrigger.svelte
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
diff --git a/sites/preview/src/lib/components/TreeItem.svelte b/sites/preview/src/lib/components/TreeItem.svelte
deleted file mode 100644
index a54449c..0000000
--- a/sites/preview/src/lib/components/TreeItem.svelte
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
diff --git a/sites/preview/src/lib/components/TreeItemToggle.svelte b/sites/preview/src/lib/components/TreeItemToggle.svelte
deleted file mode 100644
index a1127f4..0000000
--- a/sites/preview/src/lib/components/TreeItemToggle.svelte
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
diff --git a/sites/preview/src/lib/components/index.ts b/sites/preview/src/lib/components/index.ts
new file mode 100644
index 0000000..5b609aa
--- /dev/null
+++ b/sites/preview/src/lib/components/index.ts
@@ -0,0 +1 @@
+export { default as Tree } from "./tree/Tree.svelte";
diff --git a/sites/preview/src/lib/components/tree/ContextMenu.svelte b/sites/preview/src/lib/components/tree/ContextMenu.svelte
new file mode 100644
index 0000000..4e06605
--- /dev/null
+++ b/sites/preview/src/lib/components/tree/ContextMenu.svelte
@@ -0,0 +1,246 @@
+
+
+
openArgs !== undefined, handleOpenChange}>
+
+ {@render children()}
+
+
+
+
+ {#if openArgs?.type === "item"}
+ {@const item = openArgs.item()}
+ {#if item.editable()}
+
+
+ Rename
+
+ {/if}
+
+ onCopy(item, "copy")}>
+
+ Copy
+
+
+ onCopy(item, "cut")}>
+
+ Cut
+
+
+ onPaste(item)}>
+
+ Paste
+
+
+ onRemove(item)}>
+
+ Delete
+
+ {/if}
+
+ {@const isFolder = openArgs?.type === "item" && openArgs.item().node.type === "folder"}
+ {#if openArgs?.type === "tree" || isFolder}
+
+
+ New Folder
+
+
+
+
+ Upload Files
+
+ {/if}
+
+
+
+
+
diff --git a/sites/preview/src/lib/components/TreeContextMenuItem.svelte b/sites/preview/src/lib/components/tree/ContextMenuItem.svelte
similarity index 100%
rename from sites/preview/src/lib/components/TreeContextMenuItem.svelte
rename to sites/preview/src/lib/components/tree/ContextMenuItem.svelte
diff --git a/sites/preview/src/lib/components/NameConflictDialog.svelte b/sites/preview/src/lib/components/tree/NameConflictDialog.svelte
similarity index 72%
rename from sites/preview/src/lib/components/NameConflictDialog.svelte
rename to sites/preview/src/lib/components/tree/NameConflictDialog.svelte
index a12d42d..78b070d 100644
--- a/sites/preview/src/lib/components/NameConflictDialog.svelte
+++ b/sites/preview/src/lib/components/tree/NameConflictDialog.svelte
@@ -3,35 +3,25 @@
import type { NameConflictResolution } from "svelte-file-tree";
import { fade, fly } from "svelte/transition";
- let open = $state.raw(false);
- let title = $state.raw("");
- let description = $state.raw("");
- let onClose: ((resolution: NameConflictResolution) => void) | undefined;
-
type OpenArgs = {
title: string;
description: string;
- onClose?: (resolution: NameConflictResolution) => void;
+ onClose: (resolution: NameConflictResolution) => void;
};
- export function show(args: OpenArgs): void {
- if (open) {
+ let openArgs: OpenArgs | undefined = $state.raw();
+
+ export function open(args: OpenArgs): void {
+ if (openArgs !== undefined) {
throw new Error("Dialog is already open");
}
- open = true;
- title = args.title;
- description = args.description;
- onClose = args.onClose;
+ openArgs = args;
}
- function close(resolution: NameConflictResolution): void {
- onClose?.(resolution);
-
- open = false;
- title = "";
- description = "";
- onClose = undefined;
+ export function close(resolution: NameConflictResolution): void {
+ openArgs?.onClose(resolution);
+ openArgs = undefined;
}
function handleOpenChange(open: boolean): void {
@@ -41,10 +31,10 @@
}
-
open, handleOpenChange}>
+ openArgs !== undefined, handleOpenChange}>
- {#snippet child({ props })}
+ {#snippet child({ props, open })}
{#if open}
{/if}
@@ -55,15 +45,15 @@
forceMount
class="fixed top-0 left-1/2 z-50 w-xs -translate-x-1/2 rounded-b-lg bg-neutral-100 p-4 md:w-md"
>
- {#snippet child({ props })}
+ {#snippet child({ props, open })}
{#if open}
- {title}
+ {openArgs?.title}
- {description}
+ {openArgs?.description}
diff --git a/sites/preview/src/lib/components/NewFolderDialog.svelte b/sites/preview/src/lib/components/tree/NewFolderDialog.svelte
similarity index 77%
rename from sites/preview/src/lib/components/NewFolderDialog.svelte
rename to sites/preview/src/lib/components/tree/NewFolderDialog.svelte
index 394b48a..1c0630c 100644
--- a/sites/preview/src/lib/components/NewFolderDialog.svelte
+++ b/sites/preview/src/lib/components/tree/NewFolderDialog.svelte
@@ -5,27 +5,24 @@
const nameId = $props.id();
- let open = $state.raw(false);
- let name = $state.raw("");
- let onSubmit: ((name: string) => boolean) | undefined;
-
type OpenArgs = {
- onSubmit?: (name: string) => boolean;
+ onSubmit: (name: string) => void;
};
- export function show(args: OpenArgs): void {
- if (open) {
+ let openArgs: OpenArgs | undefined = $state.raw();
+ let name = $state.raw("");
+
+ export function open(args: OpenArgs): void {
+ if (openArgs !== undefined) {
throw new Error("Dialog is already open");
}
- open = true;
- onSubmit = args.onSubmit;
+ openArgs = args;
}
export function close(): void {
- open = false;
+ openArgs = undefined;
name = "";
- onSubmit = undefined;
}
function handleOpenChange(open: boolean): void {
@@ -35,23 +32,19 @@
}
const handleSubmit: EventHandler
= (event) => {
- event.preventDefault();
-
- if (onSubmit !== undefined) {
- const didSubmit = onSubmit(name);
- if (!didSubmit) {
- return;
- }
+ if (openArgs === undefined) {
+ throw new Error("Dialog is closed");
}
- close();
+ event.preventDefault();
+ openArgs.onSubmit(name);
};
- open, handleOpenChange}>
+ openArgs !== undefined, handleOpenChange}>
- {#snippet child({ props })}
+ {#snippet child({ props, open })}
{#if open}
{/if}
@@ -62,18 +55,18 @@
forceMount
class="fixed top-1/2 left-1/2 z-50 w-xs -translate-x-1/2 -translate-y-1/2 rounded-lg bg-neutral-100 p-4 md:w-md"
>
- {#snippet child({ props })}
+ {#snippet child({ props, open })}
{#if open}