Skip to content

Commit 14bbee5

Browse files
authored
Merge pull request #44 from abdel-17/context-menu
Add Context Menu to Preview
2 parents 12eab89 + 16d49eb commit 14bbee5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2227
-1003
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "module",
66
"scripts": {
77
"build": "pnpm -r build",
8-
"build:packages": "pnpm -F \"./packages/**\" --parallel build",
8+
"build:packages": "pnpm -F \"./packages/**\" -r build",
99
"build:preview": "pnpm build:packages && pnpm -F preview build",
1010
"check": "pnpm --parallel check",
1111
"format": "pnpm --parallel format",
@@ -28,4 +28,4 @@
2828
]
2929
},
3030
"packageManager": "[email protected]+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af"
31-
}
31+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
node_modules
2+
3+
# Generated Files
4+
/.svelte-kit
5+
6+
# Build
7+
/dist
8+
9+
# OS Files
10+
.DS_Store
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
engine-strict=true
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"useTabs": true,
3+
"printWidth": 100,
4+
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
5+
"overrides": [
6+
{
7+
"files": "*.svelte",
8+
"options": {
9+
"parser": "svelte"
10+
}
11+
}
12+
],
13+
"tailwindStylesheet": "./src/app.css"
14+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# create-svelte
2+
3+
Everything you need to build a Svelte library, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
4+
5+
Read more about creating a library [in the docs](https://svelte.dev/docs/kit/packaging).
6+
7+
## Creating a project
8+
9+
If you're seeing this, you've probably already done this step. Congrats!
10+
11+
```bash
12+
# create a new project in the current directory
13+
npx sv create
14+
15+
# create a new project in my-app
16+
npx sv create my-app
17+
```
18+
19+
## Developing
20+
21+
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
22+
23+
```bash
24+
npm run dev
25+
26+
# or start the server and open the app in a new browser tab
27+
npm run dev -- --open
28+
```
29+
30+
Everything inside `src/lib` is part of your library, everything inside `src/routes` can be used as a showcase or preview app.
31+
32+
## Building
33+
34+
To build your library:
35+
36+
```bash
37+
npm run package
38+
```
39+
40+
To create a production version of your showcase app:
41+
42+
```bash
43+
npm run build
44+
```
45+
46+
You can preview the production build with `npm run preview`.
47+
48+
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
49+
50+
## Publishing
51+
52+
Go into the `package.json` and give your package the desired name through the `"name"` option. Also consider adding a `"license"` field and point it to a `LICENSE` file which you can create from a template (one popular option is the [MIT license](https://opensource.org/license/mit/)).
53+
54+
To publish your library to [npm](https://www.npmjs.com):
55+
56+
```bash
57+
npm publish
58+
```
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"name": "svelte-file-tree-styled",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "svelte-kit sync && svelte-package --watch",
8+
"build": "svelte-kit sync && svelte-package && publint",
9+
"prepare": "svelte-kit sync || echo ''",
10+
"prepack": "pnpm run build",
11+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
12+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
13+
"format": "prettier --write .",
14+
"format:check": "prettier --check ."
15+
},
16+
"files": [
17+
"dist",
18+
"!dist/**/*.test.*",
19+
"!dist/**/*.spec.*"
20+
],
21+
"sideEffects": [
22+
"**/*.css"
23+
],
24+
"exports": {
25+
".": {
26+
"types": "./dist/index.d.ts",
27+
"svelte": "./dist/index.js"
28+
}
29+
},
30+
"types": "./dist/index.d.ts",
31+
"svelte": "./dist/index.js",
32+
"peerDependencies": {
33+
"svelte": "^5.20.0"
34+
},
35+
"devDependencies": {
36+
"@sveltejs/kit": "^2.20.0",
37+
"@sveltejs/package": "^2.0.0",
38+
"@sveltejs/vite-plugin-svelte": "^5.0.0",
39+
"@tailwindcss/vite": "^4.0.14",
40+
"prettier": "^3.4.2",
41+
"prettier-plugin-svelte": "^3.3.3",
42+
"prettier-plugin-tailwindcss": "^0.6.11",
43+
"publint": "^0.3.9",
44+
"svelte": "^5.23.1",
45+
"svelte-check": "^4.1.5",
46+
"tailwindcss": "^4.0.14",
47+
"typescript": "^5.0.0",
48+
"vite": "^6.2.2"
49+
},
50+
"dependencies": {
51+
"@lucide/svelte": "^0.482.0",
52+
"bits-ui": "^1.3.13",
53+
"svelte-file-tree": "workspace:^"
54+
}
55+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "tailwindcss";
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
%sveltekit.head%
8+
</head>
9+
<body data-sveltekit-preload-data="hover">
10+
<div>%sveltekit.body%</div>
11+
</body>
12+
</html>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<script lang="ts">
2+
import { Dialog } from "bits-ui";
3+
import type { EventHandler } from "svelte/elements";
4+
import { fade, scale } from "svelte/transition";
5+
6+
const id = $props.id();
7+
const typeId = `${id}:type`;
8+
const nameId = `${id}:name`;
9+
10+
type SubmitResult = {
11+
type: "file" | "folder";
12+
name: string;
13+
};
14+
15+
let isOpen = $state.raw(false);
16+
let type: "file" | "folder" = $state.raw("file");
17+
let name = $state.raw("");
18+
let onSubmit: ((result: SubmitResult) => Promise<boolean>) | undefined;
19+
let onCancel: (() => void) | undefined;
20+
21+
type OpenArgs = {
22+
onSubmit?: (result: SubmitResult) => Promise<boolean>;
23+
onCancel?: () => void;
24+
};
25+
26+
export function open(args: OpenArgs = {}) {
27+
if (isOpen) {
28+
throw new Error("The dialog is already open");
29+
}
30+
31+
isOpen = true;
32+
onSubmit = args.onSubmit;
33+
onCancel = args.onCancel;
34+
}
35+
36+
function reset(): void {
37+
onCancel = undefined;
38+
onSubmit = undefined;
39+
name = "";
40+
type = "file";
41+
isOpen = false;
42+
}
43+
44+
const handleSubmit: EventHandler<SubmitEvent, HTMLFormElement> = async (event) => {
45+
event.preventDefault();
46+
47+
if (onSubmit !== undefined) {
48+
const didSubmit = await onSubmit({ type, name });
49+
if (!didSubmit) {
50+
return;
51+
}
52+
}
53+
54+
reset();
55+
};
56+
57+
function onOpenChange(isOpen: boolean): void {
58+
if (!isOpen) {
59+
onCancel?.();
60+
reset();
61+
}
62+
}
63+
</script>
64+
65+
<Dialog.Root bind:open={isOpen} {onOpenChange}>
66+
<Dialog.Portal>
67+
<Dialog.Overlay forceMount class="fixed inset-0 z-50 bg-black/50">
68+
{#snippet child({ props })}
69+
{#if isOpen}
70+
<div {...props} transition:fade={{ duration: 200 }}></div>
71+
{/if}
72+
{/snippet}
73+
</Dialog.Overlay>
74+
75+
<Dialog.Content
76+
forceMount
77+
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"
78+
>
79+
{#snippet child({ props })}
80+
{#if isOpen}
81+
<div {...props} transition:scale={{ duration: 200, start: 0.9 }}>
82+
<Dialog.Title class="text-center text-2xl font-semibold tracking-tight">
83+
Add a New Item
84+
</Dialog.Title>
85+
86+
<form onsubmit={handleSubmit} class="mt-4">
87+
<div>
88+
<label for={typeId} class="text-sm font-medium">Type</label>
89+
<select
90+
id={typeId}
91+
bind:value={type}
92+
class="mt-1 block h-9 rounded border border-slate-400 bg-white ps-1 focus-visible:border-slate-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-600"
93+
>
94+
<option>file</option>
95+
<option>folder</option>
96+
</select>
97+
</div>
98+
99+
<div class="mt-3">
100+
<label for={nameId} class="text-sm font-medium">Name</label>
101+
<input
102+
id={nameId}
103+
bind:value={name}
104+
required
105+
class="mt-1 block h-9 w-full rounded border border-slate-400 bg-white px-3 focus-visible:border-slate-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-600"
106+
/>
107+
</div>
108+
109+
<div class="mt-5 ml-auto w-fit">
110+
<button
111+
type="submit"
112+
class="flex h-10 items-center justify-center rounded-lg border border-current px-6 text-sm font-semibold hover:bg-neutral-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current active:bg-neutral-300"
113+
>
114+
Add
115+
</button>
116+
</div>
117+
</form>
118+
</div>
119+
{/if}
120+
{/snippet}
121+
</Dialog.Content>
122+
</Dialog.Portal>
123+
</Dialog.Root>
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<script lang="ts">
2+
import { Dialog } from "bits-ui";
3+
import type { NameConflictResolution } from "svelte-file-tree";
4+
import { fade, fly } from "svelte/transition";
5+
6+
let isOpen = $state.raw(false);
7+
let title = $state.raw("");
8+
let description = $state.raw("");
9+
let onClose: ((result: NameConflictResolution) => void) | undefined;
10+
11+
type OpenArgs = {
12+
title: string;
13+
description: string;
14+
onClose?: (result: NameConflictResolution) => void;
15+
};
16+
17+
export function open(args: OpenArgs): void {
18+
if (isOpen) {
19+
throw new Error("The dialog is already open");
20+
}
21+
22+
isOpen = true;
23+
title = args.title;
24+
description = args.description;
25+
onClose = args.onClose;
26+
}
27+
28+
function close(result: NameConflictResolution): void {
29+
onClose?.(result);
30+
onClose = undefined;
31+
description = "";
32+
title = "";
33+
isOpen = false;
34+
}
35+
36+
function onOpenChange(isOpen: boolean): void {
37+
if (!isOpen) {
38+
close("cancel");
39+
}
40+
}
41+
</script>
42+
43+
<Dialog.Root bind:open={isOpen} {onOpenChange}>
44+
<Dialog.Portal>
45+
<Dialog.Overlay forceMount class="fixed inset-0 z-50 bg-black/50">
46+
{#snippet child({ props })}
47+
{#if isOpen}
48+
<div {...props} transition:fade={{ duration: 200 }}></div>
49+
{/if}
50+
{/snippet}
51+
</Dialog.Overlay>
52+
53+
<Dialog.Content
54+
forceMount
55+
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"
56+
>
57+
{#snippet child({ props })}
58+
{#if isOpen}
59+
<div {...props} transition:fly={{ y: "-100%" }}>
60+
<Dialog.Title class="text-center text-lg font-semibold tracking-tight">
61+
{title}
62+
</Dialog.Title>
63+
64+
<Dialog.Description class="mt-2 text-sm text-gray-700">
65+
{description}
66+
</Dialog.Description>
67+
68+
<div class="mt-5 flex justify-end gap-3">
69+
<button
70+
onclick={() => close("skip")}
71+
class="flex h-10 items-center justify-center rounded-lg border border-current px-6 text-sm font-semibold hover:bg-current/8 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current active:bg-current/12"
72+
>
73+
Skip
74+
</button>
75+
76+
<button
77+
onclick={() => close("cancel")}
78+
class="flex h-10 items-center justify-center rounded-lg border border-current px-6 text-sm font-semibold text-red-700 hover:bg-current/8 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current active:bg-current/12"
79+
>
80+
Cancel
81+
</button>
82+
</div>
83+
</div>
84+
{/if}
85+
{/snippet}
86+
</Dialog.Content>
87+
</Dialog.Portal>
88+
</Dialog.Root>

0 commit comments

Comments
 (0)