+27
.gitignore
+27
.gitignore
···
1
+
node_modules
2
+
3
+
# Output
4
+
.output
5
+
.vercel
6
+
.netlify
7
+
.wrangler
8
+
.svelte-kit
9
+
build
10
+
dist
11
+
12
+
# OS
13
+
.DS_Store
14
+
Thumbs.db
15
+
16
+
# Env
17
+
.env
18
+
.env.*
19
+
!.env.example
20
+
!.env.test
21
+
22
+
# Vite
23
+
vite.config.js.timestamp-*
24
+
vite.config.ts.timestamp-*
25
+
26
+
# SQLite
27
+
*.db
+1
apps/web/.env.example
+1
apps/web/.env.example
···
1
+
DATABASE_URL=file:local.db
+1
apps/web/.npmrc
+1
apps/web/.npmrc
···
1
+
engine-strict=true
+10
apps/web/.prettierignore
+10
apps/web/.prettierignore
+16
apps/web/.prettierrc
+16
apps/web/.prettierrc
···
1
+
{
2
+
"useTabs": true,
3
+
"singleQuote": true,
4
+
"trailingComma": "es5",
5
+
"printWidth": 100,
6
+
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
7
+
"overrides": [
8
+
{
9
+
"files": "*.svelte",
10
+
"options": {
11
+
"parser": "svelte"
12
+
}
13
+
}
14
+
],
15
+
"tailwindStylesheet": "./src/app.css"
16
+
}
+38
apps/web/README.md
+38
apps/web/README.md
···
1
+
# sv
2
+
3
+
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
4
+
5
+
## Creating a project
6
+
7
+
If you're seeing this, you've probably already done this step. Congrats!
8
+
9
+
```sh
10
+
# create a new project in the current directory
11
+
npx sv create
12
+
13
+
# create a new project in my-app
14
+
npx sv create my-app
15
+
```
16
+
17
+
## Developing
18
+
19
+
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20
+
21
+
```sh
22
+
npm run dev
23
+
24
+
# or start the server and open the app in a new browser tab
25
+
npm run dev -- --open
26
+
```
27
+
28
+
## Building
29
+
30
+
To create a production version of your app:
31
+
32
+
```sh
33
+
npm run build
34
+
```
35
+
36
+
You can preview the production build with `npm run preview`.
37
+
38
+
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
+16
apps/web/components.json
+16
apps/web/components.json
···
1
+
{
2
+
"$schema": "https://shadcn-svelte.com/schema.json",
3
+
"tailwind": {
4
+
"css": "src/app.css",
5
+
"baseColor": "stone"
6
+
},
7
+
"aliases": {
8
+
"components": "$lib/components",
9
+
"utils": "$lib/utils/cn",
10
+
"ui": "$lib/components/ui",
11
+
"hooks": "$lib/hooks",
12
+
"lib": "$lib"
13
+
},
14
+
"typescript": true,
15
+
"registry": "https://shadcn-svelte.com/registry"
16
+
}
+11
apps/web/drizzle.config.ts
+11
apps/web/drizzle.config.ts
···
1
+
import { defineConfig } from 'drizzle-kit';
2
+
3
+
if (!process.env.DATABASE_URL) throw new Error('DATABASE_URL is not set');
4
+
5
+
export default defineConfig({
6
+
schema: './src/lib/server/db/schema.ts',
7
+
dialect: 'sqlite',
8
+
dbCredentials: { url: process.env.DATABASE_URL },
9
+
verbose: true,
10
+
strict: true
11
+
});
+41
apps/web/eslint.config.js
+41
apps/web/eslint.config.js
···
1
+
import prettier from 'eslint-config-prettier';
2
+
import { fileURLToPath } from 'node:url';
3
+
import { includeIgnoreFile } from '@eslint/compat';
4
+
import js from '@eslint/js';
5
+
import svelte from 'eslint-plugin-svelte';
6
+
import { defineConfig } from 'eslint/config';
7
+
import globals from 'globals';
8
+
import ts from 'typescript-eslint';
9
+
import svelteConfig from './svelte.config.js';
10
+
11
+
const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url));
12
+
13
+
export default defineConfig(
14
+
includeIgnoreFile(gitignorePath),
15
+
js.configs.recommended,
16
+
...ts.configs.recommended,
17
+
...svelte.configs.recommended,
18
+
prettier,
19
+
...svelte.configs.prettier,
20
+
{
21
+
languageOptions: {
22
+
globals: { ...globals.browser, ...globals.node }
23
+
},
24
+
rules: {
25
+
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
26
+
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
27
+
'no-undef': 'off'
28
+
}
29
+
},
30
+
{
31
+
files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],
32
+
languageOptions: {
33
+
parserOptions: {
34
+
projectService: true,
35
+
extraFileExtensions: ['.svelte'],
36
+
parser: ts.parser,
37
+
svelteConfig
38
+
}
39
+
}
40
+
}
41
+
);
+71
apps/web/package.json
+71
apps/web/package.json
···
1
+
{
2
+
"name": "@iced-tea/web",
3
+
"private": true,
4
+
"version": "0.0.1",
5
+
"type": "module",
6
+
"scripts": {
7
+
"dev": "vite dev",
8
+
"build": "vite build",
9
+
"preview": "vite preview",
10
+
"prepare": "svelte-kit sync || echo ''",
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
+
"lint": "prettier --check . && eslint .",
15
+
"db:push": "drizzle-kit push",
16
+
"db:generate": "drizzle-kit generate",
17
+
"db:migrate": "drizzle-kit migrate",
18
+
"db:studio": "drizzle-kit studio"
19
+
},
20
+
"devDependencies": {
21
+
"@eslint/compat": "^1.4.0",
22
+
"@eslint/js": "^9.36.0",
23
+
"@internationalized/date": "^3.8.1",
24
+
"@libsql/client": "^0.15.15",
25
+
"@sveltejs/adapter-auto": "^6.1.0",
26
+
"@sveltejs/kit": "^2.43.2",
27
+
"@sveltejs/vite-plugin-svelte": "^6.2.0",
28
+
"@tailwindcss/forms": "^0.5.10",
29
+
"@tailwindcss/typography": "^0.5.18",
30
+
"@tailwindcss/vite": "^4.1.13",
31
+
"@tanstack/table-core": "^8.20.5",
32
+
"@types/node": "^22",
33
+
"bits-ui": "^2.11.0",
34
+
"clsx": "^2.1.1",
35
+
"drizzle-kit": "^0.31.4",
36
+
"drizzle-orm": "^0.44.5",
37
+
"embla-carousel-svelte": "^8.6.0",
38
+
"eslint": "^9.36.0",
39
+
"eslint-config-prettier": "^10.1.8",
40
+
"eslint-plugin-svelte": "^3.12.4",
41
+
"formsnap": "^2.0.1",
42
+
"globals": "^16.4.0",
43
+
"layerchart": "2.0.0-next.27",
44
+
"mode-watcher": "^1.1.0",
45
+
"paneforge": "^1.0.2",
46
+
"prettier": "^3.6.2",
47
+
"prettier-plugin-svelte": "^3.4.0",
48
+
"prettier-plugin-tailwindcss": "^0.6.14",
49
+
"svelte": "^5.39.5",
50
+
"svelte-check": "^4.3.2",
51
+
"svelte-sonner": "^1.0.5",
52
+
"sveltekit-superforms": "^2.26.1",
53
+
"tailwind-merge": "^3.3.1",
54
+
"tailwind-variants": "^3.1.1",
55
+
"tailwindcss": "^4.1.13",
56
+
"tw-animate-css": "^1.4.0",
57
+
"typescript": "^5.9.2",
58
+
"typescript-eslint": "^8.44.1",
59
+
"vaul-svelte": "^1.0.0-next.7",
60
+
"vite": "^7.1.7",
61
+
"vite-plugin-devtools-json": "^1.0.0"
62
+
},
63
+
"dependencies": {
64
+
"@fontsource/roboto": "^5.2.8",
65
+
"@lucide/svelte": "^0.544.0",
66
+
"framework7-icons": "^5.0.5",
67
+
"konsta": "^4.0.0-next.1",
68
+
"svelte-bottom-sheet": "^2.2.2",
69
+
"svelte-maplibre-gl": "^1.0.1"
70
+
}
71
+
}
+121
apps/web/src/app.css
+121
apps/web/src/app.css
···
1
+
@import "tailwindcss";
2
+
3
+
@import "tw-animate-css";
4
+
5
+
@custom-variant dark (&:is(.dark *));
6
+
7
+
:root {
8
+
--radius: 0.625rem;
9
+
--background: oklch(1 0 0);
10
+
--foreground: oklch(0.147 0.004 49.25);
11
+
--card: oklch(1 0 0);
12
+
--card-foreground: oklch(0.147 0.004 49.25);
13
+
--popover: oklch(1 0 0);
14
+
--popover-foreground: oklch(0.147 0.004 49.25);
15
+
--primary: oklch(0.216 0.006 56.043);
16
+
--primary-foreground: oklch(0.985 0.001 106.423);
17
+
--secondary: oklch(0.97 0.001 106.424);
18
+
--secondary-foreground: oklch(0.216 0.006 56.043);
19
+
--muted: oklch(0.97 0.001 106.424);
20
+
--muted-foreground: oklch(0.553 0.013 58.071);
21
+
--accent: oklch(0.97 0.001 106.424);
22
+
--accent-foreground: oklch(0.216 0.006 56.043);
23
+
--destructive: oklch(0.577 0.245 27.325);
24
+
--border: oklch(0.923 0.003 48.717);
25
+
--input: oklch(0.923 0.003 48.717);
26
+
--ring: oklch(0.709 0.01 56.259);
27
+
--chart-1: oklch(0.646 0.222 41.116);
28
+
--chart-2: oklch(0.6 0.118 184.704);
29
+
--chart-3: oklch(0.398 0.07 227.392);
30
+
--chart-4: oklch(0.828 0.189 84.429);
31
+
--chart-5: oklch(0.769 0.188 70.08);
32
+
--sidebar: oklch(0.985 0.001 106.423);
33
+
--sidebar-foreground: oklch(0.147 0.004 49.25);
34
+
--sidebar-primary: oklch(0.216 0.006 56.043);
35
+
--sidebar-primary-foreground: oklch(0.985 0.001 106.423);
36
+
--sidebar-accent: oklch(0.97 0.001 106.424);
37
+
--sidebar-accent-foreground: oklch(0.216 0.006 56.043);
38
+
--sidebar-border: oklch(0.923 0.003 48.717);
39
+
--sidebar-ring: oklch(0.709 0.01 56.259);
40
+
}
41
+
42
+
.dark {
43
+
--background: oklch(0.147 0.004 49.25);
44
+
--foreground: oklch(0.985 0.001 106.423);
45
+
--card: oklch(0.216 0.006 56.043);
46
+
--card-foreground: oklch(0.985 0.001 106.423);
47
+
--popover: oklch(0.216 0.006 56.043);
48
+
--popover-foreground: oklch(0.985 0.001 106.423);
49
+
--primary: oklch(0.923 0.003 48.717);
50
+
--primary-foreground: oklch(0.216 0.006 56.043);
51
+
--secondary: oklch(0.268 0.007 34.298);
52
+
--secondary-foreground: oklch(0.985 0.001 106.423);
53
+
--muted: oklch(0.268 0.007 34.298);
54
+
--muted-foreground: oklch(0.709 0.01 56.259);
55
+
--accent: oklch(0.268 0.007 34.298);
56
+
--accent-foreground: oklch(0.985 0.001 106.423);
57
+
--destructive: oklch(0.704 0.191 22.216);
58
+
--border: oklch(1 0 0 / 10%);
59
+
--input: oklch(1 0 0 / 15%);
60
+
--ring: oklch(0.553 0.013 58.071);
61
+
--chart-1: oklch(0.488 0.243 264.376);
62
+
--chart-2: oklch(0.696 0.17 162.48);
63
+
--chart-3: oklch(0.769 0.188 70.08);
64
+
--chart-4: oklch(0.627 0.265 303.9);
65
+
--chart-5: oklch(0.645 0.246 16.439);
66
+
--sidebar: oklch(0.216 0.006 56.043);
67
+
--sidebar-foreground: oklch(0.985 0.001 106.423);
68
+
--sidebar-primary: oklch(0.488 0.243 264.376);
69
+
--sidebar-primary-foreground: oklch(0.985 0.001 106.423);
70
+
--sidebar-accent: oklch(0.268 0.007 34.298);
71
+
--sidebar-accent-foreground: oklch(0.985 0.001 106.423);
72
+
--sidebar-border: oklch(1 0 0 / 10%);
73
+
--sidebar-ring: oklch(0.553 0.013 58.071);
74
+
}
75
+
76
+
@theme inline {
77
+
--radius-sm: calc(var(--radius) - 4px);
78
+
--radius-md: calc(var(--radius) - 2px);
79
+
--radius-lg: var(--radius);
80
+
--radius-xl: calc(var(--radius) + 4px);
81
+
--color-background: var(--background);
82
+
--color-foreground: var(--foreground);
83
+
--color-card: var(--card);
84
+
--color-card-foreground: var(--card-foreground);
85
+
--color-popover: var(--popover);
86
+
--color-popover-foreground: var(--popover-foreground);
87
+
--color-primary: var(--primary);
88
+
--color-primary-foreground: var(--primary-foreground);
89
+
--color-secondary: var(--secondary);
90
+
--color-secondary-foreground: var(--secondary-foreground);
91
+
--color-muted: var(--muted);
92
+
--color-muted-foreground: var(--muted-foreground);
93
+
--color-accent: var(--accent);
94
+
--color-accent-foreground: var(--accent-foreground);
95
+
--color-destructive: var(--destructive);
96
+
--color-border: var(--border);
97
+
--color-input: var(--input);
98
+
--color-ring: var(--ring);
99
+
--color-chart-1: var(--chart-1);
100
+
--color-chart-2: var(--chart-2);
101
+
--color-chart-3: var(--chart-3);
102
+
--color-chart-4: var(--chart-4);
103
+
--color-chart-5: var(--chart-5);
104
+
--color-sidebar: var(--sidebar);
105
+
--color-sidebar-foreground: var(--sidebar-foreground);
106
+
--color-sidebar-primary: var(--sidebar-primary);
107
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
108
+
--color-sidebar-accent: var(--sidebar-accent);
109
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
110
+
--color-sidebar-border: var(--sidebar-border);
111
+
--color-sidebar-ring: var(--sidebar-ring);
112
+
}
113
+
114
+
@layer base {
115
+
* {
116
+
@apply border-border outline-ring/50;
117
+
}
118
+
body {
119
+
@apply bg-background text-foreground;
120
+
}
121
+
}
+13
apps/web/src/app.d.ts
+13
apps/web/src/app.d.ts
···
1
+
// See https://svelte.dev/docs/kit/types#app.d.ts
2
+
// for information about these interfaces
3
+
declare global {
4
+
namespace App {
5
+
// interface Error {}
6
+
// interface Locals {}
7
+
// interface PageData {}
8
+
// interface PageState {}
9
+
// interface Platform {}
10
+
}
11
+
}
12
+
13
+
export {};
+11
apps/web/src/app.html
+11
apps/web/src/app.html
···
1
+
<!doctype html>
2
+
<html lang="en">
3
+
<head>
4
+
<meta charset="utf-8" />
5
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6
+
%sveltekit.head%
7
+
</head>
8
+
<body data-sveltekit-preload-data="hover">
9
+
<div style="display: contents">%sveltekit.body%</div>
10
+
</body>
11
+
</html>
+1
apps/web/src/lib/assets/favicon.svg
+1
apps/web/src/lib/assets/favicon.svg
···
1
+
<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>
+10
apps/web/src/lib/components/layout/app-shell.svelte
+10
apps/web/src/lib/components/layout/app-shell.svelte
+32
apps/web/src/lib/components/mode-switcher.svelte
+32
apps/web/src/lib/components/mode-switcher.svelte
···
1
+
<script lang="ts">
2
+
import SunIcon from '@lucide/svelte/icons/sun';
3
+
import MoonIcon from '@lucide/svelte/icons/moon';
4
+
5
+
import { resetMode, setMode } from 'mode-watcher';
6
+
import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
7
+
import { buttonVariants } from '$lib/components/ui/button';
8
+
import { cn } from '$lib/utils/cn';
9
+
10
+
let { class: className }: { class: string } = $props();
11
+
12
+
let cluster = $state(true);
13
+
let clusterMaxZoom = $state(11);
14
+
let clusterRadius = $state(50);
15
+
</script>
16
+
17
+
<DropdownMenu.Root>
18
+
<DropdownMenu.Trigger class={cn(buttonVariants({ variant: 'default', size: 'icon' }), className)}>
19
+
<SunIcon
20
+
class="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 !transition-all dark:scale-0 dark:-rotate-90"
21
+
/>
22
+
<MoonIcon
23
+
class="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 !transition-all dark:scale-100 dark:rotate-0"
24
+
/>
25
+
<span class="sr-only">Toggle theme</span>
26
+
</DropdownMenu.Trigger>
27
+
<DropdownMenu.Content align="end">
28
+
<DropdownMenu.Item onclick={() => setMode('light')}>Light</DropdownMenu.Item>
29
+
<DropdownMenu.Item onclick={() => setMode('dark')}>Dark</DropdownMenu.Item>
30
+
<DropdownMenu.Item onclick={() => resetMode()}>System</DropdownMenu.Item>
31
+
</DropdownMenu.Content>
32
+
</DropdownMenu.Root>
+22
apps/web/src/lib/components/ui/accordion/accordion-content.svelte
+22
apps/web/src/lib/components/ui/accordion/accordion-content.svelte
···
1
+
<script lang="ts">
2
+
import { Accordion as AccordionPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithoutChild<AccordionPrimitive.ContentProps> = $props();
11
+
</script>
12
+
13
+
<AccordionPrimitive.Content
14
+
bind:ref
15
+
data-slot="accordion-content"
16
+
class="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
17
+
{...restProps}
18
+
>
19
+
<div class={cn("pb-4 pt-0", className)}>
20
+
{@render children?.()}
21
+
</div>
22
+
</AccordionPrimitive.Content>
+17
apps/web/src/lib/components/ui/accordion/accordion-item.svelte
+17
apps/web/src/lib/components/ui/accordion/accordion-item.svelte
···
1
+
<script lang="ts">
2
+
import { Accordion as AccordionPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: AccordionPrimitive.ItemProps = $props();
10
+
</script>
11
+
12
+
<AccordionPrimitive.Item
13
+
bind:ref
14
+
data-slot="accordion-item"
15
+
class={cn("border-b last:border-b-0", className)}
16
+
{...restProps}
17
+
/>
+32
apps/web/src/lib/components/ui/accordion/accordion-trigger.svelte
+32
apps/web/src/lib/components/ui/accordion/accordion-trigger.svelte
···
1
+
<script lang="ts">
2
+
import { Accordion as AccordionPrimitive } from "bits-ui";
3
+
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
4
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
level = 3,
10
+
children,
11
+
...restProps
12
+
}: WithoutChild<AccordionPrimitive.TriggerProps> & {
13
+
level?: AccordionPrimitive.HeaderProps["level"];
14
+
} = $props();
15
+
</script>
16
+
17
+
<AccordionPrimitive.Header {level} class="flex">
18
+
<AccordionPrimitive.Trigger
19
+
data-slot="accordion-trigger"
20
+
bind:ref
21
+
class={cn(
22
+
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium outline-none transition-all hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
23
+
className
24
+
)}
25
+
{...restProps}
26
+
>
27
+
{@render children?.()}
28
+
<ChevronDownIcon
29
+
class="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200"
30
+
/>
31
+
</AccordionPrimitive.Trigger>
32
+
</AccordionPrimitive.Header>
+16
apps/web/src/lib/components/ui/accordion/accordion.svelte
+16
apps/web/src/lib/components/ui/accordion/accordion.svelte
···
1
+
<script lang="ts">
2
+
import { Accordion as AccordionPrimitive } from "bits-ui";
3
+
4
+
let {
5
+
ref = $bindable(null),
6
+
value = $bindable(),
7
+
...restProps
8
+
}: AccordionPrimitive.RootProps = $props();
9
+
</script>
10
+
11
+
<AccordionPrimitive.Root
12
+
bind:ref
13
+
bind:value={value as never}
14
+
data-slot="accordion"
15
+
{...restProps}
16
+
/>
+16
apps/web/src/lib/components/ui/accordion/index.ts
+16
apps/web/src/lib/components/ui/accordion/index.ts
···
1
+
import Root from "./accordion.svelte";
2
+
import Content from "./accordion-content.svelte";
3
+
import Item from "./accordion-item.svelte";
4
+
import Trigger from "./accordion-trigger.svelte";
5
+
6
+
export {
7
+
Root,
8
+
Content,
9
+
Item,
10
+
Trigger,
11
+
//
12
+
Root as Accordion,
13
+
Content as AccordionContent,
14
+
Item as AccordionItem,
15
+
Trigger as AccordionTrigger,
16
+
};
+18
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte
+18
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte
···
1
+
<script lang="ts">
2
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
3
+
import { buttonVariants } from "$lib/components/ui/button/index.js";
4
+
import { cn } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
...restProps
10
+
}: AlertDialogPrimitive.ActionProps = $props();
11
+
</script>
12
+
13
+
<AlertDialogPrimitive.Action
14
+
bind:ref
15
+
data-slot="alert-dialog-action"
16
+
class={cn(buttonVariants(), className)}
17
+
{...restProps}
18
+
/>
+18
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte
+18
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte
···
1
+
<script lang="ts">
2
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
3
+
import { buttonVariants } from "$lib/components/ui/button/index.js";
4
+
import { cn } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
...restProps
10
+
}: AlertDialogPrimitive.CancelProps = $props();
11
+
</script>
12
+
13
+
<AlertDialogPrimitive.Cancel
14
+
bind:ref
15
+
data-slot="alert-dialog-cancel"
16
+
class={cn(buttonVariants({ variant: "outline" }), className)}
17
+
{...restProps}
18
+
/>
+27
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte
+27
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte
···
1
+
<script lang="ts">
2
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
3
+
import AlertDialogOverlay from "./alert-dialog-overlay.svelte";
4
+
import { cn, type WithoutChild, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
portalProps,
10
+
...restProps
11
+
}: WithoutChild<AlertDialogPrimitive.ContentProps> & {
12
+
portalProps?: WithoutChildrenOrChild<AlertDialogPrimitive.PortalProps>;
13
+
} = $props();
14
+
</script>
15
+
16
+
<AlertDialogPrimitive.Portal {...portalProps}>
17
+
<AlertDialogOverlay />
18
+
<AlertDialogPrimitive.Content
19
+
bind:ref
20
+
data-slot="alert-dialog-content"
21
+
class={cn(
22
+
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed left-[50%] top-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
23
+
className
24
+
)}
25
+
{...restProps}
26
+
/>
27
+
</AlertDialogPrimitive.Portal>
+17
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte
+17
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte
···
1
+
<script lang="ts">
2
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: AlertDialogPrimitive.DescriptionProps = $props();
10
+
</script>
11
+
12
+
<AlertDialogPrimitive.Description
13
+
bind:ref
14
+
data-slot="alert-dialog-description"
15
+
class={cn("text-muted-foreground text-sm", className)}
16
+
{...restProps}
17
+
/>
+20
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte
+20
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="alert-dialog-header"
16
+
class={cn("flex flex-col gap-2 text-center sm:text-left", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+20
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte
+20
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte
···
1
+
<script lang="ts">
2
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: AlertDialogPrimitive.OverlayProps = $props();
10
+
</script>
11
+
12
+
<AlertDialogPrimitive.Overlay
13
+
bind:ref
14
+
data-slot="alert-dialog-overlay"
15
+
class={cn(
16
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+17
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte
+17
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte
···
1
+
<script lang="ts">
2
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: AlertDialogPrimitive.TitleProps = $props();
10
+
</script>
11
+
12
+
<AlertDialogPrimitive.Title
13
+
bind:ref
14
+
data-slot="alert-dialog-title"
15
+
class={cn("text-lg font-semibold", className)}
16
+
{...restProps}
17
+
/>
+7
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte
+7
apps/web/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte
···
1
+
<script lang="ts">
2
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
3
+
4
+
let { ref = $bindable(null), ...restProps }: AlertDialogPrimitive.TriggerProps = $props();
5
+
</script>
6
+
7
+
<AlertDialogPrimitive.Trigger bind:ref data-slot="alert-dialog-trigger" {...restProps} />
+39
apps/web/src/lib/components/ui/alert-dialog/index.ts
+39
apps/web/src/lib/components/ui/alert-dialog/index.ts
···
1
+
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
2
+
import Trigger from "./alert-dialog-trigger.svelte";
3
+
import Title from "./alert-dialog-title.svelte";
4
+
import Action from "./alert-dialog-action.svelte";
5
+
import Cancel from "./alert-dialog-cancel.svelte";
6
+
import Footer from "./alert-dialog-footer.svelte";
7
+
import Header from "./alert-dialog-header.svelte";
8
+
import Overlay from "./alert-dialog-overlay.svelte";
9
+
import Content from "./alert-dialog-content.svelte";
10
+
import Description from "./alert-dialog-description.svelte";
11
+
12
+
const Root = AlertDialogPrimitive.Root;
13
+
const Portal = AlertDialogPrimitive.Portal;
14
+
15
+
export {
16
+
Root,
17
+
Title,
18
+
Action,
19
+
Cancel,
20
+
Portal,
21
+
Footer,
22
+
Header,
23
+
Trigger,
24
+
Overlay,
25
+
Content,
26
+
Description,
27
+
//
28
+
Root as AlertDialog,
29
+
Title as AlertDialogTitle,
30
+
Action as AlertDialogAction,
31
+
Cancel as AlertDialogCancel,
32
+
Portal as AlertDialogPortal,
33
+
Footer as AlertDialogFooter,
34
+
Header as AlertDialogHeader,
35
+
Trigger as AlertDialogTrigger,
36
+
Overlay as AlertDialogOverlay,
37
+
Content as AlertDialogContent,
38
+
Description as AlertDialogDescription,
39
+
};
+23
apps/web/src/lib/components/ui/alert/alert-description.svelte
+23
apps/web/src/lib/components/ui/alert/alert-description.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="alert-description"
16
+
class={cn(
17
+
"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
>
22
+
{@render children?.()}
23
+
</div>
+20
apps/web/src/lib/components/ui/alert/alert-title.svelte
+20
apps/web/src/lib/components/ui/alert/alert-title.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="alert-title"
16
+
class={cn("col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+44
apps/web/src/lib/components/ui/alert/alert.svelte
+44
apps/web/src/lib/components/ui/alert/alert.svelte
···
1
+
<script lang="ts" module>
2
+
import { type VariantProps, tv } from "tailwind-variants";
3
+
4
+
export const alertVariants = tv({
5
+
base: "relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
6
+
variants: {
7
+
variant: {
8
+
default: "bg-card text-card-foreground",
9
+
destructive:
10
+
"text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current",
11
+
},
12
+
},
13
+
defaultVariants: {
14
+
variant: "default",
15
+
},
16
+
});
17
+
18
+
export type AlertVariant = VariantProps<typeof alertVariants>["variant"];
19
+
</script>
20
+
21
+
<script lang="ts">
22
+
import type { HTMLAttributes } from "svelte/elements";
23
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
24
+
25
+
let {
26
+
ref = $bindable(null),
27
+
class: className,
28
+
variant = "default",
29
+
children,
30
+
...restProps
31
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
32
+
variant?: AlertVariant;
33
+
} = $props();
34
+
</script>
35
+
36
+
<div
37
+
bind:this={ref}
38
+
data-slot="alert"
39
+
class={cn(alertVariants({ variant }), className)}
40
+
{...restProps}
41
+
role="alert"
42
+
>
43
+
{@render children?.()}
44
+
</div>
+14
apps/web/src/lib/components/ui/alert/index.ts
+14
apps/web/src/lib/components/ui/alert/index.ts
···
1
+
import Root from "./alert.svelte";
2
+
import Description from "./alert-description.svelte";
3
+
import Title from "./alert-title.svelte";
4
+
export { alertVariants, type AlertVariant } from "./alert.svelte";
5
+
6
+
export {
7
+
Root,
8
+
Description,
9
+
Title,
10
+
//
11
+
Root as Alert,
12
+
Description as AlertDescription,
13
+
Title as AlertTitle,
14
+
};
+7
apps/web/src/lib/components/ui/aspect-ratio/aspect-ratio.svelte
+7
apps/web/src/lib/components/ui/aspect-ratio/aspect-ratio.svelte
+3
apps/web/src/lib/components/ui/aspect-ratio/index.ts
+3
apps/web/src/lib/components/ui/aspect-ratio/index.ts
+17
apps/web/src/lib/components/ui/avatar/avatar-fallback.svelte
+17
apps/web/src/lib/components/ui/avatar/avatar-fallback.svelte
···
1
+
<script lang="ts">
2
+
import { Avatar as AvatarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: AvatarPrimitive.FallbackProps = $props();
10
+
</script>
11
+
12
+
<AvatarPrimitive.Fallback
13
+
bind:ref
14
+
data-slot="avatar-fallback"
15
+
class={cn("bg-muted flex size-full items-center justify-center rounded-full", className)}
16
+
{...restProps}
17
+
/>
+17
apps/web/src/lib/components/ui/avatar/avatar-image.svelte
+17
apps/web/src/lib/components/ui/avatar/avatar-image.svelte
···
1
+
<script lang="ts">
2
+
import { Avatar as AvatarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: AvatarPrimitive.ImageProps = $props();
10
+
</script>
11
+
12
+
<AvatarPrimitive.Image
13
+
bind:ref
14
+
data-slot="avatar-image"
15
+
class={cn("aspect-square size-full", className)}
16
+
{...restProps}
17
+
/>
+19
apps/web/src/lib/components/ui/avatar/avatar.svelte
+19
apps/web/src/lib/components/ui/avatar/avatar.svelte
···
1
+
<script lang="ts">
2
+
import { Avatar as AvatarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
loadingStatus = $bindable("loading"),
8
+
class: className,
9
+
...restProps
10
+
}: AvatarPrimitive.RootProps = $props();
11
+
</script>
12
+
13
+
<AvatarPrimitive.Root
14
+
bind:ref
15
+
bind:loadingStatus
16
+
data-slot="avatar"
17
+
class={cn("relative flex size-8 shrink-0 overflow-hidden rounded-full", className)}
18
+
{...restProps}
19
+
/>
+13
apps/web/src/lib/components/ui/avatar/index.ts
+13
apps/web/src/lib/components/ui/avatar/index.ts
+50
apps/web/src/lib/components/ui/badge/badge.svelte
+50
apps/web/src/lib/components/ui/badge/badge.svelte
···
1
+
<script lang="ts" module>
2
+
import { type VariantProps, tv } from "tailwind-variants";
3
+
4
+
export const badgeVariants = tv({
5
+
base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-md border px-2 py-0.5 text-xs font-medium transition-[color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none [&>svg]:size-3",
6
+
variants: {
7
+
variant: {
8
+
default:
9
+
"bg-primary text-primary-foreground [a&]:hover:bg-primary/90 border-transparent",
10
+
secondary:
11
+
"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90 border-transparent",
12
+
destructive:
13
+
"bg-destructive [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/70 border-transparent text-white",
14
+
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
15
+
},
16
+
},
17
+
defaultVariants: {
18
+
variant: "default",
19
+
},
20
+
});
21
+
22
+
export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
23
+
</script>
24
+
25
+
<script lang="ts">
26
+
import type { HTMLAnchorAttributes } from "svelte/elements";
27
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
28
+
29
+
let {
30
+
ref = $bindable(null),
31
+
href,
32
+
class: className,
33
+
variant = "default",
34
+
children,
35
+
...restProps
36
+
}: WithElementRef<HTMLAnchorAttributes> & {
37
+
variant?: BadgeVariant;
38
+
} = $props();
39
+
</script>
40
+
41
+
<svelte:element
42
+
this={href ? "a" : "span"}
43
+
bind:this={ref}
44
+
data-slot="badge"
45
+
{href}
46
+
class={cn(badgeVariants({ variant }), className)}
47
+
{...restProps}
48
+
>
49
+
{@render children?.()}
50
+
</svelte:element>
+2
apps/web/src/lib/components/ui/badge/index.ts
+2
apps/web/src/lib/components/ui/badge/index.ts
+76
apps/web/src/lib/components/ui/calendar/calendar-caption.svelte
+76
apps/web/src/lib/components/ui/calendar/calendar-caption.svelte
···
1
+
<script lang="ts">
2
+
import type { ComponentProps } from "svelte";
3
+
import type Calendar from "./calendar.svelte";
4
+
import CalendarMonthSelect from "./calendar-month-select.svelte";
5
+
import CalendarYearSelect from "./calendar-year-select.svelte";
6
+
import { DateFormatter, getLocalTimeZone, type DateValue } from "@internationalized/date";
7
+
8
+
let {
9
+
captionLayout,
10
+
months,
11
+
monthFormat,
12
+
years,
13
+
yearFormat,
14
+
month,
15
+
locale,
16
+
placeholder = $bindable(),
17
+
monthIndex = 0,
18
+
}: {
19
+
captionLayout: ComponentProps<typeof Calendar>["captionLayout"];
20
+
months: ComponentProps<typeof CalendarMonthSelect>["months"];
21
+
monthFormat: ComponentProps<typeof CalendarMonthSelect>["monthFormat"];
22
+
years: ComponentProps<typeof CalendarYearSelect>["years"];
23
+
yearFormat: ComponentProps<typeof CalendarYearSelect>["yearFormat"];
24
+
month: DateValue;
25
+
placeholder: DateValue | undefined;
26
+
locale: string;
27
+
monthIndex: number;
28
+
} = $props();
29
+
30
+
function formatYear(date: DateValue) {
31
+
const dateObj = date.toDate(getLocalTimeZone());
32
+
if (typeof yearFormat === "function") return yearFormat(dateObj.getFullYear());
33
+
return new DateFormatter(locale, { year: yearFormat }).format(dateObj);
34
+
}
35
+
36
+
function formatMonth(date: DateValue) {
37
+
const dateObj = date.toDate(getLocalTimeZone());
38
+
if (typeof monthFormat === "function") return monthFormat(dateObj.getMonth() + 1);
39
+
return new DateFormatter(locale, { month: monthFormat }).format(dateObj);
40
+
}
41
+
</script>
42
+
43
+
{#snippet MonthSelect()}
44
+
<CalendarMonthSelect
45
+
{months}
46
+
{monthFormat}
47
+
value={month.month}
48
+
onchange={(e) => {
49
+
if (!placeholder) return;
50
+
const v = Number.parseInt(e.currentTarget.value);
51
+
const newPlaceholder = placeholder.set({ month: v });
52
+
placeholder = newPlaceholder.subtract({ months: monthIndex });
53
+
}}
54
+
/>
55
+
{/snippet}
56
+
57
+
{#snippet YearSelect()}
58
+
<CalendarYearSelect {years} {yearFormat} value={month.year} />
59
+
{/snippet}
60
+
61
+
{#if captionLayout === "dropdown"}
62
+
{@render MonthSelect()}
63
+
{@render YearSelect()}
64
+
{:else if captionLayout === "dropdown-months"}
65
+
{@render MonthSelect()}
66
+
{#if placeholder}
67
+
{formatYear(placeholder)}
68
+
{/if}
69
+
{:else if captionLayout === "dropdown-years"}
70
+
{#if placeholder}
71
+
{formatMonth(placeholder)}
72
+
{/if}
73
+
{@render YearSelect()}
74
+
{:else}
75
+
{formatMonth(month)} {formatYear(month)}
76
+
{/if}
+19
apps/web/src/lib/components/ui/calendar/calendar-cell.svelte
+19
apps/web/src/lib/components/ui/calendar/calendar-cell.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CalendarPrimitive.CellProps = $props();
10
+
</script>
11
+
12
+
<CalendarPrimitive.Cell
13
+
bind:ref
14
+
class={cn(
15
+
"size-(--cell-size) relative p-0 text-center text-sm focus-within:z-20 [&:first-child[data-selected]_[data-bits-day]]:rounded-l-md [&:last-child[data-selected]_[data-bits-day]]:rounded-r-md",
16
+
className
17
+
)}
18
+
{...restProps}
19
+
/>
+35
apps/web/src/lib/components/ui/calendar/calendar-day.svelte
+35
apps/web/src/lib/components/ui/calendar/calendar-day.svelte
···
1
+
<script lang="ts">
2
+
import { buttonVariants } from "$lib/components/ui/button/index.js";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
import { Calendar as CalendarPrimitive } from "bits-ui";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
...restProps
10
+
}: CalendarPrimitive.DayProps = $props();
11
+
</script>
12
+
13
+
<CalendarPrimitive.Day
14
+
bind:ref
15
+
class={cn(
16
+
buttonVariants({ variant: "ghost" }),
17
+
"size-(--cell-size) flex select-none flex-col items-center justify-center gap-1 whitespace-nowrap p-0 font-normal leading-none",
18
+
"[&[data-today]:not([data-selected])]:bg-accent [&[data-today]:not([data-selected])]:text-accent-foreground [&[data-today][data-disabled]]:text-muted-foreground",
19
+
"data-[selected]:bg-primary dark:data-[selected]:hover:bg-accent/50 data-[selected]:text-primary-foreground",
20
+
// Outside months
21
+
"[&[data-outside-month]:not([data-selected])]:text-muted-foreground [&[data-outside-month]:not([data-selected])]:hover:text-accent-foreground",
22
+
// Disabled
23
+
"data-[disabled]:text-muted-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
24
+
// Unavailable
25
+
"data-[unavailable]:text-muted-foreground data-[unavailable]:line-through",
26
+
// hover
27
+
"dark:hover:text-accent-foreground",
28
+
// focus
29
+
"focus:border-ring focus:ring-ring/50 focus:relative",
30
+
// inner spans
31
+
"[&>span]:text-xs [&>span]:opacity-70",
32
+
className
33
+
)}
34
+
{...restProps}
35
+
/>
+12
apps/web/src/lib/components/ui/calendar/calendar-grid-body.svelte
+12
apps/web/src/lib/components/ui/calendar/calendar-grid-body.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CalendarPrimitive.GridBodyProps = $props();
10
+
</script>
11
+
12
+
<CalendarPrimitive.GridBody bind:ref class={cn(className)} {...restProps} />
+12
apps/web/src/lib/components/ui/calendar/calendar-grid-head.svelte
+12
apps/web/src/lib/components/ui/calendar/calendar-grid-head.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CalendarPrimitive.GridHeadProps = $props();
10
+
</script>
11
+
12
+
<CalendarPrimitive.GridHead bind:ref class={cn(className)} {...restProps} />
+12
apps/web/src/lib/components/ui/calendar/calendar-grid-row.svelte
+12
apps/web/src/lib/components/ui/calendar/calendar-grid-row.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CalendarPrimitive.GridRowProps = $props();
10
+
</script>
11
+
12
+
<CalendarPrimitive.GridRow bind:ref class={cn("flex", className)} {...restProps} />
+16
apps/web/src/lib/components/ui/calendar/calendar-grid.svelte
+16
apps/web/src/lib/components/ui/calendar/calendar-grid.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CalendarPrimitive.GridProps = $props();
10
+
</script>
11
+
12
+
<CalendarPrimitive.Grid
13
+
bind:ref
14
+
class={cn("mt-4 flex w-full border-collapse flex-col gap-1", className)}
15
+
{...restProps}
16
+
/>
+19
apps/web/src/lib/components/ui/calendar/calendar-head-cell.svelte
+19
apps/web/src/lib/components/ui/calendar/calendar-head-cell.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CalendarPrimitive.HeadCellProps = $props();
10
+
</script>
11
+
12
+
<CalendarPrimitive.HeadCell
13
+
bind:ref
14
+
class={cn(
15
+
"text-muted-foreground w-(--cell-size) rounded-md text-[0.8rem] font-normal",
16
+
className
17
+
)}
18
+
{...restProps}
19
+
/>
+19
apps/web/src/lib/components/ui/calendar/calendar-header.svelte
+19
apps/web/src/lib/components/ui/calendar/calendar-header.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CalendarPrimitive.HeaderProps = $props();
10
+
</script>
11
+
12
+
<CalendarPrimitive.Header
13
+
bind:ref
14
+
class={cn(
15
+
"h-(--cell-size) flex w-full items-center justify-center gap-1.5 text-sm font-medium",
16
+
className
17
+
)}
18
+
{...restProps}
19
+
/>
+16
apps/web/src/lib/components/ui/calendar/calendar-heading.svelte
+16
apps/web/src/lib/components/ui/calendar/calendar-heading.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CalendarPrimitive.HeadingProps = $props();
10
+
</script>
11
+
12
+
<CalendarPrimitive.Heading
13
+
bind:ref
14
+
class={cn("px-(--cell-size) text-sm font-medium", className)}
15
+
{...restProps}
16
+
/>
+44
apps/web/src/lib/components/ui/calendar/calendar-month-select.svelte
+44
apps/web/src/lib/components/ui/calendar/calendar-month-select.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
4
+
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
value,
10
+
onchange,
11
+
...restProps
12
+
}: WithoutChildrenOrChild<CalendarPrimitive.MonthSelectProps> = $props();
13
+
</script>
14
+
15
+
<span
16
+
class={cn(
17
+
"has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative flex rounded-md border",
18
+
className
19
+
)}
20
+
>
21
+
<CalendarPrimitive.MonthSelect bind:ref class="absolute inset-0 opacity-0" {...restProps}>
22
+
{#snippet child({ props, monthItems, selectedMonthItem })}
23
+
<select {...props} {value} {onchange}>
24
+
{#each monthItems as monthItem (monthItem.value)}
25
+
<option
26
+
value={monthItem.value}
27
+
selected={value !== undefined
28
+
? monthItem.value === value
29
+
: monthItem.value === selectedMonthItem.value}
30
+
>
31
+
{monthItem.label}
32
+
</option>
33
+
{/each}
34
+
</select>
35
+
<span
36
+
class="[&>svg]:text-muted-foreground flex h-8 select-none items-center gap-1 rounded-md pl-2 pr-1 text-sm font-medium [&>svg]:size-3.5"
37
+
aria-hidden="true"
38
+
>
39
+
{monthItems.find((item) => item.value === value)?.label || selectedMonthItem.label}
40
+
<ChevronDownIcon class="size-4" />
41
+
</span>
42
+
{/snippet}
43
+
</CalendarPrimitive.MonthSelect>
44
+
</span>
+15
apps/web/src/lib/components/ui/calendar/calendar-month.svelte
+15
apps/web/src/lib/components/ui/calendar/calendar-month.svelte
···
1
+
<script lang="ts">
2
+
import { type WithElementRef, cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
11
+
</script>
12
+
13
+
<div {...restProps} bind:this={ref} class={cn("flex flex-col", className)}>
14
+
{@render children?.()}
15
+
</div>
+19
apps/web/src/lib/components/ui/calendar/calendar-months.svelte
+19
apps/web/src/lib/components/ui/calendar/calendar-months.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
class={cn("relative flex flex-col gap-4 md:flex-row", className)}
16
+
{...restProps}
17
+
>
18
+
{@render children?.()}
19
+
</div>
+43
apps/web/src/lib/components/ui/calendar/calendar-year-select.svelte
+43
apps/web/src/lib/components/ui/calendar/calendar-year-select.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
4
+
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
value,
10
+
...restProps
11
+
}: WithoutChildrenOrChild<CalendarPrimitive.YearSelectProps> = $props();
12
+
</script>
13
+
14
+
<span
15
+
class={cn(
16
+
"has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative flex rounded-md border",
17
+
className
18
+
)}
19
+
>
20
+
<CalendarPrimitive.YearSelect bind:ref class="absolute inset-0 opacity-0" {...restProps}>
21
+
{#snippet child({ props, yearItems, selectedYearItem })}
22
+
<select {...props} {value}>
23
+
{#each yearItems as yearItem (yearItem.value)}
24
+
<option
25
+
value={yearItem.value}
26
+
selected={value !== undefined
27
+
? yearItem.value === value
28
+
: yearItem.value === selectedYearItem.value}
29
+
>
30
+
{yearItem.label}
31
+
</option>
32
+
{/each}
33
+
</select>
34
+
<span
35
+
class="[&>svg]:text-muted-foreground flex h-8 select-none items-center gap-1 rounded-md pl-2 pr-1 text-sm font-medium [&>svg]:size-3.5"
36
+
aria-hidden="true"
37
+
>
38
+
{yearItems.find((item) => item.value === value)?.label || selectedYearItem.label}
39
+
<ChevronDownIcon class="size-4" />
40
+
</span>
41
+
{/snippet}
42
+
</CalendarPrimitive.YearSelect>
43
+
</span>
+115
apps/web/src/lib/components/ui/calendar/calendar.svelte
+115
apps/web/src/lib/components/ui/calendar/calendar.svelte
···
1
+
<script lang="ts">
2
+
import { Calendar as CalendarPrimitive } from "bits-ui";
3
+
import * as Calendar from "./index.js";
4
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
5
+
import type { ButtonVariant } from "../button/button.svelte";
6
+
import { isEqualMonth, type DateValue } from "@internationalized/date";
7
+
import type { Snippet } from "svelte";
8
+
9
+
let {
10
+
ref = $bindable(null),
11
+
value = $bindable(),
12
+
placeholder = $bindable(),
13
+
class: className,
14
+
weekdayFormat = "short",
15
+
buttonVariant = "ghost",
16
+
captionLayout = "label",
17
+
locale = "en-US",
18
+
months: monthsProp,
19
+
years,
20
+
monthFormat: monthFormatProp,
21
+
yearFormat = "numeric",
22
+
day,
23
+
disableDaysOutsideMonth = false,
24
+
...restProps
25
+
}: WithoutChildrenOrChild<CalendarPrimitive.RootProps> & {
26
+
buttonVariant?: ButtonVariant;
27
+
captionLayout?: "dropdown" | "dropdown-months" | "dropdown-years" | "label";
28
+
months?: CalendarPrimitive.MonthSelectProps["months"];
29
+
years?: CalendarPrimitive.YearSelectProps["years"];
30
+
monthFormat?: CalendarPrimitive.MonthSelectProps["monthFormat"];
31
+
yearFormat?: CalendarPrimitive.YearSelectProps["yearFormat"];
32
+
day?: Snippet<[{ day: DateValue; outsideMonth: boolean }]>;
33
+
} = $props();
34
+
35
+
const monthFormat = $derived.by(() => {
36
+
if (monthFormatProp) return monthFormatProp;
37
+
if (captionLayout.startsWith("dropdown")) return "short";
38
+
return "long";
39
+
});
40
+
</script>
41
+
42
+
<!--
43
+
Discriminated Unions + Destructing (required for bindable) do not
44
+
get along, so we shut typescript up by casting `value` to `never`.
45
+
-->
46
+
<CalendarPrimitive.Root
47
+
bind:value={value as never}
48
+
bind:ref
49
+
bind:placeholder
50
+
{weekdayFormat}
51
+
{disableDaysOutsideMonth}
52
+
class={cn(
53
+
"bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
54
+
className
55
+
)}
56
+
{locale}
57
+
{monthFormat}
58
+
{yearFormat}
59
+
{...restProps}
60
+
>
61
+
{#snippet children({ months, weekdays })}
62
+
<Calendar.Months>
63
+
<Calendar.Nav>
64
+
<Calendar.PrevButton variant={buttonVariant} />
65
+
<Calendar.NextButton variant={buttonVariant} />
66
+
</Calendar.Nav>
67
+
{#each months as month, monthIndex (month)}
68
+
<Calendar.Month>
69
+
<Calendar.Header>
70
+
<Calendar.Caption
71
+
{captionLayout}
72
+
months={monthsProp}
73
+
{monthFormat}
74
+
{years}
75
+
{yearFormat}
76
+
month={month.value}
77
+
bind:placeholder
78
+
{locale}
79
+
{monthIndex}
80
+
/>
81
+
</Calendar.Header>
82
+
<Calendar.Grid>
83
+
<Calendar.GridHead>
84
+
<Calendar.GridRow class="select-none">
85
+
{#each weekdays as weekday (weekday)}
86
+
<Calendar.HeadCell>
87
+
{weekday.slice(0, 2)}
88
+
</Calendar.HeadCell>
89
+
{/each}
90
+
</Calendar.GridRow>
91
+
</Calendar.GridHead>
92
+
<Calendar.GridBody>
93
+
{#each month.weeks as weekDates (weekDates)}
94
+
<Calendar.GridRow class="mt-2 w-full">
95
+
{#each weekDates as date (date)}
96
+
<Calendar.Cell {date} month={month.value}>
97
+
{#if day}
98
+
{@render day({
99
+
day: date,
100
+
outsideMonth: !isEqualMonth(date, month.value),
101
+
})}
102
+
{:else}
103
+
<Calendar.Day />
104
+
{/if}
105
+
</Calendar.Cell>
106
+
{/each}
107
+
</Calendar.GridRow>
108
+
{/each}
109
+
</Calendar.GridBody>
110
+
</Calendar.Grid>
111
+
</Calendar.Month>
112
+
{/each}
113
+
</Calendar.Months>
114
+
{/snippet}
115
+
</CalendarPrimitive.Root>
+40
apps/web/src/lib/components/ui/calendar/index.ts
+40
apps/web/src/lib/components/ui/calendar/index.ts
···
1
+
import Root from "./calendar.svelte";
2
+
import Cell from "./calendar-cell.svelte";
3
+
import Day from "./calendar-day.svelte";
4
+
import Grid from "./calendar-grid.svelte";
5
+
import Header from "./calendar-header.svelte";
6
+
import Months from "./calendar-months.svelte";
7
+
import GridRow from "./calendar-grid-row.svelte";
8
+
import Heading from "./calendar-heading.svelte";
9
+
import GridBody from "./calendar-grid-body.svelte";
10
+
import GridHead from "./calendar-grid-head.svelte";
11
+
import HeadCell from "./calendar-head-cell.svelte";
12
+
import NextButton from "./calendar-next-button.svelte";
13
+
import PrevButton from "./calendar-prev-button.svelte";
14
+
import MonthSelect from "./calendar-month-select.svelte";
15
+
import YearSelect from "./calendar-year-select.svelte";
16
+
import Month from "./calendar-month.svelte";
17
+
import Nav from "./calendar-nav.svelte";
18
+
import Caption from "./calendar-caption.svelte";
19
+
20
+
export {
21
+
Day,
22
+
Cell,
23
+
Grid,
24
+
Header,
25
+
Months,
26
+
GridRow,
27
+
Heading,
28
+
GridBody,
29
+
GridHead,
30
+
HeadCell,
31
+
NextButton,
32
+
PrevButton,
33
+
Nav,
34
+
Month,
35
+
YearSelect,
36
+
MonthSelect,
37
+
Caption,
38
+
//
39
+
Root as Calendar,
40
+
};
+20
apps/web/src/lib/components/ui/card/card-action.svelte
+20
apps/web/src/lib/components/ui/card/card-action.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="card-action"
16
+
class={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+15
apps/web/src/lib/components/ui/card/card-content.svelte
+15
apps/web/src/lib/components/ui/card/card-content.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div bind:this={ref} data-slot="card-content" class={cn("px-6", className)} {...restProps}>
14
+
{@render children?.()}
15
+
</div>
+20
apps/web/src/lib/components/ui/card/card-description.svelte
+20
apps/web/src/lib/components/ui/card/card-description.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
11
+
</script>
12
+
13
+
<p
14
+
bind:this={ref}
15
+
data-slot="card-description"
16
+
class={cn("text-muted-foreground text-sm", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</p>
+23
apps/web/src/lib/components/ui/card/card-header.svelte
+23
apps/web/src/lib/components/ui/card/card-header.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="card-header"
16
+
class={cn(
17
+
"@container/card-header has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6 grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
>
22
+
{@render children?.()}
23
+
</div>
+20
apps/web/src/lib/components/ui/card/card-title.svelte
+20
apps/web/src/lib/components/ui/card/card-title.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="card-title"
16
+
class={cn("font-semibold leading-none", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+23
apps/web/src/lib/components/ui/card/card.svelte
+23
apps/web/src/lib/components/ui/card/card.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="card"
16
+
class={cn(
17
+
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
>
22
+
{@render children?.()}
23
+
</div>
+25
apps/web/src/lib/components/ui/card/index.ts
+25
apps/web/src/lib/components/ui/card/index.ts
···
1
+
import Root from "./card.svelte";
2
+
import Content from "./card-content.svelte";
3
+
import Description from "./card-description.svelte";
4
+
import Footer from "./card-footer.svelte";
5
+
import Header from "./card-header.svelte";
6
+
import Title from "./card-title.svelte";
7
+
import Action from "./card-action.svelte";
8
+
9
+
export {
10
+
Root,
11
+
Content,
12
+
Description,
13
+
Footer,
14
+
Header,
15
+
Title,
16
+
Action,
17
+
//
18
+
Root as Card,
19
+
Content as CardContent,
20
+
Description as CardDescription,
21
+
Footer as CardFooter,
22
+
Header as CardHeader,
23
+
Title as CardTitle,
24
+
Action as CardAction,
25
+
};
+43
apps/web/src/lib/components/ui/carousel/carousel-content.svelte
+43
apps/web/src/lib/components/ui/carousel/carousel-content.svelte
···
1
+
<script lang="ts">
2
+
import emblaCarouselSvelte from "embla-carousel-svelte";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
import { getEmblaContext } from "./context.js";
5
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
6
+
7
+
let {
8
+
ref = $bindable(null),
9
+
class: className,
10
+
children,
11
+
...restProps
12
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
13
+
14
+
const emblaCtx = getEmblaContext("<Carousel.Content/>");
15
+
</script>
16
+
17
+
<div
18
+
data-slot="carousel-content"
19
+
class="overflow-hidden"
20
+
use:emblaCarouselSvelte={{
21
+
options: {
22
+
container: "[data-embla-container]",
23
+
slides: "[data-embla-slide]",
24
+
...emblaCtx.options,
25
+
axis: emblaCtx.orientation === "horizontal" ? "x" : "y",
26
+
},
27
+
plugins: emblaCtx.plugins,
28
+
}}
29
+
onemblaInit={emblaCtx.onInit}
30
+
>
31
+
<div
32
+
bind:this={ref}
33
+
class={cn(
34
+
"flex",
35
+
emblaCtx.orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
36
+
className
37
+
)}
38
+
data-embla-container=""
39
+
{...restProps}
40
+
>
41
+
{@render children?.()}
42
+
</div>
43
+
</div>
+30
apps/web/src/lib/components/ui/carousel/carousel-item.svelte
+30
apps/web/src/lib/components/ui/carousel/carousel-item.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { getEmblaContext } from "./context.js";
4
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
children,
10
+
...restProps
11
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
12
+
13
+
const emblaCtx = getEmblaContext("<Carousel.Item/>");
14
+
</script>
15
+
16
+
<div
17
+
bind:this={ref}
18
+
data-slot="carousel-item"
19
+
role="group"
20
+
aria-roledescription="slide"
21
+
class={cn(
22
+
"min-w-0 shrink-0 grow-0 basis-full",
23
+
emblaCtx.orientation === "horizontal" ? "pl-4" : "pt-4",
24
+
className
25
+
)}
26
+
data-embla-slide=""
27
+
{...restProps}
28
+
>
29
+
{@render children?.()}
30
+
</div>
+38
apps/web/src/lib/components/ui/carousel/carousel-next.svelte
+38
apps/web/src/lib/components/ui/carousel/carousel-next.svelte
···
1
+
<script lang="ts">
2
+
import ArrowRightIcon from "@lucide/svelte/icons/arrow-right";
3
+
import type { WithoutChildren } from "bits-ui";
4
+
import { getEmblaContext } from "./context.js";
5
+
import { cn } from "$lib/utils/cn.js";
6
+
import { Button, type Props } from "$lib/components/ui/button/index.js";
7
+
8
+
let {
9
+
ref = $bindable(null),
10
+
class: className,
11
+
variant = "outline",
12
+
size = "icon",
13
+
...restProps
14
+
}: WithoutChildren<Props> = $props();
15
+
16
+
const emblaCtx = getEmblaContext("<Carousel.Next/>");
17
+
</script>
18
+
19
+
<Button
20
+
data-slot="carousel-next"
21
+
{variant}
22
+
{size}
23
+
aria-disabled={!emblaCtx.canScrollNext}
24
+
class={cn(
25
+
"absolute size-8 rounded-full",
26
+
emblaCtx.orientation === "horizontal"
27
+
? "-right-12 top-1/2 -translate-y-1/2"
28
+
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
29
+
className
30
+
)}
31
+
onclick={emblaCtx.scrollNext}
32
+
onkeydown={emblaCtx.handleKeyDown}
33
+
bind:ref
34
+
{...restProps}
35
+
>
36
+
<ArrowRightIcon class="size-4" />
37
+
<span class="sr-only">Next slide</span>
38
+
</Button>
+38
apps/web/src/lib/components/ui/carousel/carousel-previous.svelte
+38
apps/web/src/lib/components/ui/carousel/carousel-previous.svelte
···
1
+
<script lang="ts">
2
+
import ArrowLeftIcon from "@lucide/svelte/icons/arrow-left";
3
+
import type { WithoutChildren } from "bits-ui";
4
+
import { getEmblaContext } from "./context.js";
5
+
import { cn } from "$lib/utils/cn.js";
6
+
import { Button, type Props } from "$lib/components/ui/button/index.js";
7
+
8
+
let {
9
+
ref = $bindable(null),
10
+
class: className,
11
+
variant = "outline",
12
+
size = "icon",
13
+
...restProps
14
+
}: WithoutChildren<Props> = $props();
15
+
16
+
const emblaCtx = getEmblaContext("<Carousel.Previous/>");
17
+
</script>
18
+
19
+
<Button
20
+
data-slot="carousel-previous"
21
+
{variant}
22
+
{size}
23
+
aria-disabled={!emblaCtx.canScrollPrev}
24
+
class={cn(
25
+
"absolute size-8 rounded-full",
26
+
emblaCtx.orientation === "horizontal"
27
+
? "-left-12 top-1/2 -translate-y-1/2"
28
+
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
29
+
className
30
+
)}
31
+
onclick={emblaCtx.scrollPrev}
32
+
onkeydown={emblaCtx.handleKeyDown}
33
+
{...restProps}
34
+
bind:ref
35
+
>
36
+
<ArrowLeftIcon class="size-4" />
37
+
<span class="sr-only">Previous slide</span>
38
+
</Button>
+93
apps/web/src/lib/components/ui/carousel/carousel.svelte
+93
apps/web/src/lib/components/ui/carousel/carousel.svelte
···
1
+
<script lang="ts">
2
+
import {
3
+
type CarouselAPI,
4
+
type CarouselProps,
5
+
type EmblaContext,
6
+
setEmblaContext,
7
+
} from "./context.js";
8
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
9
+
10
+
let {
11
+
ref = $bindable(null),
12
+
opts = {},
13
+
plugins = [],
14
+
setApi = () => {},
15
+
orientation = "horizontal",
16
+
class: className,
17
+
children,
18
+
...restProps
19
+
}: WithElementRef<CarouselProps> = $props();
20
+
21
+
let carouselState = $state<EmblaContext>({
22
+
api: undefined,
23
+
scrollPrev,
24
+
scrollNext,
25
+
orientation,
26
+
canScrollNext: false,
27
+
canScrollPrev: false,
28
+
handleKeyDown,
29
+
options: opts,
30
+
plugins,
31
+
onInit,
32
+
scrollSnaps: [],
33
+
selectedIndex: 0,
34
+
scrollTo,
35
+
});
36
+
37
+
setEmblaContext(carouselState);
38
+
39
+
function scrollPrev() {
40
+
carouselState.api?.scrollPrev();
41
+
}
42
+
43
+
function scrollNext() {
44
+
carouselState.api?.scrollNext();
45
+
}
46
+
47
+
function scrollTo(index: number, jump?: boolean) {
48
+
carouselState.api?.scrollTo(index, jump);
49
+
}
50
+
51
+
function onSelect() {
52
+
if (!carouselState.api) return;
53
+
carouselState.selectedIndex = carouselState.api.selectedScrollSnap();
54
+
carouselState.canScrollNext = carouselState.api.canScrollNext();
55
+
carouselState.canScrollPrev = carouselState.api.canScrollPrev();
56
+
}
57
+
58
+
function handleKeyDown(e: KeyboardEvent) {
59
+
if (e.key === "ArrowLeft") {
60
+
e.preventDefault();
61
+
scrollPrev();
62
+
} else if (e.key === "ArrowRight") {
63
+
e.preventDefault();
64
+
scrollNext();
65
+
}
66
+
}
67
+
68
+
function onInit(event: CustomEvent<CarouselAPI>) {
69
+
carouselState.api = event.detail;
70
+
setApi(carouselState.api);
71
+
72
+
carouselState.scrollSnaps = carouselState.api.scrollSnapList();
73
+
carouselState.api.on("select", onSelect);
74
+
onSelect();
75
+
}
76
+
77
+
$effect(() => {
78
+
return () => {
79
+
carouselState.api?.off("select", onSelect);
80
+
};
81
+
});
82
+
</script>
83
+
84
+
<div
85
+
bind:this={ref}
86
+
data-slot="carousel"
87
+
class={cn("relative", className)}
88
+
role="region"
89
+
aria-roledescription="carousel"
90
+
{...restProps}
91
+
>
92
+
{@render children?.()}
93
+
</div>
+58
apps/web/src/lib/components/ui/carousel/context.ts
+58
apps/web/src/lib/components/ui/carousel/context.ts
···
1
+
import type { WithElementRef } from "$lib/utils/cn.js";
2
+
import type {
3
+
EmblaCarouselSvelteType,
4
+
default as emblaCarouselSvelte,
5
+
} from "embla-carousel-svelte";
6
+
import { getContext, hasContext, setContext } from "svelte";
7
+
import type { HTMLAttributes } from "svelte/elements";
8
+
9
+
export type CarouselAPI =
10
+
NonNullable<NonNullable<EmblaCarouselSvelteType["$$_attributes"]>["on:emblaInit"]> extends (
11
+
evt: CustomEvent<infer CarouselAPI>
12
+
) => void
13
+
? CarouselAPI
14
+
: never;
15
+
16
+
type EmblaCarouselConfig = NonNullable<Parameters<typeof emblaCarouselSvelte>[1]>;
17
+
18
+
export type CarouselOptions = EmblaCarouselConfig["options"];
19
+
export type CarouselPlugins = EmblaCarouselConfig["plugins"];
20
+
21
+
////
22
+
23
+
export type CarouselProps = {
24
+
opts?: CarouselOptions;
25
+
plugins?: CarouselPlugins;
26
+
setApi?: (api: CarouselAPI | undefined) => void;
27
+
orientation?: "horizontal" | "vertical";
28
+
} & WithElementRef<HTMLAttributes<HTMLDivElement>>;
29
+
30
+
const EMBLA_CAROUSEL_CONTEXT = Symbol("EMBLA_CAROUSEL_CONTEXT");
31
+
32
+
export type EmblaContext = {
33
+
api: CarouselAPI | undefined;
34
+
orientation: "horizontal" | "vertical";
35
+
scrollNext: () => void;
36
+
scrollPrev: () => void;
37
+
canScrollNext: boolean;
38
+
canScrollPrev: boolean;
39
+
handleKeyDown: (e: KeyboardEvent) => void;
40
+
options: CarouselOptions;
41
+
plugins: CarouselPlugins;
42
+
onInit: (e: CustomEvent<CarouselAPI>) => void;
43
+
scrollTo: (index: number, jump?: boolean) => void;
44
+
scrollSnaps: number[];
45
+
selectedIndex: number;
46
+
};
47
+
48
+
export function setEmblaContext(config: EmblaContext): EmblaContext {
49
+
setContext(EMBLA_CAROUSEL_CONTEXT, config);
50
+
return config;
51
+
}
52
+
53
+
export function getEmblaContext(name = "This component") {
54
+
if (!hasContext(EMBLA_CAROUSEL_CONTEXT)) {
55
+
throw new Error(`${name} must be used within a <Carousel.Root> component`);
56
+
}
57
+
return getContext<ReturnType<typeof setEmblaContext>>(EMBLA_CAROUSEL_CONTEXT);
58
+
}
+19
apps/web/src/lib/components/ui/carousel/index.ts
+19
apps/web/src/lib/components/ui/carousel/index.ts
···
1
+
import Root from "./carousel.svelte";
2
+
import Content from "./carousel-content.svelte";
3
+
import Item from "./carousel-item.svelte";
4
+
import Previous from "./carousel-previous.svelte";
5
+
import Next from "./carousel-next.svelte";
6
+
7
+
export {
8
+
Root,
9
+
Content,
10
+
Item,
11
+
Previous,
12
+
Next,
13
+
//
14
+
Root as Carousel,
15
+
Content as CarouselContent,
16
+
Item as CarouselItem,
17
+
Previous as CarouselPrevious,
18
+
Next as CarouselNext,
19
+
};
+80
apps/web/src/lib/components/ui/chart/chart-container.svelte
+80
apps/web/src/lib/components/ui/chart/chart-container.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
import ChartStyle from "./chart-style.svelte";
5
+
import { setChartContext, type ChartConfig } from "./chart-utils.js";
6
+
7
+
const uid = $props.id();
8
+
9
+
let {
10
+
ref = $bindable(null),
11
+
id = uid,
12
+
class: className,
13
+
children,
14
+
config,
15
+
...restProps
16
+
}: WithElementRef<HTMLAttributes<HTMLElement>> & {
17
+
config: ChartConfig;
18
+
} = $props();
19
+
20
+
const chartId = `chart-${id || uid.replace(/:/g, "")}`;
21
+
22
+
setChartContext({
23
+
get config() {
24
+
return config;
25
+
},
26
+
});
27
+
</script>
28
+
29
+
<div
30
+
bind:this={ref}
31
+
data-chart={chartId}
32
+
data-slot="chart"
33
+
class={cn(
34
+
"flex aspect-video justify-center overflow-visible text-xs",
35
+
// Overrides
36
+
//
37
+
// Stroke around dots/marks when hovering
38
+
"[&_.stroke-white]:stroke-transparent",
39
+
// override the default stroke color of lines
40
+
"[&_.lc-line]:stroke-border/50",
41
+
42
+
// by default, layerchart shows a line intersecting the point when hovering, this hides that
43
+
"[&_.lc-highlight-line]:stroke-0",
44
+
45
+
// by default, when you hover a point on a stacked series chart, it will drop the opacity
46
+
// of the other series, this overrides that
47
+
"[&_.lc-area-path]:opacity-100 [&_.lc-highlight-line]:opacity-100 [&_.lc-highlight-point]:opacity-100 [&_.lc-spline-path]:opacity-100 [&_.lc-text-svg]:overflow-visible [&_.lc-text]:text-xs",
48
+
49
+
// We don't want the little tick lines between the axis labels and the chart, so we remove
50
+
// the stroke. The alternative is to manually disable `tickMarks` on the x/y axis of every
51
+
// chart.
52
+
"[&_.lc-axis-tick]:stroke-0",
53
+
54
+
// We don't want to display the rule on the x/y axis, as there is already going to be
55
+
// a grid line there and rule ends up overlapping the marks because it is rendered after
56
+
// the marks
57
+
"[&_.lc-rule-x-line:not(.lc-grid-x-rule)]:stroke-0 [&_.lc-rule-y-line:not(.lc-grid-y-rule)]:stroke-0",
58
+
"[&_.lc-grid-x-radial-line]:stroke-border [&_.lc-grid-x-radial-circle]:stroke-border",
59
+
"[&_.lc-grid-y-radial-line]:stroke-border [&_.lc-grid-y-radial-circle]:stroke-border",
60
+
61
+
// Legend adjustments
62
+
"[&_.lc-legend-swatch-button]:items-center [&_.lc-legend-swatch-button]:gap-1.5",
63
+
"[&_.lc-legend-swatch-group]:items-center [&_.lc-legend-swatch-group]:gap-4",
64
+
"[&_.lc-legend-swatch]:size-2.5 [&_.lc-legend-swatch]:rounded-[2px]",
65
+
66
+
// Labels
67
+
"[&_.lc-labels-text:not([fill])]:fill-foreground [&_text]:stroke-transparent",
68
+
69
+
// Tick labels on th x/y axes
70
+
"[&_.lc-axis-tick-label]:fill-muted-foreground [&_.lc-axis-tick-label]:font-normal",
71
+
"[&_.lc-tooltip-rects-g]:fill-transparent",
72
+
"[&_.lc-layout-svg-g]:fill-transparent",
73
+
"[&_.lc-root-container]:w-full",
74
+
className
75
+
)}
76
+
{...restProps}
77
+
>
78
+
<ChartStyle id={chartId} {config} />
79
+
{@render children?.()}
80
+
</div>
+37
apps/web/src/lib/components/ui/chart/chart-style.svelte
+37
apps/web/src/lib/components/ui/chart/chart-style.svelte
···
1
+
<script lang="ts">
2
+
import { THEMES, type ChartConfig } from "./chart-utils.js";
3
+
4
+
let { id, config }: { id: string; config: ChartConfig } = $props();
5
+
6
+
const colorConfig = $derived(
7
+
config ? Object.entries(config).filter(([, config]) => config.theme || config.color) : null
8
+
);
9
+
10
+
const themeContents = $derived.by(() => {
11
+
if (!colorConfig || !colorConfig.length) return;
12
+
13
+
const themeContents = [];
14
+
for (let [_theme, prefix] of Object.entries(THEMES)) {
15
+
let content = `${prefix} [data-chart=${id}] {\n`;
16
+
const color = colorConfig.map(([key, itemConfig]) => {
17
+
const theme = _theme as keyof typeof itemConfig.theme;
18
+
const color = itemConfig.theme?.[theme] || itemConfig.color;
19
+
return color ? `\t--color-${key}: ${color};` : null;
20
+
});
21
+
22
+
content += color.join("\n") + "\n}";
23
+
24
+
themeContents.push(content);
25
+
}
26
+
27
+
return themeContents.join("\n");
28
+
});
29
+
</script>
30
+
31
+
{#if themeContents}
32
+
{#key id}
33
+
<svelte:element this={"style"}>
34
+
{themeContents}
35
+
</svelte:element>
36
+
{/key}
37
+
{/if}
+159
apps/web/src/lib/components/ui/chart/chart-tooltip.svelte
+159
apps/web/src/lib/components/ui/chart/chart-tooltip.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
import { getPayloadConfigFromPayload, useChart, type TooltipPayload } from "./chart-utils.js";
5
+
import { getTooltipContext, Tooltip as TooltipPrimitive } from "layerchart";
6
+
import type { Snippet } from "svelte";
7
+
8
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+
function defaultFormatter(value: any, _payload: TooltipPayload[]) {
10
+
return `${value}`;
11
+
}
12
+
13
+
let {
14
+
ref = $bindable(null),
15
+
class: className,
16
+
hideLabel = false,
17
+
indicator = "dot",
18
+
hideIndicator = false,
19
+
labelKey,
20
+
label,
21
+
labelFormatter = defaultFormatter,
22
+
labelClassName,
23
+
formatter,
24
+
nameKey,
25
+
color,
26
+
...restProps
27
+
}: WithoutChildren<WithElementRef<HTMLAttributes<HTMLDivElement>>> & {
28
+
hideLabel?: boolean;
29
+
label?: string;
30
+
indicator?: "line" | "dot" | "dashed";
31
+
nameKey?: string;
32
+
labelKey?: string;
33
+
hideIndicator?: boolean;
34
+
labelClassName?: string;
35
+
labelFormatter?: // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+
((value: any, payload: TooltipPayload[]) => string | number | Snippet) | null;
37
+
formatter?: Snippet<
38
+
[
39
+
{
40
+
value: unknown;
41
+
name: string;
42
+
item: TooltipPayload;
43
+
index: number;
44
+
payload: TooltipPayload[];
45
+
},
46
+
]
47
+
>;
48
+
} = $props();
49
+
50
+
const chart = useChart();
51
+
const tooltipCtx = getTooltipContext();
52
+
53
+
const formattedLabel = $derived.by(() => {
54
+
if (hideLabel || !tooltipCtx.payload?.length) return null;
55
+
56
+
const [item] = tooltipCtx.payload;
57
+
const key = labelKey ?? item?.label ?? item?.name ?? "value";
58
+
59
+
const itemConfig = getPayloadConfigFromPayload(chart.config, item, key);
60
+
61
+
const value =
62
+
!labelKey && typeof label === "string"
63
+
? (chart.config[label as keyof typeof chart.config]?.label ?? label)
64
+
: (itemConfig?.label ?? item.label);
65
+
66
+
if (value === undefined) return null;
67
+
if (!labelFormatter) return value;
68
+
return labelFormatter(value, tooltipCtx.payload);
69
+
});
70
+
71
+
const nestLabel = $derived(tooltipCtx.payload.length === 1 && indicator !== "dot");
72
+
</script>
73
+
74
+
{#snippet TooltipLabel()}
75
+
{#if formattedLabel}
76
+
<div class={cn("font-medium", labelClassName)}>
77
+
{#if typeof formattedLabel === "function"}
78
+
{@render formattedLabel()}
79
+
{:else}
80
+
{formattedLabel}
81
+
{/if}
82
+
</div>
83
+
{/if}
84
+
{/snippet}
85
+
86
+
<TooltipPrimitive.Root variant="none">
87
+
<div
88
+
class={cn(
89
+
"border-border/50 bg-background grid min-w-[9rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl",
90
+
className
91
+
)}
92
+
{...restProps}
93
+
>
94
+
{#if !nestLabel}
95
+
{@render TooltipLabel()}
96
+
{/if}
97
+
<div class="grid gap-1.5">
98
+
{#each tooltipCtx.payload as item, i (item.key + i)}
99
+
{@const key = `${nameKey || item.key || item.name || "value"}`}
100
+
{@const itemConfig = getPayloadConfigFromPayload(chart.config, item, key)}
101
+
{@const indicatorColor = color || item.payload?.color || item.color}
102
+
<div
103
+
class={cn(
104
+
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:size-2.5",
105
+
indicator === "dot" && "items-center"
106
+
)}
107
+
>
108
+
{#if formatter && item.value !== undefined && item.name}
109
+
{@render formatter({
110
+
value: item.value,
111
+
name: item.name,
112
+
item,
113
+
index: i,
114
+
payload: tooltipCtx.payload,
115
+
})}
116
+
{:else}
117
+
{#if itemConfig?.icon}
118
+
<itemConfig.icon />
119
+
{:else if !hideIndicator}
120
+
<div
121
+
style="--color-bg: {indicatorColor}; --color-border: {indicatorColor};"
122
+
class={cn(
123
+
"border-(--color-border) bg-(--color-bg) shrink-0 rounded-[2px]",
124
+
{
125
+
"size-2.5": indicator === "dot",
126
+
"h-full w-1": indicator === "line",
127
+
"w-0 border-[1.5px] border-dashed bg-transparent":
128
+
indicator === "dashed",
129
+
"my-0.5": nestLabel && indicator === "dashed",
130
+
}
131
+
)}
132
+
></div>
133
+
{/if}
134
+
<div
135
+
class={cn(
136
+
"flex flex-1 shrink-0 justify-between leading-none",
137
+
nestLabel ? "items-end" : "items-center"
138
+
)}
139
+
>
140
+
<div class="grid gap-1.5">
141
+
{#if nestLabel}
142
+
{@render TooltipLabel()}
143
+
{/if}
144
+
<span class="text-muted-foreground">
145
+
{itemConfig?.label || item.name}
146
+
</span>
147
+
</div>
148
+
{#if item.value !== undefined}
149
+
<span class="text-foreground font-mono font-medium tabular-nums">
150
+
{item.value.toLocaleString()}
151
+
</span>
152
+
{/if}
153
+
</div>
154
+
{/if}
155
+
</div>
156
+
{/each}
157
+
</div>
158
+
</div>
159
+
</TooltipPrimitive.Root>
+66
apps/web/src/lib/components/ui/chart/chart-utils.ts
+66
apps/web/src/lib/components/ui/chart/chart-utils.ts
···
1
+
import type { Tooltip } from "layerchart";
2
+
import { getContext, setContext, type Component, type ComponentProps, type Snippet } from "svelte";
3
+
4
+
export const THEMES = { light: "", dark: ".dark" } as const;
5
+
6
+
export type ChartConfig = {
7
+
[k in string]: {
8
+
label?: string;
9
+
icon?: Component;
10
+
} & (
11
+
| { color?: string; theme?: never }
12
+
| { color?: never; theme: Record<keyof typeof THEMES, string> }
13
+
);
14
+
};
15
+
16
+
export type ExtractSnippetParams<T> = T extends Snippet<[infer P]> ? P : never;
17
+
18
+
export type TooltipPayload = ExtractSnippetParams<
19
+
ComponentProps<typeof Tooltip.Root>["children"]
20
+
>["payload"][number];
21
+
22
+
// Helper to extract item config from a payload.
23
+
export function getPayloadConfigFromPayload(
24
+
config: ChartConfig,
25
+
payload: TooltipPayload,
26
+
key: string
27
+
) {
28
+
if (typeof payload !== "object" || payload === null) return undefined;
29
+
30
+
const payloadPayload =
31
+
"payload" in payload && typeof payload.payload === "object" && payload.payload !== null
32
+
? payload.payload
33
+
: undefined;
34
+
35
+
let configLabelKey: string = key;
36
+
37
+
if (payload.key === key) {
38
+
configLabelKey = payload.key;
39
+
} else if (payload.name === key) {
40
+
configLabelKey = payload.name;
41
+
} else if (key in payload && typeof payload[key as keyof typeof payload] === "string") {
42
+
configLabelKey = payload[key as keyof typeof payload] as string;
43
+
} else if (
44
+
payloadPayload !== undefined &&
45
+
key in payloadPayload &&
46
+
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
47
+
) {
48
+
configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;
49
+
}
50
+
51
+
return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];
52
+
}
53
+
54
+
type ChartContextValue = {
55
+
config: ChartConfig;
56
+
};
57
+
58
+
const chartContextKey = Symbol("chart-context");
59
+
60
+
export function setChartContext(value: ChartContextValue) {
61
+
return setContext(chartContextKey, value);
62
+
}
63
+
64
+
export function useChart() {
65
+
return getContext<ChartContextValue>(chartContextKey);
66
+
}
+6
apps/web/src/lib/components/ui/chart/index.ts
+6
apps/web/src/lib/components/ui/chart/index.ts
···
1
+
import ChartContainer from "./chart-container.svelte";
2
+
import ChartTooltip from "./chart-tooltip.svelte";
3
+
4
+
export { getPayloadConfigFromPayload, type ChartConfig } from "./chart-utils.js";
5
+
6
+
export { ChartContainer, ChartTooltip, ChartContainer as Container, ChartTooltip as Tooltip };
+36
apps/web/src/lib/components/ui/checkbox/checkbox.svelte
+36
apps/web/src/lib/components/ui/checkbox/checkbox.svelte
···
1
+
<script lang="ts">
2
+
import { Checkbox as CheckboxPrimitive } from "bits-ui";
3
+
import CheckIcon from "@lucide/svelte/icons/check";
4
+
import MinusIcon from "@lucide/svelte/icons/minus";
5
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
6
+
7
+
let {
8
+
ref = $bindable(null),
9
+
checked = $bindable(false),
10
+
indeterminate = $bindable(false),
11
+
class: className,
12
+
...restProps
13
+
}: WithoutChildrenOrChild<CheckboxPrimitive.RootProps> = $props();
14
+
</script>
15
+
16
+
<CheckboxPrimitive.Root
17
+
bind:ref
18
+
data-slot="checkbox"
19
+
class={cn(
20
+
"border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive shadow-xs peer flex size-4 shrink-0 items-center justify-center rounded-[4px] border outline-none transition-shadow focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
21
+
className
22
+
)}
23
+
bind:checked
24
+
bind:indeterminate
25
+
{...restProps}
26
+
>
27
+
{#snippet children({ checked, indeterminate })}
28
+
<div data-slot="checkbox-indicator" class="text-current transition-none">
29
+
{#if checked}
30
+
<CheckIcon class="size-3.5" />
31
+
{:else if indeterminate}
32
+
<MinusIcon class="size-3.5" />
33
+
{/if}
34
+
</div>
35
+
{/snippet}
36
+
</CheckboxPrimitive.Root>
+6
apps/web/src/lib/components/ui/checkbox/index.ts
+6
apps/web/src/lib/components/ui/checkbox/index.ts
+7
apps/web/src/lib/components/ui/collapsible/collapsible-content.svelte
+7
apps/web/src/lib/components/ui/collapsible/collapsible-content.svelte
···
1
+
<script lang="ts">
2
+
import { Collapsible as CollapsiblePrimitive } from "bits-ui";
3
+
4
+
let { ref = $bindable(null), ...restProps }: CollapsiblePrimitive.ContentProps = $props();
5
+
</script>
6
+
7
+
<CollapsiblePrimitive.Content bind:ref data-slot="collapsible-content" {...restProps} />
+7
apps/web/src/lib/components/ui/collapsible/collapsible-trigger.svelte
+7
apps/web/src/lib/components/ui/collapsible/collapsible-trigger.svelte
···
1
+
<script lang="ts">
2
+
import { Collapsible as CollapsiblePrimitive } from "bits-ui";
3
+
4
+
let { ref = $bindable(null), ...restProps }: CollapsiblePrimitive.TriggerProps = $props();
5
+
</script>
6
+
7
+
<CollapsiblePrimitive.Trigger bind:ref data-slot="collapsible-trigger" {...restProps} />
+11
apps/web/src/lib/components/ui/collapsible/collapsible.svelte
+11
apps/web/src/lib/components/ui/collapsible/collapsible.svelte
···
1
+
<script lang="ts">
2
+
import { Collapsible as CollapsiblePrimitive } from "bits-ui";
3
+
4
+
let {
5
+
ref = $bindable(null),
6
+
open = $bindable(false),
7
+
...restProps
8
+
}: CollapsiblePrimitive.RootProps = $props();
9
+
</script>
10
+
11
+
<CollapsiblePrimitive.Root bind:ref bind:open data-slot="collapsible" {...restProps} />
+13
apps/web/src/lib/components/ui/collapsible/index.ts
+13
apps/web/src/lib/components/ui/collapsible/index.ts
···
1
+
import Root from "./collapsible.svelte";
2
+
import Trigger from "./collapsible-trigger.svelte";
3
+
import Content from "./collapsible-content.svelte";
4
+
5
+
export {
6
+
Root,
7
+
Content,
8
+
Trigger,
9
+
//
10
+
Root as Collapsible,
11
+
Content as CollapsibleContent,
12
+
Trigger as CollapsibleTrigger,
13
+
};
+40
apps/web/src/lib/components/ui/command/command-dialog.svelte
+40
apps/web/src/lib/components/ui/command/command-dialog.svelte
···
1
+
<script lang="ts">
2
+
import type { Command as CommandPrimitive, Dialog as DialogPrimitive } from "bits-ui";
3
+
import type { Snippet } from "svelte";
4
+
import Command from "./command.svelte";
5
+
import * as Dialog from "$lib/components/ui/dialog/index.js";
6
+
import type { WithoutChildrenOrChild } from "$lib/utils/cn.js";
7
+
8
+
let {
9
+
open = $bindable(false),
10
+
ref = $bindable(null),
11
+
value = $bindable(""),
12
+
title = "Command Palette",
13
+
description = "Search for a command to run",
14
+
portalProps,
15
+
children,
16
+
...restProps
17
+
}: WithoutChildrenOrChild<DialogPrimitive.RootProps> &
18
+
WithoutChildrenOrChild<CommandPrimitive.RootProps> & {
19
+
portalProps?: DialogPrimitive.PortalProps;
20
+
children: Snippet;
21
+
title?: string;
22
+
description?: string;
23
+
} = $props();
24
+
</script>
25
+
26
+
<Dialog.Root bind:open {...restProps}>
27
+
<Dialog.Header class="sr-only">
28
+
<Dialog.Title>{title}</Dialog.Title>
29
+
<Dialog.Description>{description}</Dialog.Description>
30
+
</Dialog.Header>
31
+
<Dialog.Content class="overflow-hidden p-0" {portalProps}>
32
+
<Command
33
+
class="**:data-[slot=command-input-wrapper]:h-12 [&_[data-command-group]:not([hidden])_~[data-command-group]]:pt-0 [&_[data-command-group]]:px-2 [&_[data-command-input-wrapper]_svg]:h-5 [&_[data-command-input-wrapper]_svg]:w-5 [&_[data-command-input]]:h-12 [&_[data-command-item]]:px-2 [&_[data-command-item]]:py-3 [&_[data-command-item]_svg]:h-5 [&_[data-command-item]_svg]:w-5"
34
+
{...restProps}
35
+
bind:value
36
+
bind:ref
37
+
{children}
38
+
/>
39
+
</Dialog.Content>
40
+
</Dialog.Root>
+17
apps/web/src/lib/components/ui/command/command-empty.svelte
+17
apps/web/src/lib/components/ui/command/command-empty.svelte
···
1
+
<script lang="ts">
2
+
import { Command as CommandPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CommandPrimitive.EmptyProps = $props();
10
+
</script>
11
+
12
+
<CommandPrimitive.Empty
13
+
bind:ref
14
+
data-slot="command-empty"
15
+
class={cn("py-6 text-center text-sm", className)}
16
+
{...restProps}
17
+
/>
+32
apps/web/src/lib/components/ui/command/command-group.svelte
+32
apps/web/src/lib/components/ui/command/command-group.svelte
···
1
+
<script lang="ts">
2
+
import { Command as CommandPrimitive, useId } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
heading,
10
+
value,
11
+
...restProps
12
+
}: CommandPrimitive.GroupProps & {
13
+
heading?: string;
14
+
} = $props();
15
+
</script>
16
+
17
+
<CommandPrimitive.Group
18
+
bind:ref
19
+
data-slot="command-group"
20
+
class={cn("text-foreground overflow-hidden p-1", className)}
21
+
value={value ?? heading ?? `----${useId()}`}
22
+
{...restProps}
23
+
>
24
+
{#if heading}
25
+
<CommandPrimitive.GroupHeading
26
+
class="text-muted-foreground px-2 py-1.5 text-xs font-medium"
27
+
>
28
+
{heading}
29
+
</CommandPrimitive.GroupHeading>
30
+
{/if}
31
+
<CommandPrimitive.GroupItems {children} />
32
+
</CommandPrimitive.Group>
+26
apps/web/src/lib/components/ui/command/command-input.svelte
+26
apps/web/src/lib/components/ui/command/command-input.svelte
···
1
+
<script lang="ts">
2
+
import { Command as CommandPrimitive } from "bits-ui";
3
+
import SearchIcon from "@lucide/svelte/icons/search";
4
+
import { cn } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
value = $bindable(""),
10
+
...restProps
11
+
}: CommandPrimitive.InputProps = $props();
12
+
</script>
13
+
14
+
<div class="flex h-9 items-center gap-2 border-b pl-3 pr-8" data-slot="command-input-wrapper">
15
+
<SearchIcon class="size-4 shrink-0 opacity-50" />
16
+
<CommandPrimitive.Input
17
+
data-slot="command-input"
18
+
class={cn(
19
+
"placeholder:text-muted-foreground outline-hidden flex h-10 w-full rounded-md bg-transparent py-3 text-sm disabled:cursor-not-allowed disabled:opacity-50",
20
+
className
21
+
)}
22
+
bind:ref
23
+
{...restProps}
24
+
bind:value
25
+
/>
26
+
</div>
+20
apps/web/src/lib/components/ui/command/command-item.svelte
+20
apps/web/src/lib/components/ui/command/command-item.svelte
···
1
+
<script lang="ts">
2
+
import { Command as CommandPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CommandPrimitive.ItemProps = $props();
10
+
</script>
11
+
12
+
<CommandPrimitive.Item
13
+
bind:ref
14
+
data-slot="command-item"
15
+
class={cn(
16
+
"aria-selected:bg-accent aria-selected:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground outline-hidden relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+20
apps/web/src/lib/components/ui/command/command-link-item.svelte
+20
apps/web/src/lib/components/ui/command/command-link-item.svelte
···
1
+
<script lang="ts">
2
+
import { Command as CommandPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CommandPrimitive.LinkItemProps = $props();
10
+
</script>
11
+
12
+
<CommandPrimitive.LinkItem
13
+
bind:ref
14
+
data-slot="command-item"
15
+
class={cn(
16
+
"aria-selected:bg-accent aria-selected:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground outline-hidden relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+17
apps/web/src/lib/components/ui/command/command-list.svelte
+17
apps/web/src/lib/components/ui/command/command-list.svelte
···
1
+
<script lang="ts">
2
+
import { Command as CommandPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CommandPrimitive.ListProps = $props();
10
+
</script>
11
+
12
+
<CommandPrimitive.List
13
+
bind:ref
14
+
data-slot="command-list"
15
+
class={cn("max-h-[300px] scroll-py-1 overflow-y-auto overflow-x-hidden", className)}
16
+
{...restProps}
17
+
/>
+17
apps/web/src/lib/components/ui/command/command-separator.svelte
+17
apps/web/src/lib/components/ui/command/command-separator.svelte
···
1
+
<script lang="ts">
2
+
import { Command as CommandPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: CommandPrimitive.SeparatorProps = $props();
10
+
</script>
11
+
12
+
<CommandPrimitive.Separator
13
+
bind:ref
14
+
data-slot="command-separator"
15
+
class={cn("bg-border -mx-1 h-px", className)}
16
+
{...restProps}
17
+
/>
+20
apps/web/src/lib/components/ui/command/command-shortcut.svelte
+20
apps/web/src/lib/components/ui/command/command-shortcut.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
11
+
</script>
12
+
13
+
<span
14
+
bind:this={ref}
15
+
data-slot="command-shortcut"
16
+
class={cn("text-muted-foreground ml-auto text-xs tracking-widest", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</span>
+22
apps/web/src/lib/components/ui/command/command.svelte
+22
apps/web/src/lib/components/ui/command/command.svelte
···
1
+
<script lang="ts">
2
+
import { Command as CommandPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
value = $bindable(""),
8
+
class: className,
9
+
...restProps
10
+
}: CommandPrimitive.RootProps = $props();
11
+
</script>
12
+
13
+
<CommandPrimitive.Root
14
+
bind:value
15
+
bind:ref
16
+
data-slot="command"
17
+
class={cn(
18
+
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
19
+
className
20
+
)}
21
+
{...restProps}
22
+
/>
+40
apps/web/src/lib/components/ui/command/index.ts
+40
apps/web/src/lib/components/ui/command/index.ts
···
1
+
import { Command as CommandPrimitive } from "bits-ui";
2
+
3
+
import Root from "./command.svelte";
4
+
import Dialog from "./command-dialog.svelte";
5
+
import Empty from "./command-empty.svelte";
6
+
import Group from "./command-group.svelte";
7
+
import Item from "./command-item.svelte";
8
+
import Input from "./command-input.svelte";
9
+
import List from "./command-list.svelte";
10
+
import Separator from "./command-separator.svelte";
11
+
import Shortcut from "./command-shortcut.svelte";
12
+
import LinkItem from "./command-link-item.svelte";
13
+
14
+
const Loading = CommandPrimitive.Loading;
15
+
16
+
export {
17
+
Root,
18
+
Dialog,
19
+
Empty,
20
+
Group,
21
+
Item,
22
+
LinkItem,
23
+
Input,
24
+
List,
25
+
Separator,
26
+
Shortcut,
27
+
Loading,
28
+
//
29
+
Root as Command,
30
+
Dialog as CommandDialog,
31
+
Empty as CommandEmpty,
32
+
Group as CommandGroup,
33
+
Item as CommandItem,
34
+
LinkItem as CommandLinkItem,
35
+
Input as CommandInput,
36
+
List as CommandList,
37
+
Separator as CommandSeparator,
38
+
Shortcut as CommandShortcut,
39
+
Loading as CommandLoading,
40
+
};
+142
apps/web/src/lib/components/ui/data-table/data-table.svelte.ts
+142
apps/web/src/lib/components/ui/data-table/data-table.svelte.ts
···
1
+
import {
2
+
type RowData,
3
+
type TableOptions,
4
+
type TableOptionsResolved,
5
+
type TableState,
6
+
createTable,
7
+
} from "@tanstack/table-core";
8
+
9
+
/**
10
+
* Creates a reactive TanStack table object for Svelte.
11
+
* @param options Table options to create the table with.
12
+
* @returns A reactive table object.
13
+
* @example
14
+
* ```svelte
15
+
* <script>
16
+
* const table = createSvelteTable({ ... })
17
+
* </script>
18
+
*
19
+
* <table>
20
+
* <thead>
21
+
* {#each table.getHeaderGroups() as headerGroup}
22
+
* <tr>
23
+
* {#each headerGroup.headers as header}
24
+
* <th colspan={header.colSpan}>
25
+
* <FlexRender content={header.column.columnDef.header} context={header.getContext()} />
26
+
* </th>
27
+
* {/each}
28
+
* </tr>
29
+
* {/each}
30
+
* </thead>
31
+
* <!-- ... -->
32
+
* </table>
33
+
* ```
34
+
*/
35
+
export function createSvelteTable<TData extends RowData>(options: TableOptions<TData>) {
36
+
const resolvedOptions: TableOptionsResolved<TData> = mergeObjects(
37
+
{
38
+
state: {},
39
+
onStateChange() {},
40
+
renderFallbackValue: null,
41
+
mergeOptions: (
42
+
defaultOptions: TableOptions<TData>,
43
+
options: Partial<TableOptions<TData>>
44
+
) => {
45
+
return mergeObjects(defaultOptions, options);
46
+
},
47
+
},
48
+
options
49
+
);
50
+
51
+
const table = createTable(resolvedOptions);
52
+
let state = $state<Partial<TableState>>(table.initialState);
53
+
54
+
function updateOptions() {
55
+
table.setOptions((prev) => {
56
+
return mergeObjects(prev, options, {
57
+
state: mergeObjects(state, options.state || {}),
58
+
59
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+
onStateChange: (updater: any) => {
61
+
if (updater instanceof Function) state = updater(state);
62
+
else state = mergeObjects(state, updater);
63
+
64
+
options.onStateChange?.(updater);
65
+
},
66
+
});
67
+
});
68
+
}
69
+
70
+
updateOptions();
71
+
72
+
$effect.pre(() => {
73
+
updateOptions();
74
+
});
75
+
76
+
return table;
77
+
}
78
+
79
+
type MaybeThunk<T extends object> = T | (() => T | null | undefined);
80
+
type Intersection<T extends readonly unknown[]> = (T extends [infer H, ...infer R]
81
+
? H & Intersection<R>
82
+
: unknown) & {};
83
+
84
+
/**
85
+
* Lazily merges several objects (or thunks) while preserving
86
+
* getter semantics from every source.
87
+
*
88
+
* Proxy-based to avoid known WebKit recursion issue.
89
+
*/
90
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
91
+
export function mergeObjects<Sources extends readonly MaybeThunk<any>[]>(
92
+
...sources: Sources
93
+
): Intersection<{ [K in keyof Sources]: Sources[K] }> {
94
+
const resolve = <T extends object>(src: MaybeThunk<T>): T | undefined =>
95
+
typeof src === "function" ? (src() ?? undefined) : src;
96
+
97
+
const findSourceWithKey = (key: PropertyKey) => {
98
+
for (let i = sources.length - 1; i >= 0; i--) {
99
+
const obj = resolve(sources[i]);
100
+
if (obj && key in obj) return obj;
101
+
}
102
+
return undefined;
103
+
};
104
+
105
+
return new Proxy(Object.create(null), {
106
+
get(_, key) {
107
+
const src = findSourceWithKey(key);
108
+
109
+
return src?.[key as never];
110
+
},
111
+
112
+
has(_, key) {
113
+
return !!findSourceWithKey(key);
114
+
},
115
+
116
+
ownKeys(): (string | symbol)[] {
117
+
// eslint-disable-next-line svelte/prefer-svelte-reactivity
118
+
const all = new Set<string | symbol>();
119
+
for (const s of sources) {
120
+
const obj = resolve(s);
121
+
if (obj) {
122
+
for (const k of Reflect.ownKeys(obj) as (string | symbol)[]) {
123
+
all.add(k);
124
+
}
125
+
}
126
+
}
127
+
return [...all];
128
+
},
129
+
130
+
getOwnPropertyDescriptor(_, key) {
131
+
const src = findSourceWithKey(key);
132
+
if (!src) return undefined;
133
+
return {
134
+
configurable: true,
135
+
enumerable: true,
136
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
137
+
value: (src as any)[key],
138
+
writable: true,
139
+
};
140
+
},
141
+
}) as Intersection<{ [K in keyof Sources]: Sources[K] }>;
142
+
}
+40
apps/web/src/lib/components/ui/data-table/flex-render.svelte
+40
apps/web/src/lib/components/ui/data-table/flex-render.svelte
···
1
+
<script
2
+
lang="ts"
3
+
generics="TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>"
4
+
>
5
+
import type { CellContext, ColumnDefTemplate, HeaderContext } from "@tanstack/table-core";
6
+
import { RenderComponentConfig, RenderSnippetConfig } from "./render-helpers.js";
7
+
import type { Attachment } from "svelte/attachments";
8
+
type Props = {
9
+
/** The cell or header field of the current cell's column definition. */
10
+
content?: TContext extends HeaderContext<TData, TValue>
11
+
? ColumnDefTemplate<HeaderContext<TData, TValue>>
12
+
: TContext extends CellContext<TData, TValue>
13
+
? ColumnDefTemplate<CellContext<TData, TValue>>
14
+
: never;
15
+
/** The result of the `getContext()` function of the header or cell */
16
+
context: TContext;
17
+
18
+
/** Used to pass attachments that can't be gotten through context */
19
+
attach?: Attachment;
20
+
};
21
+
22
+
let { content, context, attach }: Props = $props();
23
+
</script>
24
+
25
+
{#if typeof content === "string"}
26
+
{content}
27
+
{:else if content instanceof Function}
28
+
<!-- It's unlikely that a CellContext will be passed to a Header -->
29
+
<!-- eslint-disable-next-line @typescript-eslint/no-explicit-any -->
30
+
{@const result = content(context as any)}
31
+
{#if result instanceof RenderComponentConfig}
32
+
{@const { component: Component, props } = result}
33
+
<Component {...props} {attach} />
34
+
{:else if result instanceof RenderSnippetConfig}
35
+
{@const { snippet, params } = result}
36
+
{@render snippet({ ...params, attach })}
37
+
{:else}
38
+
{result}
39
+
{/if}
40
+
{/if}
+3
apps/web/src/lib/components/ui/data-table/index.ts
+3
apps/web/src/lib/components/ui/data-table/index.ts
+111
apps/web/src/lib/components/ui/data-table/render-helpers.ts
+111
apps/web/src/lib/components/ui/data-table/render-helpers.ts
···
1
+
import type { Component, ComponentProps, Snippet } from "svelte";
2
+
3
+
/**
4
+
* A helper class to make it easy to identify Svelte components in
5
+
* `columnDef.cell` and `columnDef.header` properties.
6
+
*
7
+
* > NOTE: This class should only be used internally by the adapter. If you're
8
+
* reading this and you don't know what this is for, you probably don't need it.
9
+
*
10
+
* @example
11
+
* ```svelte
12
+
* {@const result = content(context as any)}
13
+
* {#if result instanceof RenderComponentConfig}
14
+
* {@const { component: Component, props } = result}
15
+
* <Component {...props} />
16
+
* {/if}
17
+
* ```
18
+
*/
19
+
export class RenderComponentConfig<TComponent extends Component> {
20
+
component: TComponent;
21
+
props: ComponentProps<TComponent> | Record<string, never>;
22
+
constructor(
23
+
component: TComponent,
24
+
props: ComponentProps<TComponent> | Record<string, never> = {}
25
+
) {
26
+
this.component = component;
27
+
this.props = props;
28
+
}
29
+
}
30
+
31
+
/**
32
+
* A helper class to make it easy to identify Svelte Snippets in `columnDef.cell` and `columnDef.header` properties.
33
+
*
34
+
* > NOTE: This class should only be used internally by the adapter. If you're
35
+
* reading this and you don't know what this is for, you probably don't need it.
36
+
*
37
+
* @example
38
+
* ```svelte
39
+
* {@const result = content(context as any)}
40
+
* {#if result instanceof RenderSnippetConfig}
41
+
* {@const { snippet, params } = result}
42
+
* {@render snippet(params)}
43
+
* {/if}
44
+
* ```
45
+
*/
46
+
export class RenderSnippetConfig<TProps> {
47
+
snippet: Snippet<[TProps]>;
48
+
params: TProps;
49
+
constructor(snippet: Snippet<[TProps]>, params: TProps) {
50
+
this.snippet = snippet;
51
+
this.params = params;
52
+
}
53
+
}
54
+
55
+
/**
56
+
* A helper function to help create cells from Svelte components through ColumnDef's `cell` and `header` properties.
57
+
*
58
+
* This is only to be used with Svelte Components - use `renderSnippet` for Svelte Snippets.
59
+
*
60
+
* @param component A Svelte component
61
+
* @param props The props to pass to `component`
62
+
* @returns A `RenderComponentConfig` object that helps svelte-table know how to render the header/cell component.
63
+
* @example
64
+
* ```ts
65
+
* // +page.svelte
66
+
* const defaultColumns = [
67
+
* columnHelper.accessor('name', {
68
+
* header: header => renderComponent(SortHeader, { label: 'Name', header }),
69
+
* }),
70
+
* columnHelper.accessor('state', {
71
+
* header: header => renderComponent(SortHeader, { label: 'State', header }),
72
+
* }),
73
+
* ]
74
+
* ```
75
+
* @see {@link https://tanstack.com/table/latest/docs/guide/column-defs}
76
+
*/
77
+
export function renderComponent<
78
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
79
+
T extends Component<any>,
80
+
Props extends ComponentProps<T>,
81
+
>(component: T, props: Props = {} as Props) {
82
+
return new RenderComponentConfig(component, props);
83
+
}
84
+
85
+
/**
86
+
* A helper function to help create cells from Svelte Snippets through ColumnDef's `cell` and `header` properties.
87
+
*
88
+
* The snippet must only take one parameter.
89
+
*
90
+
* This is only to be used with Snippets - use `renderComponent` for Svelte Components.
91
+
*
92
+
* @param snippet
93
+
* @param params
94
+
* @returns - A `RenderSnippetConfig` object that helps svelte-table know how to render the header/cell snippet.
95
+
* @example
96
+
* ```ts
97
+
* // +page.svelte
98
+
* const defaultColumns = [
99
+
* columnHelper.accessor('name', {
100
+
* cell: cell => renderSnippet(nameSnippet, { name: cell.row.name }),
101
+
* }),
102
+
* columnHelper.accessor('state', {
103
+
* cell: cell => renderSnippet(stateSnippet, { state: cell.row.state }),
104
+
* }),
105
+
* ]
106
+
* ```
107
+
* @see {@link https://tanstack.com/table/latest/docs/guide/column-defs}
108
+
*/
109
+
export function renderSnippet<TProps>(snippet: Snippet<[TProps]>, params: TProps = {} as TProps) {
110
+
return new RenderSnippetConfig(snippet, params);
111
+
}
+7
apps/web/src/lib/components/ui/dialog/dialog-close.svelte
+7
apps/web/src/lib/components/ui/dialog/dialog-close.svelte
+43
apps/web/src/lib/components/ui/dialog/dialog-content.svelte
+43
apps/web/src/lib/components/ui/dialog/dialog-content.svelte
···
1
+
<script lang="ts">
2
+
import { Dialog as DialogPrimitive } from "bits-ui";
3
+
import XIcon from "@lucide/svelte/icons/x";
4
+
import type { Snippet } from "svelte";
5
+
import * as Dialog from "./index.js";
6
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
7
+
8
+
let {
9
+
ref = $bindable(null),
10
+
class: className,
11
+
portalProps,
12
+
children,
13
+
showCloseButton = true,
14
+
...restProps
15
+
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
16
+
portalProps?: DialogPrimitive.PortalProps;
17
+
children: Snippet;
18
+
showCloseButton?: boolean;
19
+
} = $props();
20
+
</script>
21
+
22
+
<Dialog.Portal {...portalProps}>
23
+
<Dialog.Overlay />
24
+
<DialogPrimitive.Content
25
+
bind:ref
26
+
data-slot="dialog-content"
27
+
class={cn(
28
+
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed left-[50%] top-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
29
+
className
30
+
)}
31
+
{...restProps}
32
+
>
33
+
{@render children?.()}
34
+
{#if showCloseButton}
35
+
<DialogPrimitive.Close
36
+
class="ring-offset-background focus:ring-ring rounded-xs focus:outline-hidden absolute end-4 top-4 opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
37
+
>
38
+
<XIcon />
39
+
<span class="sr-only">Close</span>
40
+
</DialogPrimitive.Close>
41
+
{/if}
42
+
</DialogPrimitive.Content>
43
+
</Dialog.Portal>
+17
apps/web/src/lib/components/ui/dialog/dialog-description.svelte
+17
apps/web/src/lib/components/ui/dialog/dialog-description.svelte
···
1
+
<script lang="ts">
2
+
import { Dialog as DialogPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: DialogPrimitive.DescriptionProps = $props();
10
+
</script>
11
+
12
+
<DialogPrimitive.Description
13
+
bind:ref
14
+
data-slot="dialog-description"
15
+
class={cn("text-muted-foreground text-sm", className)}
16
+
{...restProps}
17
+
/>
+20
apps/web/src/lib/components/ui/dialog/dialog-header.svelte
+20
apps/web/src/lib/components/ui/dialog/dialog-header.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="dialog-header"
16
+
class={cn("flex flex-col gap-2 text-center sm:text-left", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+20
apps/web/src/lib/components/ui/dialog/dialog-overlay.svelte
+20
apps/web/src/lib/components/ui/dialog/dialog-overlay.svelte
···
1
+
<script lang="ts">
2
+
import { Dialog as DialogPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: DialogPrimitive.OverlayProps = $props();
10
+
</script>
11
+
12
+
<DialogPrimitive.Overlay
13
+
bind:ref
14
+
data-slot="dialog-overlay"
15
+
class={cn(
16
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+17
apps/web/src/lib/components/ui/dialog/dialog-title.svelte
+17
apps/web/src/lib/components/ui/dialog/dialog-title.svelte
···
1
+
<script lang="ts">
2
+
import { Dialog as DialogPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: DialogPrimitive.TitleProps = $props();
10
+
</script>
11
+
12
+
<DialogPrimitive.Title
13
+
bind:ref
14
+
data-slot="dialog-title"
15
+
class={cn("text-lg font-semibold leading-none", className)}
16
+
{...restProps}
17
+
/>
+7
apps/web/src/lib/components/ui/dialog/dialog-trigger.svelte
+7
apps/web/src/lib/components/ui/dialog/dialog-trigger.svelte
+37
apps/web/src/lib/components/ui/dialog/index.ts
+37
apps/web/src/lib/components/ui/dialog/index.ts
···
1
+
import { Dialog as DialogPrimitive } from "bits-ui";
2
+
3
+
import Title from "./dialog-title.svelte";
4
+
import Footer from "./dialog-footer.svelte";
5
+
import Header from "./dialog-header.svelte";
6
+
import Overlay from "./dialog-overlay.svelte";
7
+
import Content from "./dialog-content.svelte";
8
+
import Description from "./dialog-description.svelte";
9
+
import Trigger from "./dialog-trigger.svelte";
10
+
import Close from "./dialog-close.svelte";
11
+
12
+
const Root = DialogPrimitive.Root;
13
+
const Portal = DialogPrimitive.Portal;
14
+
15
+
export {
16
+
Root,
17
+
Title,
18
+
Portal,
19
+
Footer,
20
+
Header,
21
+
Trigger,
22
+
Overlay,
23
+
Content,
24
+
Description,
25
+
Close,
26
+
//
27
+
Root as Dialog,
28
+
Title as DialogTitle,
29
+
Portal as DialogPortal,
30
+
Footer as DialogFooter,
31
+
Header as DialogHeader,
32
+
Trigger as DialogTrigger,
33
+
Overlay as DialogOverlay,
34
+
Content as DialogContent,
35
+
Description as DialogDescription,
36
+
Close as DialogClose,
37
+
};
+7
apps/web/src/lib/components/ui/drawer/drawer-close.svelte
+7
apps/web/src/lib/components/ui/drawer/drawer-close.svelte
+37
apps/web/src/lib/components/ui/drawer/drawer-content.svelte
+37
apps/web/src/lib/components/ui/drawer/drawer-content.svelte
···
1
+
<script lang="ts">
2
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
3
+
import DrawerOverlay from "./drawer-overlay.svelte";
4
+
import { cn } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
portalProps,
10
+
children,
11
+
...restProps
12
+
}: DrawerPrimitive.ContentProps & {
13
+
portalProps?: DrawerPrimitive.PortalProps;
14
+
} = $props();
15
+
</script>
16
+
17
+
<DrawerPrimitive.Portal {...portalProps}>
18
+
<DrawerOverlay />
19
+
<DrawerPrimitive.Content
20
+
bind:ref
21
+
data-slot="drawer-content"
22
+
class={cn(
23
+
"group/drawer-content bg-background fixed z-50 flex h-auto flex-col",
24
+
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
25
+
"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
26
+
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
27
+
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm",
28
+
className
29
+
)}
30
+
{...restProps}
31
+
>
32
+
<div
33
+
class="bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block"
34
+
></div>
35
+
{@render children?.()}
36
+
</DrawerPrimitive.Content>
37
+
</DrawerPrimitive.Portal>
+17
apps/web/src/lib/components/ui/drawer/drawer-description.svelte
+17
apps/web/src/lib/components/ui/drawer/drawer-description.svelte
···
1
+
<script lang="ts">
2
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: DrawerPrimitive.DescriptionProps = $props();
10
+
</script>
11
+
12
+
<DrawerPrimitive.Description
13
+
bind:ref
14
+
data-slot="drawer-description"
15
+
class={cn("text-muted-foreground text-sm", className)}
16
+
{...restProps}
17
+
/>
+20
apps/web/src/lib/components/ui/drawer/drawer-header.svelte
+20
apps/web/src/lib/components/ui/drawer/drawer-header.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="drawer-header"
16
+
class={cn("flex flex-col gap-1.5 p-4", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+12
apps/web/src/lib/components/ui/drawer/drawer-nested.svelte
+12
apps/web/src/lib/components/ui/drawer/drawer-nested.svelte
···
1
+
<script lang="ts">
2
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
3
+
4
+
let {
5
+
shouldScaleBackground = true,
6
+
open = $bindable(false),
7
+
activeSnapPoint = $bindable(null),
8
+
...restProps
9
+
}: DrawerPrimitive.RootProps = $props();
10
+
</script>
11
+
12
+
<DrawerPrimitive.NestedRoot {shouldScaleBackground} bind:open bind:activeSnapPoint {...restProps} />
+20
apps/web/src/lib/components/ui/drawer/drawer-overlay.svelte
+20
apps/web/src/lib/components/ui/drawer/drawer-overlay.svelte
···
1
+
<script lang="ts">
2
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: DrawerPrimitive.OverlayProps = $props();
10
+
</script>
11
+
12
+
<DrawerPrimitive.Overlay
13
+
bind:ref
14
+
data-slot="drawer-overlay"
15
+
class={cn(
16
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+17
apps/web/src/lib/components/ui/drawer/drawer-title.svelte
+17
apps/web/src/lib/components/ui/drawer/drawer-title.svelte
···
1
+
<script lang="ts">
2
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: DrawerPrimitive.TitleProps = $props();
10
+
</script>
11
+
12
+
<DrawerPrimitive.Title
13
+
bind:ref
14
+
data-slot="drawer-title"
15
+
class={cn("text-foreground font-semibold", className)}
16
+
{...restProps}
17
+
/>
+7
apps/web/src/lib/components/ui/drawer/drawer-trigger.svelte
+7
apps/web/src/lib/components/ui/drawer/drawer-trigger.svelte
+12
apps/web/src/lib/components/ui/drawer/drawer.svelte
+12
apps/web/src/lib/components/ui/drawer/drawer.svelte
···
1
+
<script lang="ts">
2
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
3
+
4
+
let {
5
+
shouldScaleBackground = true,
6
+
open = $bindable(false),
7
+
activeSnapPoint = $bindable(null),
8
+
...restProps
9
+
}: DrawerPrimitive.RootProps = $props();
10
+
</script>
11
+
12
+
<DrawerPrimitive.Root {shouldScaleBackground} bind:open bind:activeSnapPoint {...restProps} />
+41
apps/web/src/lib/components/ui/drawer/index.ts
+41
apps/web/src/lib/components/ui/drawer/index.ts
···
1
+
import { Drawer as DrawerPrimitive } from "vaul-svelte";
2
+
3
+
import Root from "./drawer.svelte";
4
+
import Content from "./drawer-content.svelte";
5
+
import Description from "./drawer-description.svelte";
6
+
import Overlay from "./drawer-overlay.svelte";
7
+
import Footer from "./drawer-footer.svelte";
8
+
import Header from "./drawer-header.svelte";
9
+
import Title from "./drawer-title.svelte";
10
+
import NestedRoot from "./drawer-nested.svelte";
11
+
import Close from "./drawer-close.svelte";
12
+
import Trigger from "./drawer-trigger.svelte";
13
+
14
+
const Portal: typeof DrawerPrimitive.Portal = DrawerPrimitive.Portal;
15
+
16
+
export {
17
+
Root,
18
+
NestedRoot,
19
+
Content,
20
+
Description,
21
+
Overlay,
22
+
Footer,
23
+
Header,
24
+
Title,
25
+
Trigger,
26
+
Portal,
27
+
Close,
28
+
29
+
//
30
+
Root as Drawer,
31
+
NestedRoot as DrawerNestedRoot,
32
+
Content as DrawerContent,
33
+
Description as DrawerDescription,
34
+
Overlay as DrawerOverlay,
35
+
Footer as DrawerFooter,
36
+
Header as DrawerHeader,
37
+
Title as DrawerTitle,
38
+
Trigger as DrawerTrigger,
39
+
Portal as DrawerPortal,
40
+
Close as DrawerClose,
41
+
};
+17
apps/web/src/lib/components/ui/empty/empty-content.svelte
+17
apps/web/src/lib/components/ui/empty/empty-content.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="empty-content"
10
+
class={cn(
11
+
"flex w-full min-w-0 max-w-sm flex-col items-center gap-4 text-balance text-sm",
12
+
className
13
+
)}
14
+
{...restProps}
15
+
>
16
+
{@render children?.()}
17
+
</div>
+17
apps/web/src/lib/components/ui/empty/empty-description.svelte
+17
apps/web/src/lib/components/ui/empty/empty-description.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="empty-description"
10
+
class={cn(
11
+
"text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
12
+
className
13
+
)}
14
+
{...restProps}
15
+
>
16
+
{@render children?.()}
17
+
</div>
+14
apps/web/src/lib/components/ui/empty/empty-header.svelte
+14
apps/web/src/lib/components/ui/empty/empty-header.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="empty-header"
10
+
class={cn("flex max-w-sm flex-col items-center gap-2 text-center", className)}
11
+
{...restProps}
12
+
>
13
+
{@render children?.()}
14
+
</div>
+39
apps/web/src/lib/components/ui/empty/empty-media.svelte
+39
apps/web/src/lib/components/ui/empty/empty-media.svelte
···
1
+
<script lang="ts" module>
2
+
import { tv, type VariantProps } from "tailwind-variants";
3
+
4
+
export const emptyMediaVariants = tv({
5
+
base: "mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
6
+
variants: {
7
+
variant: {
8
+
default: "bg-transparent",
9
+
icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
10
+
},
11
+
},
12
+
defaultVariants: {
13
+
variant: "default",
14
+
},
15
+
});
16
+
17
+
export type EmptyMediaVariant = VariantProps<typeof emptyMediaVariants>["variant"];
18
+
</script>
19
+
20
+
<script lang="ts">
21
+
import { cn } from "$lib/utils/cn.js";
22
+
import type { HTMLAttributes } from "svelte/elements";
23
+
24
+
let {
25
+
class: className,
26
+
children,
27
+
variant = "default",
28
+
...restProps
29
+
}: HTMLAttributes<HTMLDivElement> & { variant?: EmptyMediaVariant } = $props();
30
+
</script>
31
+
32
+
<div
33
+
data-slot="empty-icon"
34
+
data-variant={variant}
35
+
class={cn(emptyMediaVariants({ variant }), className)}
36
+
{...restProps}
37
+
>
38
+
{@render children?.()}
39
+
</div>
+14
apps/web/src/lib/components/ui/empty/empty-title.svelte
+14
apps/web/src/lib/components/ui/empty/empty-title.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="empty-title"
10
+
class={cn("text-lg font-medium tracking-tight", className)}
11
+
{...restProps}
12
+
>
13
+
{@render children?.()}
14
+
</div>
+17
apps/web/src/lib/components/ui/empty/empty.svelte
+17
apps/web/src/lib/components/ui/empty/empty.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="empty"
10
+
class={cn(
11
+
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance rounded-lg border-dashed p-6 text-center md:p-12",
12
+
className
13
+
)}
14
+
{...restProps}
15
+
>
16
+
{@render children?.()}
17
+
</div>
+22
apps/web/src/lib/components/ui/empty/index.ts
+22
apps/web/src/lib/components/ui/empty/index.ts
···
1
+
import Root from "./empty.svelte";
2
+
import Header from "./empty-header.svelte";
3
+
import Media from "./empty-media.svelte";
4
+
import Title from "./empty-title.svelte";
5
+
import Description from "./empty-description.svelte";
6
+
import Content from "./empty-content.svelte";
7
+
8
+
export {
9
+
Root,
10
+
Header,
11
+
Media,
12
+
Title,
13
+
Description,
14
+
Content,
15
+
//
16
+
Root as Empty,
17
+
Header as EmptyHeader,
18
+
Media as EmptyMedia,
19
+
Title as EmptyTitle,
20
+
Description as EmptyDescription,
21
+
Content as EmptyContent,
22
+
};
+14
apps/web/src/lib/components/ui/field/field-content.svelte
+14
apps/web/src/lib/components/ui/field/field-content.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="field-content"
10
+
class={cn("group/field-content flex flex-1 flex-col gap-1.5 leading-snug", className)}
11
+
{...restProps}
12
+
>
13
+
{@render children?.()}
14
+
</div>
+23
apps/web/src/lib/components/ui/field/field-description.svelte
+23
apps/web/src/lib/components/ui/field/field-description.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
class: className,
7
+
children,
8
+
...restProps
9
+
}: HTMLAttributes<HTMLParagraphElement> = $props();
10
+
</script>
11
+
12
+
<p
13
+
data-slot="field-description"
14
+
class={cn(
15
+
"text-muted-foreground text-sm font-normal leading-normal group-has-[[data-orientation=horizontal]]/field:text-balance",
16
+
"nth-last-2:-mt-1 last:mt-0 [[data-variant=legend]+&]:-mt-1.5",
17
+
"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
>
22
+
{@render children?.()}
23
+
</p>
+56
apps/web/src/lib/components/ui/field/field-error.svelte
+56
apps/web/src/lib/components/ui/field/field-error.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
import type { Snippet } from "svelte";
5
+
6
+
let {
7
+
class: className,
8
+
children,
9
+
errors,
10
+
...restProps
11
+
}: HTMLAttributes<HTMLDivElement> & {
12
+
children?: Snippet;
13
+
errors?: { message?: string }[];
14
+
} = $props();
15
+
16
+
const hasContent = $derived.by(() => {
17
+
// has slotted error
18
+
if (children) return true;
19
+
20
+
// no errors
21
+
if (!errors) return false;
22
+
23
+
// has an error but no message
24
+
if (errors.length === 1 && !errors[0]?.message) {
25
+
return false;
26
+
}
27
+
28
+
return true;
29
+
});
30
+
31
+
const isMultipleErrors = $derived(errors && errors.length > 1);
32
+
const singleErrorMessage = $derived(errors && errors.length === 1 && errors[0]?.message);
33
+
</script>
34
+
35
+
{#if hasContent}
36
+
<div
37
+
role="alert"
38
+
data-slot="field-error"
39
+
class={cn("text-destructive text-sm font-normal", className)}
40
+
{...restProps}
41
+
>
42
+
{#if children}
43
+
{@render children()}
44
+
{:else if singleErrorMessage}
45
+
{singleErrorMessage}
46
+
{:else if isMultipleErrors}
47
+
<ul class="ml-4 flex list-disc flex-col gap-1">
48
+
{#each errors ?? [] as error, index (index)}
49
+
{#if error?.message}
50
+
<li>{error.message}</li>
51
+
{/if}
52
+
{/each}
53
+
</ul>
54
+
{/if}
55
+
</div>
56
+
{/if}
+17
apps/web/src/lib/components/ui/field/field-group.svelte
+17
apps/web/src/lib/components/ui/field/field-group.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="field-group"
10
+
class={cn(
11
+
"group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4",
12
+
className
13
+
)}
14
+
{...restProps}
15
+
>
16
+
{@render children?.()}
17
+
</div>
+26
apps/web/src/lib/components/ui/field/field-label.svelte
+26
apps/web/src/lib/components/ui/field/field-label.svelte
···
1
+
<script lang="ts">
2
+
import { Label } from "$lib/components/ui/label/index.js";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
import type { ComponentProps } from "svelte";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
children,
10
+
...restProps
11
+
}: ComponentProps<typeof Label> = $props();
12
+
</script>
13
+
14
+
<Label
15
+
bind:ref
16
+
data-slot="field-label"
17
+
class={cn(
18
+
"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50",
19
+
"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4",
20
+
"has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10",
21
+
className
22
+
)}
23
+
{...restProps}
24
+
>
25
+
{@render children?.()}
26
+
</Label>
+27
apps/web/src/lib/components/ui/field/field-legend.svelte
+27
apps/web/src/lib/components/ui/field/field-legend.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
class: className,
7
+
variant = "legend",
8
+
children,
9
+
...restProps
10
+
}: HTMLAttributes<HTMLLegendElement> & {
11
+
variant?: "legend" | "label";
12
+
} = $props();
13
+
</script>
14
+
15
+
<legend
16
+
data-slot="field-legend"
17
+
data-variant={variant}
18
+
class={cn(
19
+
"mb-3 font-medium",
20
+
"data-[variant=legend]:text-base",
21
+
"data-[variant=label]:text-sm",
22
+
className
23
+
)}
24
+
{...restProps}
25
+
>
26
+
{@render children?.()}
27
+
</legend>
+36
apps/web/src/lib/components/ui/field/field-separator.svelte
+36
apps/web/src/lib/components/ui/field/field-separator.svelte
···
1
+
<script lang="ts">
2
+
import { Separator } from "$lib/components/ui/separator/index.js";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
import type { HTMLAttributes } from "svelte/elements";
5
+
import type { Snippet } from "svelte";
6
+
7
+
let {
8
+
class: className,
9
+
children,
10
+
...restProps
11
+
}: HTMLAttributes<HTMLDivElement> & {
12
+
children?: Snippet;
13
+
} = $props();
14
+
15
+
const hasContent = $derived(!!children);
16
+
</script>
17
+
18
+
<div
19
+
data-slot="field-separator"
20
+
data-content={hasContent}
21
+
class={cn(
22
+
"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
23
+
className
24
+
)}
25
+
{...restProps}
26
+
>
27
+
<Separator class="absolute inset-0 top-1/2" />
28
+
{#if children}
29
+
<span
30
+
class="bg-background text-muted-foreground relative mx-auto block w-fit px-2"
31
+
data-slot="field-separator-content"
32
+
>
33
+
{@render children()}
34
+
</span>
35
+
{/if}
36
+
</div>
+18
apps/web/src/lib/components/ui/field/field-set.svelte
+18
apps/web/src/lib/components/ui/field/field-set.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLFieldsetAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLFieldsetAttributes = $props();
6
+
</script>
7
+
8
+
<fieldset
9
+
data-slot="field-set"
10
+
class={cn(
11
+
"flex flex-col gap-6",
12
+
"has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
13
+
className
14
+
)}
15
+
{...restProps}
16
+
>
17
+
{@render children?.()}
18
+
</fieldset>
+17
apps/web/src/lib/components/ui/field/field-title.svelte
+17
apps/web/src/lib/components/ui/field/field-title.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="field-title"
10
+
class={cn(
11
+
"flex w-fit items-center gap-2 text-sm font-medium leading-snug group-data-[disabled=true]/field:opacity-50",
12
+
className
13
+
)}
14
+
{...restProps}
15
+
>
16
+
{@render children?.()}
17
+
</div>
+51
apps/web/src/lib/components/ui/field/field.svelte
+51
apps/web/src/lib/components/ui/field/field.svelte
···
1
+
<script lang="ts" module>
2
+
import { tv, type VariantProps } from "tailwind-variants";
3
+
4
+
const fieldVariants = tv({
5
+
base: "group/field data-[invalid=true]:text-destructive flex w-full gap-3",
6
+
variants: {
7
+
orientation: {
8
+
vertical: "flex-col [&>*]:w-full [&>.sr-only]:w-auto",
9
+
horizontal: [
10
+
"flex-row items-center",
11
+
"[&>[data-slot=field-label]]:flex-auto",
12
+
"has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px has-[>[data-slot=field-content]]:items-start",
13
+
],
14
+
responsive: [
15
+
"@md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto flex-col [&>*]:w-full [&>.sr-only]:w-auto",
16
+
"@md/field-group:[&>[data-slot=field-label]]:flex-auto",
17
+
"@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
18
+
],
19
+
},
20
+
},
21
+
defaultVariants: {
22
+
orientation: "vertical",
23
+
},
24
+
});
25
+
26
+
export type FieldOrientation = VariantProps<typeof fieldVariants>["orientation"];
27
+
</script>
28
+
29
+
<script lang="ts">
30
+
import { cn } from "$lib/utils/cn.js";
31
+
import type { HTMLAttributes } from "svelte/elements";
32
+
33
+
let {
34
+
class: className,
35
+
orientation = "vertical",
36
+
children,
37
+
...restProps
38
+
}: HTMLAttributes<HTMLDivElement> & {
39
+
orientation?: FieldOrientation;
40
+
} = $props();
41
+
</script>
42
+
43
+
<div
44
+
role="group"
45
+
data-slot="field"
46
+
data-orientation={orientation}
47
+
class={cn(fieldVariants({ orientation }), className)}
48
+
{...restProps}
49
+
>
50
+
{@render children?.()}
51
+
</div>
+33
apps/web/src/lib/components/ui/field/index.ts
+33
apps/web/src/lib/components/ui/field/index.ts
···
1
+
import Field from "./field.svelte";
2
+
import Set from "./field-set.svelte";
3
+
import Legend from "./field-legend.svelte";
4
+
import Group from "./field-group.svelte";
5
+
import Content from "./field-content.svelte";
6
+
import Label from "./field-label.svelte";
7
+
import Title from "./field-title.svelte";
8
+
import Description from "./field-description.svelte";
9
+
import Separator from "./field-separator.svelte";
10
+
import Error from "./field-error.svelte";
11
+
12
+
export {
13
+
Field,
14
+
Set,
15
+
Legend,
16
+
Group,
17
+
Content,
18
+
Label,
19
+
Title,
20
+
Description,
21
+
Separator,
22
+
Error,
23
+
//
24
+
Set as FieldSet,
25
+
Legend as FieldLegend,
26
+
Group as FieldGroup,
27
+
Content as FieldContent,
28
+
Label as FieldLabel,
29
+
Title as FieldTitle,
30
+
Description as FieldDescription,
31
+
Separator as FieldSeparator,
32
+
Error as FieldError,
33
+
};
+17
apps/web/src/lib/components/ui/form/form-description.svelte
+17
apps/web/src/lib/components/ui/form/form-description.svelte
···
1
+
<script lang="ts">
2
+
import * as FormPrimitive from "formsnap";
3
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: WithoutChild<FormPrimitive.DescriptionProps> = $props();
10
+
</script>
11
+
12
+
<FormPrimitive.Description
13
+
bind:ref
14
+
data-slot="form-description"
15
+
class={cn("text-muted-foreground text-sm", className)}
16
+
{...restProps}
17
+
/>
+24
apps/web/src/lib/components/ui/form/form-element-field.svelte
+24
apps/web/src/lib/components/ui/form/form-element-field.svelte
···
1
+
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPathLeaves<T>">
2
+
import * as FormPrimitive from "formsnap";
3
+
import type { FormPathLeaves } from "sveltekit-superforms";
4
+
import type { HTMLAttributes } from "svelte/elements";
5
+
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils/cn.js";
6
+
7
+
let {
8
+
ref = $bindable(null),
9
+
class: className,
10
+
form,
11
+
name,
12
+
children: childrenProp,
13
+
...restProps
14
+
}: WithoutChildren<WithElementRef<HTMLAttributes<HTMLDivElement>>> &
15
+
FormPrimitive.ElementFieldProps<T, U> = $props();
16
+
</script>
17
+
18
+
<FormPrimitive.ElementField {form} {name}>
19
+
{#snippet children({ constraints, errors, tainted, value })}
20
+
<div bind:this={ref} class={cn("space-y-2", className)} {...restProps}>
21
+
{@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })}
22
+
</div>
23
+
{/snippet}
24
+
</FormPrimitive.ElementField>
+30
apps/web/src/lib/components/ui/form/form-field-errors.svelte
+30
apps/web/src/lib/components/ui/form/form-field-errors.svelte
···
1
+
<script lang="ts">
2
+
import * as FormPrimitive from "formsnap";
3
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
errorClasses,
9
+
children: childrenProp,
10
+
...restProps
11
+
}: WithoutChild<FormPrimitive.FieldErrorsProps> & {
12
+
errorClasses?: string | undefined | null;
13
+
} = $props();
14
+
</script>
15
+
16
+
<FormPrimitive.FieldErrors
17
+
bind:ref
18
+
class={cn("text-destructive text-sm font-medium", className)}
19
+
{...restProps}
20
+
>
21
+
{#snippet children({ errors, errorProps })}
22
+
{#if childrenProp}
23
+
{@render childrenProp({ errors, errorProps })}
24
+
{:else}
25
+
{#each errors as error (error)}
26
+
<div {...errorProps} class={cn(errorClasses)}>{error}</div>
27
+
{/each}
28
+
{/if}
29
+
{/snippet}
30
+
</FormPrimitive.FieldErrors>
+29
apps/web/src/lib/components/ui/form/form-field.svelte
+29
apps/web/src/lib/components/ui/form/form-field.svelte
···
1
+
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
2
+
import * as FormPrimitive from "formsnap";
3
+
import type { FormPath } from "sveltekit-superforms";
4
+
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils/cn.js";
5
+
import type { HTMLAttributes } from "svelte/elements";
6
+
7
+
let {
8
+
ref = $bindable(null),
9
+
class: className,
10
+
form,
11
+
name,
12
+
children: childrenProp,
13
+
...restProps
14
+
}: FormPrimitive.FieldProps<T, U> &
15
+
WithoutChildren<WithElementRef<HTMLAttributes<HTMLDivElement>>> = $props();
16
+
</script>
17
+
18
+
<FormPrimitive.Field {form} {name}>
19
+
{#snippet children({ constraints, errors, tainted, value })}
20
+
<div
21
+
bind:this={ref}
22
+
data-slot="form-item"
23
+
class={cn("space-y-2", className)}
24
+
{...restProps}
25
+
>
26
+
{@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })}
27
+
</div>
28
+
{/snippet}
29
+
</FormPrimitive.Field>
+15
apps/web/src/lib/components/ui/form/form-fieldset.svelte
+15
apps/web/src/lib/components/ui/form/form-fieldset.svelte
···
1
+
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
2
+
import * as FormPrimitive from "formsnap";
3
+
import type { FormPath } from "sveltekit-superforms";
4
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
form,
10
+
name,
11
+
...restProps
12
+
}: WithoutChild<FormPrimitive.FieldsetProps<T, U>> = $props();
13
+
</script>
14
+
15
+
<FormPrimitive.Fieldset bind:ref {form} {name} class={cn("space-y-2", className)} {...restProps} />
+24
apps/web/src/lib/components/ui/form/form-label.svelte
+24
apps/web/src/lib/components/ui/form/form-label.svelte
···
1
+
<script lang="ts">
2
+
import * as FormPrimitive from "formsnap";
3
+
import { Label } from "$lib/components/ui/label/index.js";
4
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
children,
9
+
class: className,
10
+
...restProps
11
+
}: WithoutChild<FormPrimitive.LabelProps> = $props();
12
+
</script>
13
+
14
+
<FormPrimitive.Label {...restProps} bind:ref>
15
+
{#snippet child({ props })}
16
+
<Label
17
+
{...props}
18
+
data-slot="form-label"
19
+
class={cn("data-[fs-error]:text-destructive", className)}
20
+
>
21
+
{@render children?.()}
22
+
</Label>
23
+
{/snippet}
24
+
</FormPrimitive.Label>
+16
apps/web/src/lib/components/ui/form/form-legend.svelte
+16
apps/web/src/lib/components/ui/form/form-legend.svelte
···
1
+
<script lang="ts">
2
+
import * as FormPrimitive from "formsnap";
3
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: WithoutChild<FormPrimitive.LegendProps> = $props();
10
+
</script>
11
+
12
+
<FormPrimitive.Legend
13
+
bind:ref
14
+
class={cn("data-[fs-error]:text-destructive text-sm font-medium leading-none", className)}
15
+
{...restProps}
16
+
/>
+33
apps/web/src/lib/components/ui/form/index.ts
+33
apps/web/src/lib/components/ui/form/index.ts
···
1
+
import * as FormPrimitive from "formsnap";
2
+
import Description from "./form-description.svelte";
3
+
import Label from "./form-label.svelte";
4
+
import FieldErrors from "./form-field-errors.svelte";
5
+
import Field from "./form-field.svelte";
6
+
import Fieldset from "./form-fieldset.svelte";
7
+
import Legend from "./form-legend.svelte";
8
+
import ElementField from "./form-element-field.svelte";
9
+
import Button from "./form-button.svelte";
10
+
11
+
const Control = FormPrimitive.Control;
12
+
13
+
export {
14
+
Field,
15
+
Control,
16
+
Label,
17
+
Button,
18
+
FieldErrors,
19
+
Description,
20
+
Fieldset,
21
+
Legend,
22
+
ElementField,
23
+
//
24
+
Field as FormField,
25
+
Control as FormControl,
26
+
Description as FormDescription,
27
+
Label as FormLabel,
28
+
FieldErrors as FormFieldErrors,
29
+
Fieldset as FormFieldset,
30
+
Legend as FormLegend,
31
+
ElementField as FormElementField,
32
+
Button as FormButton,
33
+
};
+29
apps/web/src/lib/components/ui/hover-card/hover-card-content.svelte
+29
apps/web/src/lib/components/ui/hover-card/hover-card-content.svelte
···
1
+
<script lang="ts">
2
+
import { LinkPreview as HoverCardPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
align = "center",
9
+
sideOffset = 4,
10
+
portalProps,
11
+
...restProps
12
+
}: HoverCardPrimitive.ContentProps & {
13
+
portalProps?: HoverCardPrimitive.PortalProps;
14
+
} = $props();
15
+
</script>
16
+
17
+
<HoverCardPrimitive.Portal {...portalProps}>
18
+
<HoverCardPrimitive.Content
19
+
bind:ref
20
+
data-slot="hover-card-content"
21
+
{align}
22
+
{sideOffset}
23
+
class={cn(
24
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 outline-hidden z-50 mt-3 w-64 rounded-md border p-4 shadow-md outline-none",
25
+
className
26
+
)}
27
+
{...restProps}
28
+
/>
29
+
</HoverCardPrimitive.Portal>
+7
apps/web/src/lib/components/ui/hover-card/hover-card-trigger.svelte
+7
apps/web/src/lib/components/ui/hover-card/hover-card-trigger.svelte
+14
apps/web/src/lib/components/ui/hover-card/index.ts
+14
apps/web/src/lib/components/ui/hover-card/index.ts
···
1
+
import { LinkPreview as HoverCardPrimitive } from "bits-ui";
2
+
import Content from "./hover-card-content.svelte";
3
+
import Trigger from "./hover-card-trigger.svelte";
4
+
5
+
const Root = HoverCardPrimitive.Root;
6
+
7
+
export {
8
+
Root,
9
+
Content,
10
+
Trigger,
11
+
Root as HoverCard,
12
+
Content as HoverCardContent,
13
+
Trigger as HoverCardTrigger,
14
+
};
+22
apps/web/src/lib/components/ui/input-group/index.ts
+22
apps/web/src/lib/components/ui/input-group/index.ts
···
1
+
import Root from "./input-group.svelte";
2
+
import Addon from "./input-group-addon.svelte";
3
+
import Button from "./input-group-button.svelte";
4
+
import Input from "./input-group-input.svelte";
5
+
import Text from "./input-group-text.svelte";
6
+
import Textarea from "./input-group-textarea.svelte";
7
+
8
+
export {
9
+
Root,
10
+
Addon,
11
+
Button,
12
+
Input,
13
+
Text,
14
+
Textarea,
15
+
//
16
+
Root as InputGroup,
17
+
Addon as InputGroupAddon,
18
+
Button as InputGroupButton,
19
+
Input as InputGroupInput,
20
+
Text as InputGroupText,
21
+
Textarea as InputGroupTextarea,
22
+
};
+53
apps/web/src/lib/components/ui/input-group/input-group-addon.svelte
+53
apps/web/src/lib/components/ui/input-group/input-group-addon.svelte
···
1
+
<script lang="ts" module>
2
+
import { tv, type VariantProps } from "tailwind-variants";
3
+
const inputGroupAddonVariants = tv({
4
+
base: "text-muted-foreground flex h-auto cursor-text select-none items-center justify-center gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
5
+
variants: {
6
+
align: {
7
+
"inline-start":
8
+
"order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
9
+
"inline-end":
10
+
"order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]",
11
+
"block-start":
12
+
"[.border-b]:pb-3 order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5",
13
+
"block-end":
14
+
"[.border-t]:pt-3 order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5",
15
+
},
16
+
},
17
+
defaultVariants: {
18
+
align: "inline-start",
19
+
},
20
+
});
21
+
22
+
export type InputGroupAddonAlign = VariantProps<typeof inputGroupAddonVariants>["align"];
23
+
</script>
24
+
25
+
<script lang="ts">
26
+
import { cn } from "$lib/utils/cn.js";
27
+
import type { HTMLAttributes } from "svelte/elements";
28
+
29
+
let {
30
+
class: className,
31
+
children,
32
+
align = "inline-start",
33
+
...restProps
34
+
}: HTMLAttributes<HTMLDivElement> & {
35
+
align?: InputGroupAddonAlign;
36
+
} = $props();
37
+
</script>
38
+
39
+
<div
40
+
role="group"
41
+
data-slot="input-group-addon"
42
+
data-align={align}
43
+
class={cn(inputGroupAddonVariants({ align }), className)}
44
+
onclick={(e) => {
45
+
if ((e.target as HTMLElement).closest("button")) {
46
+
return;
47
+
}
48
+
e.currentTarget.parentElement?.querySelector("input")?.focus();
49
+
}}
50
+
{...restProps}
51
+
>
52
+
{@render children?.()}
53
+
</div>
+21
apps/web/src/lib/components/ui/input-group/input-group-input.svelte
+21
apps/web/src/lib/components/ui/input-group/input-group-input.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { ComponentProps } from "svelte";
4
+
import { Input } from "$lib/components/ui/input/index.js";
5
+
6
+
let {
7
+
value = $bindable(),
8
+
class: className,
9
+
...props
10
+
}: ComponentProps<typeof Input> = $props();
11
+
</script>
12
+
13
+
<Input
14
+
data-slot="input-group-control"
15
+
class={cn(
16
+
"flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent",
17
+
className
18
+
)}
19
+
bind:value
20
+
{...props}
21
+
/>
+16
apps/web/src/lib/components/ui/input-group/input-group-text.svelte
+16
apps/web/src/lib/components/ui/input-group/input-group-text.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLSpanElement> = $props();
6
+
</script>
7
+
8
+
<span
9
+
class={cn(
10
+
"text-muted-foreground flex items-center gap-2 text-sm [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
11
+
className
12
+
)}
13
+
{...restProps}
14
+
>
15
+
{@render children?.()}
16
+
</span>
+21
apps/web/src/lib/components/ui/input-group/input-group-textarea.svelte
+21
apps/web/src/lib/components/ui/input-group/input-group-textarea.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import { Textarea } from "$lib/components/ui/textarea/index.js";
4
+
import type { ComponentProps } from "svelte";
5
+
6
+
let {
7
+
value = $bindable(),
8
+
class: className,
9
+
...props
10
+
}: ComponentProps<typeof Textarea> = $props();
11
+
</script>
12
+
13
+
<Textarea
14
+
data-slot="input-group-control"
15
+
class={cn(
16
+
"flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent",
17
+
className
18
+
)}
19
+
bind:value
20
+
{...props}
21
+
/>
+32
apps/web/src/lib/components/ui/input-group/input-group.svelte
+32
apps/web/src/lib/components/ui/input-group/input-group.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...props }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="input-group"
10
+
role="group"
11
+
class={cn(
12
+
"group/input-group border-input dark:bg-input/30 shadow-xs relative flex w-full items-center rounded-md border outline-none transition-[color,box-shadow]",
13
+
"h-9 has-[>textarea]:h-auto",
14
+
15
+
// Variants based on alignment.
16
+
"has-[>[data-align=inline-start]]:[&>input]:pl-2",
17
+
"has-[>[data-align=inline-end]]:[&>input]:pr-2",
18
+
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
19
+
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
20
+
21
+
// Focus state.
22
+
"has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]",
23
+
24
+
// Error state.
25
+
"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
26
+
27
+
className
28
+
)}
29
+
{...props}
30
+
>
31
+
{@render children?.()}
32
+
</div>
+15
apps/web/src/lib/components/ui/input-otp/index.ts
+15
apps/web/src/lib/components/ui/input-otp/index.ts
···
1
+
import Root from "./input-otp.svelte";
2
+
import Group from "./input-otp-group.svelte";
3
+
import Slot from "./input-otp-slot.svelte";
4
+
import Separator from "./input-otp-separator.svelte";
5
+
6
+
export {
7
+
Root,
8
+
Group,
9
+
Slot,
10
+
Separator,
11
+
Root as InputOTP,
12
+
Group as InputOTPGroup,
13
+
Slot as InputOTPSlot,
14
+
Separator as InputOTPSeparator,
15
+
};
+20
apps/web/src/lib/components/ui/input-otp/input-otp-group.svelte
+20
apps/web/src/lib/components/ui/input-otp/input-otp-group.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="input-otp-group"
16
+
class={cn("flex items-center", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+19
apps/web/src/lib/components/ui/input-otp/input-otp-separator.svelte
+19
apps/web/src/lib/components/ui/input-otp/input-otp-separator.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import type { WithElementRef } from "$lib/utils/cn.js";
4
+
import DotIcon from "@lucide/svelte/icons/dot";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div bind:this={ref} data-slot="input-otp-separator" role="separator" {...restProps}>
14
+
{#if children}
15
+
{@render children?.()}
16
+
{:else}
17
+
<DotIcon />
18
+
{/if}
19
+
</div>
+31
apps/web/src/lib/components/ui/input-otp/input-otp-slot.svelte
+31
apps/web/src/lib/components/ui/input-otp/input-otp-slot.svelte
···
1
+
<script lang="ts">
2
+
import { PinInput as InputOTPPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
cell,
8
+
class: className,
9
+
...restProps
10
+
}: InputOTPPrimitive.CellProps = $props();
11
+
</script>
12
+
13
+
<InputOTPPrimitive.Cell
14
+
{cell}
15
+
bind:ref
16
+
data-slot="input-otp-slot"
17
+
class={cn(
18
+
"border-input aria-invalid:border-destructive dark:bg-input/30 relative flex size-9 items-center justify-center border-y border-r text-sm outline-none transition-all first:rounded-l-md first:border-l last:rounded-r-md",
19
+
cell.isActive &&
20
+
"border-ring ring-ring/50 aria-invalid:border-destructive dark:aria-invalid:ring-destructive/40 aria-invalid:ring-destructive/20 ring-offset-background z-10 ring-[3px]",
21
+
className
22
+
)}
23
+
{...restProps}
24
+
>
25
+
{cell.char}
26
+
{#if cell.hasFakeCaret}
27
+
<div class="pointer-events-none absolute inset-0 flex items-center justify-center">
28
+
<div class="animate-caret-blink bg-foreground h-4 w-px duration-1000"></div>
29
+
</div>
30
+
{/if}
31
+
</InputOTPPrimitive.Cell>
+22
apps/web/src/lib/components/ui/input-otp/input-otp.svelte
+22
apps/web/src/lib/components/ui/input-otp/input-otp.svelte
···
1
+
<script lang="ts">
2
+
import { PinInput as InputOTPPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
value = $bindable(""),
9
+
...restProps
10
+
}: InputOTPPrimitive.RootProps = $props();
11
+
</script>
12
+
13
+
<InputOTPPrimitive.Root
14
+
bind:ref
15
+
bind:value
16
+
data-slot="input-otp"
17
+
class={cn(
18
+
"has-disabled:opacity-50 flex items-center gap-2 [&_input]:disabled:cursor-not-allowed",
19
+
className
20
+
)}
21
+
{...restProps}
22
+
/>
+7
apps/web/src/lib/components/ui/input/index.ts
+7
apps/web/src/lib/components/ui/input/index.ts
+52
apps/web/src/lib/components/ui/input/input.svelte
+52
apps/web/src/lib/components/ui/input/input.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
6
+
7
+
type Props = WithElementRef<
8
+
Omit<HTMLInputAttributes, "type"> &
9
+
({ type: "file"; files?: FileList } | { type?: InputType; files?: undefined })
10
+
>;
11
+
12
+
let {
13
+
ref = $bindable(null),
14
+
value = $bindable(),
15
+
type,
16
+
files = $bindable(),
17
+
class: className,
18
+
"data-slot": dataSlot = "input",
19
+
...restProps
20
+
}: Props = $props();
21
+
</script>
22
+
23
+
{#if type === "file"}
24
+
<input
25
+
bind:this={ref}
26
+
data-slot={dataSlot}
27
+
class={cn(
28
+
"selection:bg-primary dark:bg-input/30 selection:text-primary-foreground border-input ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 pt-1.5 text-sm font-medium outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50",
29
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
30
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
31
+
className
32
+
)}
33
+
type="file"
34
+
bind:files
35
+
bind:value
36
+
{...restProps}
37
+
/>
38
+
{:else}
39
+
<input
40
+
bind:this={ref}
41
+
data-slot={dataSlot}
42
+
class={cn(
43
+
"border-input bg-background selection:bg-primary dark:bg-input/30 selection:text-primary-foreground ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
44
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
45
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
46
+
className
47
+
)}
48
+
{type}
49
+
bind:value
50
+
{...restProps}
51
+
/>
52
+
{/if}
+34
apps/web/src/lib/components/ui/item/index.ts
+34
apps/web/src/lib/components/ui/item/index.ts
···
1
+
import Root from "./item.svelte";
2
+
import Group from "./item-group.svelte";
3
+
import Separator from "./item-separator.svelte";
4
+
import Header from "./item-header.svelte";
5
+
import Footer from "./item-footer.svelte";
6
+
import Content from "./item-content.svelte";
7
+
import Title from "./item-title.svelte";
8
+
import Description from "./item-description.svelte";
9
+
import Actions from "./item-actions.svelte";
10
+
import Media from "./item-media.svelte";
11
+
12
+
export {
13
+
Root,
14
+
Group,
15
+
Separator,
16
+
Header,
17
+
Footer,
18
+
Content,
19
+
Title,
20
+
Description,
21
+
Actions,
22
+
Media,
23
+
//
24
+
Root as Item,
25
+
Group as ItemGroup,
26
+
Separator as ItemSeparator,
27
+
Header as ItemHeader,
28
+
Footer as ItemFooter,
29
+
Content as ItemContent,
30
+
Title as ItemTitle,
31
+
Description as ItemDescription,
32
+
Actions as ItemActions,
33
+
Media as ItemMedia,
34
+
};
+10
apps/web/src/lib/components/ui/item/item-actions.svelte
+10
apps/web/src/lib/components/ui/item/item-actions.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div data-slot="item-actions" class={cn("flex items-center gap-2", className)} {...restProps}>
9
+
{@render children?.()}
10
+
</div>
+14
apps/web/src/lib/components/ui/item/item-content.svelte
+14
apps/web/src/lib/components/ui/item/item-content.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="item-content"
10
+
class={cn("flex flex-1 flex-col gap-1 [&+[data-slot=item-content]]:flex-none", className)}
11
+
{...restProps}
12
+
>
13
+
{@render children?.()}
14
+
</div>
+22
apps/web/src/lib/components/ui/item/item-description.svelte
+22
apps/web/src/lib/components/ui/item/item-description.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
class: className,
7
+
children,
8
+
...restProps
9
+
}: HTMLAttributes<HTMLParagraphElement> = $props();
10
+
</script>
11
+
12
+
<p
13
+
data-slot="item-description"
14
+
class={cn(
15
+
"text-muted-foreground line-clamp-2 text-balance text-sm font-normal leading-normal",
16
+
"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
>
21
+
{@render children?.()}
22
+
</p>
+15
apps/web/src/lib/components/ui/item/item-group.svelte
+15
apps/web/src/lib/components/ui/item/item-group.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
role="list"
10
+
data-slot="item-group"
11
+
class={cn("group/item-group flex flex-col", className)}
12
+
{...restProps}
13
+
>
14
+
{@render children?.()}
15
+
</div>
+14
apps/web/src/lib/components/ui/item/item-header.svelte
+14
apps/web/src/lib/components/ui/item/item-header.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="item-header"
10
+
class={cn("flex basis-full items-center justify-between gap-2", className)}
11
+
{...restProps}
12
+
>
13
+
{@render children?.()}
14
+
</div>
+40
apps/web/src/lib/components/ui/item/item-media.svelte
+40
apps/web/src/lib/components/ui/item/item-media.svelte
···
1
+
<script lang="ts" module>
2
+
import { tv, type VariantProps } from "tailwind-variants";
3
+
4
+
const itemMediaVariants = tv({
5
+
base: "flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:translate-y-0.5 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none",
6
+
variants: {
7
+
variant: {
8
+
default: "bg-transparent",
9
+
icon: "bg-muted size-8 rounded-sm border [&_svg:not([class*='size-'])]:size-4",
10
+
image: "size-10 overflow-hidden rounded-sm [&_img]:size-full [&_img]:object-cover",
11
+
},
12
+
},
13
+
defaultVariants: {
14
+
variant: "default",
15
+
},
16
+
});
17
+
18
+
export type ItemMediaVariant = VariantProps<typeof itemMediaVariants>["variant"];
19
+
</script>
20
+
21
+
<script lang="ts">
22
+
import { cn } from "$lib/utils/cn.js";
23
+
import type { HTMLAttributes } from "svelte/elements";
24
+
25
+
let {
26
+
class: className,
27
+
children,
28
+
variant = "default",
29
+
...restProps
30
+
}: HTMLAttributes<HTMLDivElement> & { variant?: ItemMediaVariant } = $props();
31
+
</script>
32
+
33
+
<div
34
+
data-slot="item-media"
35
+
data-variant={variant}
36
+
class={cn(itemMediaVariants({ variant }), className)}
37
+
{...restProps}
38
+
>
39
+
{@render children?.()}
40
+
</div>
+14
apps/web/src/lib/components/ui/item/item-separator.svelte
+14
apps/web/src/lib/components/ui/item/item-separator.svelte
···
1
+
<script lang="ts">
2
+
import { Separator } from "$lib/components/ui/separator/index.js";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
import type { ComponentProps } from "svelte";
5
+
6
+
let { class: className, ...restProps }: ComponentProps<typeof Separator> = $props();
7
+
</script>
8
+
9
+
<Separator
10
+
data-slot="item-separator"
11
+
orientation="horizontal"
12
+
class={cn("my-0", className)}
13
+
{...restProps}
14
+
/>
+14
apps/web/src/lib/components/ui/item/item-title.svelte
+14
apps/web/src/lib/components/ui/item/item-title.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLDivElement> = $props();
6
+
</script>
7
+
8
+
<div
9
+
data-slot="item-title"
10
+
class={cn("flex w-fit items-center gap-2 text-sm font-medium leading-snug", className)}
11
+
{...restProps}
12
+
>
13
+
{@render children?.()}
14
+
</div>
+61
apps/web/src/lib/components/ui/item/item.svelte
+61
apps/web/src/lib/components/ui/item/item.svelte
···
1
+
<script lang="ts" module>
2
+
import { tv, type VariantProps } from "tailwind-variants";
3
+
4
+
const itemVariants = tv({
5
+
base: "group/item [a]:hover:bg-accent/50 [a]:transition-colors focus-visible:border-ring focus-visible:ring-ring/50 flex flex-wrap items-center rounded-md border border-transparent text-sm outline-none transition-colors duration-100 focus-visible:ring-[3px]",
6
+
variants: {
7
+
variant: {
8
+
default: "bg-transparent",
9
+
outline: "border-border",
10
+
muted: "bg-muted/50",
11
+
},
12
+
size: {
13
+
default: "gap-4 p-4",
14
+
sm: "gap-2.5 px-4 py-3",
15
+
},
16
+
},
17
+
defaultVariants: {
18
+
variant: "default",
19
+
size: "default",
20
+
},
21
+
});
22
+
23
+
export type ItemSize = VariantProps<typeof itemVariants>["size"];
24
+
export type ItemVariant = VariantProps<typeof itemVariants>["variant"];
25
+
</script>
26
+
27
+
<script lang="ts">
28
+
import { cn } from "$lib/utils/cn.js";
29
+
import type { HTMLAttributes } from "svelte/elements";
30
+
import type { Snippet } from "svelte";
31
+
32
+
let {
33
+
class: className,
34
+
child,
35
+
variant,
36
+
size,
37
+
...restProps
38
+
}: HTMLAttributes<HTMLDivElement> & {
39
+
child?: Snippet<[{ props: Record<string, unknown> }]>;
40
+
variant?: ItemVariant;
41
+
size?: ItemSize;
42
+
} = $props();
43
+
44
+
const classes = $derived(cn(itemVariants({ variant, size }), className));
45
+
46
+
const mergedProps = $derived({
47
+
class: classes,
48
+
"data-slot": "item",
49
+
"data-variant": variant,
50
+
"data-size": size,
51
+
...restProps,
52
+
});
53
+
</script>
54
+
55
+
{#if child}
56
+
{@render child({ props: mergedProps })}
57
+
{:else}
58
+
<div {...mergedProps}>
59
+
{@render mergedProps.children?.()}
60
+
</div>
61
+
{/if}
+10
apps/web/src/lib/components/ui/kbd/index.ts
+10
apps/web/src/lib/components/ui/kbd/index.ts
+10
apps/web/src/lib/components/ui/kbd/kbd-group.svelte
+10
apps/web/src/lib/components/ui/kbd/kbd-group.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLElement> = $props();
6
+
</script>
7
+
8
+
<kbd data-slot="kbd-group" class={cn("inline-flex items-center gap-1", className)} {...restProps}>
9
+
{@render children?.()}
10
+
</kbd>
+19
apps/web/src/lib/components/ui/kbd/kbd.svelte
+19
apps/web/src/lib/components/ui/kbd/kbd.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let { class: className, children, ...restProps }: HTMLAttributes<HTMLElement> = $props();
6
+
</script>
7
+
8
+
<kbd
9
+
data-slot="kbd"
10
+
class={cn(
11
+
"bg-muted text-muted-foreground pointer-events-none inline-flex h-5 w-fit min-w-5 select-none items-center justify-center gap-1 rounded-sm px-1 font-sans text-xs font-medium",
12
+
"[&_svg:not([class*='size-'])]:size-3",
13
+
"[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
14
+
className
15
+
)}
16
+
{...restProps}
17
+
>
18
+
{@render children?.()}
19
+
</kbd>
+7
apps/web/src/lib/components/ui/label/index.ts
+7
apps/web/src/lib/components/ui/label/index.ts
+20
apps/web/src/lib/components/ui/label/label.svelte
+20
apps/web/src/lib/components/ui/label/label.svelte
···
1
+
<script lang="ts">
2
+
import { Label as LabelPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: LabelPrimitive.RootProps = $props();
10
+
</script>
11
+
12
+
<LabelPrimitive.Root
13
+
bind:ref
14
+
data-slot="label"
15
+
class={cn(
16
+
"flex select-none items-center gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+25
apps/web/src/lib/components/ui/pagination/index.ts
+25
apps/web/src/lib/components/ui/pagination/index.ts
···
1
+
import Root from "./pagination.svelte";
2
+
import Content from "./pagination-content.svelte";
3
+
import Item from "./pagination-item.svelte";
4
+
import Link from "./pagination-link.svelte";
5
+
import PrevButton from "./pagination-prev-button.svelte";
6
+
import NextButton from "./pagination-next-button.svelte";
7
+
import Ellipsis from "./pagination-ellipsis.svelte";
8
+
9
+
export {
10
+
Root,
11
+
Content,
12
+
Item,
13
+
Link,
14
+
PrevButton,
15
+
NextButton,
16
+
Ellipsis,
17
+
//
18
+
Root as Pagination,
19
+
Content as PaginationContent,
20
+
Item as PaginationItem,
21
+
Link as PaginationLink,
22
+
PrevButton as PaginationPrevButton,
23
+
NextButton as PaginationNextButton,
24
+
Ellipsis as PaginationEllipsis,
25
+
};
+20
apps/web/src/lib/components/ui/pagination/pagination-content.svelte
+20
apps/web/src/lib/components/ui/pagination/pagination-content.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLUListElement>> = $props();
11
+
</script>
12
+
13
+
<ul
14
+
bind:this={ref}
15
+
data-slot="pagination-content"
16
+
class={cn("flex flex-row items-center gap-1", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</ul>
+22
apps/web/src/lib/components/ui/pagination/pagination-ellipsis.svelte
+22
apps/web/src/lib/components/ui/pagination/pagination-ellipsis.svelte
···
1
+
<script lang="ts">
2
+
import EllipsisIcon from "@lucide/svelte/icons/ellipsis";
3
+
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils/cn.js";
4
+
import type { HTMLAttributes } from "svelte/elements";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
...restProps
10
+
}: WithoutChildren<WithElementRef<HTMLAttributes<HTMLSpanElement>>> = $props();
11
+
</script>
12
+
13
+
<span
14
+
bind:this={ref}
15
+
aria-hidden="true"
16
+
data-slot="pagination-ellipsis"
17
+
class={cn("flex size-9 items-center justify-center", className)}
18
+
{...restProps}
19
+
>
20
+
<EllipsisIcon class="size-4" />
21
+
<span class="sr-only">More pages</span>
22
+
</span>
+14
apps/web/src/lib/components/ui/pagination/pagination-item.svelte
+14
apps/web/src/lib/components/ui/pagination/pagination-item.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLLiAttributes } from "svelte/elements";
3
+
import type { WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
children,
8
+
...restProps
9
+
}: WithElementRef<HTMLLiAttributes> = $props();
10
+
</script>
11
+
12
+
<li bind:this={ref} data-slot="pagination-item" {...restProps}>
13
+
{@render children?.()}
14
+
</li>
+39
apps/web/src/lib/components/ui/pagination/pagination-link.svelte
+39
apps/web/src/lib/components/ui/pagination/pagination-link.svelte
···
1
+
<script lang="ts">
2
+
import { Pagination as PaginationPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
import { type Props, buttonVariants } from "$lib/components/ui/button/index.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
size = "icon",
10
+
isActive,
11
+
page,
12
+
children,
13
+
...restProps
14
+
}: PaginationPrimitive.PageProps &
15
+
Props & {
16
+
isActive: boolean;
17
+
} = $props();
18
+
</script>
19
+
20
+
{#snippet Fallback()}
21
+
{page.value}
22
+
{/snippet}
23
+
24
+
<PaginationPrimitive.Page
25
+
bind:ref
26
+
{page}
27
+
aria-current={isActive ? "page" : undefined}
28
+
data-slot="pagination-link"
29
+
data-active={isActive}
30
+
class={cn(
31
+
buttonVariants({
32
+
variant: isActive ? "outline" : "ghost",
33
+
size,
34
+
}),
35
+
className
36
+
)}
37
+
children={children || Fallback}
38
+
{...restProps}
39
+
/>
+28
apps/web/src/lib/components/ui/pagination/pagination.svelte
+28
apps/web/src/lib/components/ui/pagination/pagination.svelte
···
1
+
<script lang="ts">
2
+
import { Pagination as PaginationPrimitive } from "bits-ui";
3
+
4
+
import { cn } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
count = 0,
10
+
perPage = 10,
11
+
page = $bindable(1),
12
+
siblingCount = 1,
13
+
...restProps
14
+
}: PaginationPrimitive.RootProps = $props();
15
+
</script>
16
+
17
+
<PaginationPrimitive.Root
18
+
bind:ref
19
+
bind:page
20
+
role="navigation"
21
+
aria-label="pagination"
22
+
data-slot="pagination"
23
+
class={cn("mx-auto flex w-full justify-center", className)}
24
+
{count}
25
+
{perPage}
26
+
{siblingCount}
27
+
{...restProps}
28
+
/>
+17
apps/web/src/lib/components/ui/popover/index.ts
+17
apps/web/src/lib/components/ui/popover/index.ts
···
1
+
import { Popover as PopoverPrimitive } from "bits-ui";
2
+
import Content from "./popover-content.svelte";
3
+
import Trigger from "./popover-trigger.svelte";
4
+
const Root = PopoverPrimitive.Root;
5
+
const Close = PopoverPrimitive.Close;
6
+
7
+
export {
8
+
Root,
9
+
Content,
10
+
Trigger,
11
+
Close,
12
+
//
13
+
Root as Popover,
14
+
Content as PopoverContent,
15
+
Trigger as PopoverTrigger,
16
+
Close as PopoverClose,
17
+
};
+29
apps/web/src/lib/components/ui/popover/popover-content.svelte
+29
apps/web/src/lib/components/ui/popover/popover-content.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import { Popover as PopoverPrimitive } from "bits-ui";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
sideOffset = 4,
9
+
align = "center",
10
+
portalProps,
11
+
...restProps
12
+
}: PopoverPrimitive.ContentProps & {
13
+
portalProps?: PopoverPrimitive.PortalProps;
14
+
} = $props();
15
+
</script>
16
+
17
+
<PopoverPrimitive.Portal {...portalProps}>
18
+
<PopoverPrimitive.Content
19
+
bind:ref
20
+
data-slot="popover-content"
21
+
{sideOffset}
22
+
{align}
23
+
class={cn(
24
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--bits-popover-content-transform-origin) outline-hidden z-50 w-72 rounded-md border p-4 shadow-md",
25
+
className
26
+
)}
27
+
{...restProps}
28
+
/>
29
+
</PopoverPrimitive.Portal>
+17
apps/web/src/lib/components/ui/popover/popover-trigger.svelte
+17
apps/web/src/lib/components/ui/popover/popover-trigger.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import { Popover as PopoverPrimitive } from "bits-ui";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: PopoverPrimitive.TriggerProps = $props();
10
+
</script>
11
+
12
+
<PopoverPrimitive.Trigger
13
+
bind:ref
14
+
data-slot="popover-trigger"
15
+
class={cn("", className)}
16
+
{...restProps}
17
+
/>
+7
apps/web/src/lib/components/ui/progress/index.ts
+7
apps/web/src/lib/components/ui/progress/index.ts
+27
apps/web/src/lib/components/ui/progress/progress.svelte
+27
apps/web/src/lib/components/ui/progress/progress.svelte
···
1
+
<script lang="ts">
2
+
import { Progress as ProgressPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
max = 100,
9
+
value,
10
+
...restProps
11
+
}: WithoutChildrenOrChild<ProgressPrimitive.RootProps> = $props();
12
+
</script>
13
+
14
+
<ProgressPrimitive.Root
15
+
bind:ref
16
+
data-slot="progress"
17
+
class={cn("bg-primary/20 relative h-2 w-full overflow-hidden rounded-full", className)}
18
+
{value}
19
+
{max}
20
+
{...restProps}
21
+
>
22
+
<div
23
+
data-slot="progress-indicator"
24
+
class="bg-primary h-full w-full flex-1 transition-all"
25
+
style="transform: translateX(-{100 - (100 * (value ?? 0)) / (max ?? 1)}%)"
26
+
></div>
27
+
</ProgressPrimitive.Root>
+10
apps/web/src/lib/components/ui/radio-group/index.ts
+10
apps/web/src/lib/components/ui/radio-group/index.ts
+31
apps/web/src/lib/components/ui/radio-group/radio-group-item.svelte
+31
apps/web/src/lib/components/ui/radio-group/radio-group-item.svelte
···
1
+
<script lang="ts">
2
+
import { RadioGroup as RadioGroupPrimitive } from "bits-ui";
3
+
import CircleIcon from "@lucide/svelte/icons/circle";
4
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
...restProps
10
+
}: WithoutChildrenOrChild<RadioGroupPrimitive.ItemProps> = $props();
11
+
</script>
12
+
13
+
<RadioGroupPrimitive.Item
14
+
bind:ref
15
+
data-slot="radio-group-item"
16
+
class={cn(
17
+
"border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 shadow-xs aspect-square size-4 shrink-0 rounded-full border outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
>
22
+
{#snippet children({ checked })}
23
+
<div data-slot="radio-group-indicator" class="relative flex items-center justify-center">
24
+
{#if checked}
25
+
<CircleIcon
26
+
class="fill-primary absolute left-1/2 top-1/2 size-2 -translate-x-1/2 -translate-y-1/2"
27
+
/>
28
+
{/if}
29
+
</div>
30
+
{/snippet}
31
+
</RadioGroupPrimitive.Item>
+19
apps/web/src/lib/components/ui/radio-group/radio-group.svelte
+19
apps/web/src/lib/components/ui/radio-group/radio-group.svelte
···
1
+
<script lang="ts">
2
+
import { RadioGroup as RadioGroupPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
value = $bindable(""),
9
+
...restProps
10
+
}: RadioGroupPrimitive.RootProps = $props();
11
+
</script>
12
+
13
+
<RadioGroupPrimitive.Root
14
+
bind:ref
15
+
bind:value
16
+
data-slot="radio-group"
17
+
class={cn("grid gap-3", className)}
18
+
{...restProps}
19
+
/>
+42
apps/web/src/lib/components/ui/range-calendar/index.ts
+42
apps/web/src/lib/components/ui/range-calendar/index.ts
···
1
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
2
+
import Root from "./range-calendar.svelte";
3
+
import Cell from "./range-calendar-cell.svelte";
4
+
import Day from "./range-calendar-day.svelte";
5
+
import Grid from "./range-calendar-grid.svelte";
6
+
import Header from "./range-calendar-header.svelte";
7
+
import Months from "./range-calendar-months.svelte";
8
+
import GridRow from "./range-calendar-grid-row.svelte";
9
+
import Heading from "./range-calendar-heading.svelte";
10
+
import HeadCell from "./range-calendar-head-cell.svelte";
11
+
import NextButton from "./range-calendar-next-button.svelte";
12
+
import PrevButton from "./range-calendar-prev-button.svelte";
13
+
import MonthSelect from "./range-calendar-month-select.svelte";
14
+
import YearSelect from "./range-calendar-year-select.svelte";
15
+
import Caption from "./range-calendar-caption.svelte";
16
+
import Nav from "./range-calendar-nav.svelte";
17
+
import Month from "./range-calendar-month.svelte";
18
+
19
+
const GridHead = RangeCalendarPrimitive.GridHead;
20
+
const GridBody = RangeCalendarPrimitive.GridBody;
21
+
22
+
export {
23
+
Day,
24
+
Cell,
25
+
Grid,
26
+
Header,
27
+
Months,
28
+
GridRow,
29
+
Heading,
30
+
GridBody,
31
+
GridHead,
32
+
HeadCell,
33
+
NextButton,
34
+
PrevButton,
35
+
MonthSelect,
36
+
YearSelect,
37
+
Caption,
38
+
Nav,
39
+
Month,
40
+
//
41
+
Root as RangeCalendar,
42
+
};
+76
apps/web/src/lib/components/ui/range-calendar/range-calendar-caption.svelte
+76
apps/web/src/lib/components/ui/range-calendar/range-calendar-caption.svelte
···
1
+
<script lang="ts">
2
+
import type { ComponentProps } from "svelte";
3
+
import type RangeCalendar from "./range-calendar.svelte";
4
+
import RangeCalendarMonthSelect from "./range-calendar-month-select.svelte";
5
+
import RangeCalendarYearSelect from "./range-calendar-year-select.svelte";
6
+
import { DateFormatter, getLocalTimeZone, type DateValue } from "@internationalized/date";
7
+
8
+
let {
9
+
captionLayout,
10
+
months,
11
+
monthFormat,
12
+
years,
13
+
yearFormat,
14
+
month,
15
+
locale,
16
+
placeholder = $bindable(),
17
+
monthIndex = 0,
18
+
}: {
19
+
captionLayout: ComponentProps<typeof RangeCalendar>["captionLayout"];
20
+
months: ComponentProps<typeof RangeCalendarMonthSelect>["months"];
21
+
monthFormat: ComponentProps<typeof RangeCalendarMonthSelect>["monthFormat"];
22
+
years: ComponentProps<typeof RangeCalendarYearSelect>["years"];
23
+
yearFormat: ComponentProps<typeof RangeCalendarYearSelect>["yearFormat"];
24
+
month: DateValue;
25
+
placeholder: DateValue | undefined;
26
+
locale: string;
27
+
monthIndex: number;
28
+
} = $props();
29
+
30
+
function formatYear(date: DateValue) {
31
+
const dateObj = date.toDate(getLocalTimeZone());
32
+
if (typeof yearFormat === "function") return yearFormat(dateObj.getFullYear());
33
+
return new DateFormatter(locale, { year: yearFormat }).format(dateObj);
34
+
}
35
+
36
+
function formatMonth(date: DateValue) {
37
+
const dateObj = date.toDate(getLocalTimeZone());
38
+
if (typeof monthFormat === "function") return monthFormat(dateObj.getMonth() + 1);
39
+
return new DateFormatter(locale, { month: monthFormat }).format(dateObj);
40
+
}
41
+
</script>
42
+
43
+
{#snippet MonthSelect()}
44
+
<RangeCalendarMonthSelect
45
+
{months}
46
+
{monthFormat}
47
+
value={month.month}
48
+
onchange={(e) => {
49
+
if (!placeholder) return;
50
+
const v = Number.parseInt(e.currentTarget.value);
51
+
const newPlaceholder = placeholder.set({ month: v });
52
+
placeholder = newPlaceholder.subtract({ months: monthIndex });
53
+
}}
54
+
/>
55
+
{/snippet}
56
+
57
+
{#snippet YearSelect()}
58
+
<RangeCalendarYearSelect {years} {yearFormat} value={month.year} />
59
+
{/snippet}
60
+
61
+
{#if captionLayout === "dropdown"}
62
+
{@render MonthSelect()}
63
+
{@render YearSelect()}
64
+
{:else if captionLayout === "dropdown-months"}
65
+
{@render MonthSelect()}
66
+
{#if placeholder}
67
+
{formatYear(placeholder)}
68
+
{/if}
69
+
{:else if captionLayout === "dropdown-years"}
70
+
{#if placeholder}
71
+
{formatMonth(placeholder)}
72
+
{/if}
73
+
{@render YearSelect()}
74
+
{:else}
75
+
{formatMonth(month)} {formatYear(month)}
76
+
{/if}
+19
apps/web/src/lib/components/ui/range-calendar/range-calendar-cell.svelte
+19
apps/web/src/lib/components/ui/range-calendar/range-calendar-cell.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: RangeCalendarPrimitive.CellProps = $props();
10
+
</script>
11
+
12
+
<RangeCalendarPrimitive.Cell
13
+
bind:ref
14
+
class={cn(
15
+
"size-(--cell-size) dark:[&:has([data-range-start])]:hover:bg-accent dark:[&:has([data-range-end])]:hover:bg-accent [&:has([data-range-middle])]:bg-accent dark:[&:has([data-range-middle])]:hover:bg-accent/50 [&:has([data-selected])]:bg-accent relative p-0 text-center text-sm focus-within:z-20 data-[range-middle]:rounded-r-md [&:first-child[data-selected]_[data-bits-day]]:rounded-l-md [&:has([data-range-end])]:rounded-r-md [&:has([data-range-middle])]:rounded-none first:[&:has([data-range-middle])]:rounded-l-md last:[&:has([data-range-middle])]:rounded-r-md [&:has([data-range-start])]:rounded-l-md [&:last-child[data-selected]_[data-bits-day]]:rounded-r-md",
16
+
className
17
+
)}
18
+
{...restProps}
19
+
/>
+39
apps/web/src/lib/components/ui/range-calendar/range-calendar-day.svelte
+39
apps/web/src/lib/components/ui/range-calendar/range-calendar-day.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { buttonVariants } from "$lib/components/ui/button/index.js";
4
+
import { cn } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
...restProps
10
+
}: RangeCalendarPrimitive.DayProps = $props();
11
+
</script>
12
+
13
+
<RangeCalendarPrimitive.Day
14
+
bind:ref
15
+
class={cn(
16
+
buttonVariants({ variant: "ghost" }),
17
+
"size-(--cell-size) flex select-none flex-col items-center justify-center gap-1 whitespace-nowrap p-0 font-normal leading-none",
18
+
"[&[data-today]:not([data-selected])]:bg-accent [&[data-today]:not([data-selected])]:text-accent-foreground [&[data-today][data-disabled]]:text-muted-foreground data-[range-middle]:rounded-none",
19
+
// range Start
20
+
"data-[range-start]:bg-primary dark:data-[range-start]:hover:bg-accent data-[range-start]:text-primary-foreground",
21
+
// range End
22
+
"data-[range-end]:bg-primary dark:data-[range-end]:hover:bg-accent data-[range-end]:text-primary-foreground",
23
+
// Outside months
24
+
"[&[data-outside-month]:not([data-selected])]:text-muted-foreground [&[data-outside-month]:not([data-selected])]:hover:text-accent-foreground",
25
+
// Disabled
26
+
"data-[disabled]:text-muted-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
27
+
// Unavailable
28
+
"data-[unavailable]:line-through",
29
+
"dark:data-[range-middle]:hover:bg-accent/0",
30
+
// hover
31
+
"dark:hover:text-accent-foreground",
32
+
// focus
33
+
"focus:border-ring focus:ring-ring/50 focus:relative",
34
+
// inner spans
35
+
"[&>span]:text-xs [&>span]:opacity-70",
36
+
className
37
+
)}
38
+
{...restProps}
39
+
/>
+12
apps/web/src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte
+12
apps/web/src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: RangeCalendarPrimitive.GridRowProps = $props();
10
+
</script>
11
+
12
+
<RangeCalendarPrimitive.GridRow bind:ref class={cn("flex", className)} {...restProps} />
+16
apps/web/src/lib/components/ui/range-calendar/range-calendar-grid.svelte
+16
apps/web/src/lib/components/ui/range-calendar/range-calendar-grid.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: RangeCalendarPrimitive.GridProps = $props();
10
+
</script>
11
+
12
+
<RangeCalendarPrimitive.Grid
13
+
bind:ref
14
+
class={cn("mt-4 flex w-full border-collapse flex-col gap-1", className)}
15
+
{...restProps}
16
+
/>
+19
apps/web/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte
+19
apps/web/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: RangeCalendarPrimitive.HeadCellProps = $props();
10
+
</script>
11
+
12
+
<RangeCalendarPrimitive.HeadCell
13
+
bind:ref
14
+
class={cn(
15
+
"text-muted-foreground w-(--cell-size) rounded-md text-[0.8rem] font-normal",
16
+
className
17
+
)}
18
+
{...restProps}
19
+
/>
+19
apps/web/src/lib/components/ui/range-calendar/range-calendar-header.svelte
+19
apps/web/src/lib/components/ui/range-calendar/range-calendar-header.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: RangeCalendarPrimitive.HeaderProps = $props();
10
+
</script>
11
+
12
+
<RangeCalendarPrimitive.Header
13
+
bind:ref
14
+
class={cn(
15
+
"h-(--cell-size) flex w-full items-center justify-center gap-1.5 text-sm font-medium",
16
+
className
17
+
)}
18
+
{...restProps}
19
+
/>
+16
apps/web/src/lib/components/ui/range-calendar/range-calendar-heading.svelte
+16
apps/web/src/lib/components/ui/range-calendar/range-calendar-heading.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: RangeCalendarPrimitive.HeadingProps = $props();
10
+
</script>
11
+
12
+
<RangeCalendarPrimitive.Heading
13
+
bind:ref
14
+
class={cn("px-(--cell-size) text-sm font-medium", className)}
15
+
{...restProps}
16
+
/>
+44
apps/web/src/lib/components/ui/range-calendar/range-calendar-month-select.svelte
+44
apps/web/src/lib/components/ui/range-calendar/range-calendar-month-select.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
4
+
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
value,
10
+
onchange,
11
+
...restProps
12
+
}: WithoutChildrenOrChild<RangeCalendarPrimitive.MonthSelectProps> = $props();
13
+
</script>
14
+
15
+
<span
16
+
class={cn(
17
+
"has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative flex rounded-md border",
18
+
className
19
+
)}
20
+
>
21
+
<RangeCalendarPrimitive.MonthSelect bind:ref class="absolute inset-0 opacity-0" {...restProps}>
22
+
{#snippet child({ props, monthItems, selectedMonthItem })}
23
+
<select {...props} {value} {onchange}>
24
+
{#each monthItems as monthItem (monthItem.value)}
25
+
<option
26
+
value={monthItem.value}
27
+
selected={value !== undefined
28
+
? monthItem.value === value
29
+
: monthItem.value === selectedMonthItem.value}
30
+
>
31
+
{monthItem.label}
32
+
</option>
33
+
{/each}
34
+
</select>
35
+
<span
36
+
class="[&>svg]:text-muted-foreground flex h-8 select-none items-center gap-1 rounded-md pl-2 pr-1 text-sm font-medium [&>svg]:size-3.5"
37
+
aria-hidden="true"
38
+
>
39
+
{monthItems.find((item) => item.value === value)?.label || selectedMonthItem.label}
40
+
<ChevronDownIcon class="size-4" />
41
+
</span>
42
+
{/snippet}
43
+
</RangeCalendarPrimitive.MonthSelect>
44
+
</span>
+15
apps/web/src/lib/components/ui/range-calendar/range-calendar-month.svelte
+15
apps/web/src/lib/components/ui/range-calendar/range-calendar-month.svelte
···
1
+
<script lang="ts">
2
+
import { type WithElementRef, cn } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
11
+
</script>
12
+
13
+
<div {...restProps} bind:this={ref} class={cn("flex flex-col", className)}>
14
+
{@render children?.()}
15
+
</div>
+19
apps/web/src/lib/components/ui/range-calendar/range-calendar-months.svelte
+19
apps/web/src/lib/components/ui/range-calendar/range-calendar-months.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
class={cn("relative flex flex-col gap-4 md:flex-row", className)}
16
+
{...restProps}
17
+
>
18
+
{@render children?.()}
19
+
</div>
+43
apps/web/src/lib/components/ui/range-calendar/range-calendar-year-select.svelte
+43
apps/web/src/lib/components/ui/range-calendar/range-calendar-year-select.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
4
+
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
value,
10
+
...restProps
11
+
}: WithoutChildrenOrChild<RangeCalendarPrimitive.YearSelectProps> = $props();
12
+
</script>
13
+
14
+
<span
15
+
class={cn(
16
+
"has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative flex rounded-md border",
17
+
className
18
+
)}
19
+
>
20
+
<RangeCalendarPrimitive.YearSelect bind:ref class="absolute inset-0 opacity-0" {...restProps}>
21
+
{#snippet child({ props, yearItems, selectedYearItem })}
22
+
<select {...props} {value}>
23
+
{#each yearItems as yearItem (yearItem.value)}
24
+
<option
25
+
value={yearItem.value}
26
+
selected={value !== undefined
27
+
? yearItem.value === value
28
+
: yearItem.value === selectedYearItem.value}
29
+
>
30
+
{yearItem.label}
31
+
</option>
32
+
{/each}
33
+
</select>
34
+
<span
35
+
class="[&>svg]:text-muted-foreground flex h-8 select-none items-center gap-1 rounded-md pl-2 pr-1 text-sm font-medium [&>svg]:size-3.5"
36
+
aria-hidden="true"
37
+
>
38
+
{yearItems.find((item) => item.value === value)?.label || selectedYearItem.label}
39
+
<ChevronDownIcon class="size-4" />
40
+
</span>
41
+
{/snippet}
42
+
</RangeCalendarPrimitive.YearSelect>
43
+
</span>
+112
apps/web/src/lib/components/ui/range-calendar/range-calendar.svelte
+112
apps/web/src/lib/components/ui/range-calendar/range-calendar.svelte
···
1
+
<script lang="ts">
2
+
import { RangeCalendar as RangeCalendarPrimitive } from "bits-ui";
3
+
import * as RangeCalendar from "./index.js";
4
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
5
+
import type { ButtonVariant } from "$lib/components/ui/button/index.js";
6
+
import type { Snippet } from "svelte";
7
+
import { isEqualMonth, type DateValue } from "@internationalized/date";
8
+
9
+
let {
10
+
ref = $bindable(null),
11
+
value = $bindable(),
12
+
placeholder = $bindable(),
13
+
weekdayFormat = "short",
14
+
class: className,
15
+
buttonVariant = "ghost",
16
+
captionLayout = "label",
17
+
locale = "en-US",
18
+
months: monthsProp,
19
+
years,
20
+
monthFormat: monthFormatProp,
21
+
yearFormat = "numeric",
22
+
day,
23
+
disableDaysOutsideMonth = false,
24
+
...restProps
25
+
}: WithoutChildrenOrChild<RangeCalendarPrimitive.RootProps> & {
26
+
buttonVariant?: ButtonVariant;
27
+
captionLayout?: "dropdown" | "dropdown-months" | "dropdown-years" | "label";
28
+
months?: RangeCalendarPrimitive.MonthSelectProps["months"];
29
+
years?: RangeCalendarPrimitive.YearSelectProps["years"];
30
+
monthFormat?: RangeCalendarPrimitive.MonthSelectProps["monthFormat"];
31
+
yearFormat?: RangeCalendarPrimitive.YearSelectProps["yearFormat"];
32
+
day?: Snippet<[{ day: DateValue; outsideMonth: boolean }]>;
33
+
} = $props();
34
+
35
+
const monthFormat = $derived.by(() => {
36
+
if (monthFormatProp) return monthFormatProp;
37
+
if (captionLayout.startsWith("dropdown")) return "short";
38
+
return "long";
39
+
});
40
+
</script>
41
+
42
+
<RangeCalendarPrimitive.Root
43
+
bind:ref
44
+
bind:value
45
+
bind:placeholder
46
+
{weekdayFormat}
47
+
{disableDaysOutsideMonth}
48
+
class={cn(
49
+
"bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
50
+
className
51
+
)}
52
+
{locale}
53
+
{monthFormat}
54
+
{yearFormat}
55
+
{...restProps}
56
+
>
57
+
{#snippet children({ months, weekdays })}
58
+
<RangeCalendar.Months>
59
+
<RangeCalendar.Nav>
60
+
<RangeCalendar.PrevButton variant={buttonVariant} />
61
+
<RangeCalendar.NextButton variant={buttonVariant} />
62
+
</RangeCalendar.Nav>
63
+
{#each months as month, monthIndex (month)}
64
+
<RangeCalendar.Month>
65
+
<RangeCalendar.Header>
66
+
<RangeCalendar.Caption
67
+
{captionLayout}
68
+
months={monthsProp}
69
+
{monthFormat}
70
+
{years}
71
+
{yearFormat}
72
+
month={month.value}
73
+
bind:placeholder
74
+
{locale}
75
+
{monthIndex}
76
+
/>
77
+
</RangeCalendar.Header>
78
+
79
+
<RangeCalendar.Grid>
80
+
<RangeCalendar.GridHead>
81
+
<RangeCalendar.GridRow class="select-none">
82
+
{#each weekdays as weekday (weekday)}
83
+
<RangeCalendar.HeadCell>
84
+
{weekday.slice(0, 2)}
85
+
</RangeCalendar.HeadCell>
86
+
{/each}
87
+
</RangeCalendar.GridRow>
88
+
</RangeCalendar.GridHead>
89
+
<RangeCalendar.GridBody>
90
+
{#each month.weeks as weekDates (weekDates)}
91
+
<RangeCalendar.GridRow class="mt-2 w-full">
92
+
{#each weekDates as date (date)}
93
+
<RangeCalendar.Cell {date} month={month.value}>
94
+
{#if day}
95
+
{@render day({
96
+
day: date,
97
+
outsideMonth: !isEqualMonth(date, month.value),
98
+
})}
99
+
{:else}
100
+
<RangeCalendar.Day />
101
+
{/if}
102
+
</RangeCalendar.Cell>
103
+
{/each}
104
+
</RangeCalendar.GridRow>
105
+
{/each}
106
+
</RangeCalendar.GridBody>
107
+
</RangeCalendar.Grid>
108
+
</RangeCalendar.Month>
109
+
{/each}
110
+
</RangeCalendar.Months>
111
+
{/snippet}
112
+
</RangeCalendarPrimitive.Root>
+13
apps/web/src/lib/components/ui/resizable/index.ts
+13
apps/web/src/lib/components/ui/resizable/index.ts
···
1
+
import { Pane } from "paneforge";
2
+
import Handle from "./resizable-handle.svelte";
3
+
import PaneGroup from "./resizable-pane-group.svelte";
4
+
5
+
export {
6
+
PaneGroup,
7
+
Pane,
8
+
Handle,
9
+
//
10
+
PaneGroup as ResizablePaneGroup,
11
+
Pane as ResizablePane,
12
+
Handle as ResizableHandle,
13
+
};
+30
apps/web/src/lib/components/ui/resizable/resizable-handle.svelte
+30
apps/web/src/lib/components/ui/resizable/resizable-handle.svelte
···
1
+
<script lang="ts">
2
+
import GripVerticalIcon from "@lucide/svelte/icons/grip-vertical";
3
+
import * as ResizablePrimitive from "paneforge";
4
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
withHandle = false,
10
+
...restProps
11
+
}: WithoutChildrenOrChild<ResizablePrimitive.PaneResizerProps> & {
12
+
withHandle?: boolean;
13
+
} = $props();
14
+
</script>
15
+
16
+
<ResizablePrimitive.PaneResizer
17
+
bind:ref
18
+
data-slot="resizable-handle"
19
+
class={cn(
20
+
"bg-border focus-visible:ring-ring focus-visible:outline-hidden relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 data-[direction=vertical]:h-px data-[direction=vertical]:w-full data-[direction=vertical]:after:left-0 data-[direction=vertical]:after:h-1 data-[direction=vertical]:after:w-full data-[direction=vertical]:after:-translate-y-1/2 data-[direction=vertical]:after:translate-x-0 [&[data-direction=vertical]>div]:rotate-90",
21
+
className
22
+
)}
23
+
{...restProps}
24
+
>
25
+
{#if withHandle}
26
+
<div class="bg-border rounded-xs z-10 flex h-4 w-3 items-center justify-center border">
27
+
<GripVerticalIcon class="size-2.5" />
28
+
</div>
29
+
{/if}
30
+
</ResizablePrimitive.PaneResizer>
+20
apps/web/src/lib/components/ui/resizable/resizable-pane-group.svelte
+20
apps/web/src/lib/components/ui/resizable/resizable-pane-group.svelte
···
1
+
<script lang="ts">
2
+
import * as ResizablePrimitive from "paneforge";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
this: paneGroup = $bindable(),
8
+
class: className,
9
+
...restProps
10
+
}: ResizablePrimitive.PaneGroupProps & {
11
+
this?: ResizablePrimitive.PaneGroup;
12
+
} = $props();
13
+
</script>
14
+
15
+
<ResizablePrimitive.PaneGroup
16
+
bind:this={paneGroup}
17
+
data-slot="resizable-pane-group"
18
+
class={cn("flex h-full w-full data-[direction=vertical]:flex-col", className)}
19
+
{...restProps}
20
+
/>
+10
apps/web/src/lib/components/ui/scroll-area/index.ts
+10
apps/web/src/lib/components/ui/scroll-area/index.ts
+31
apps/web/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte
+31
apps/web/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte
···
1
+
<script lang="ts">
2
+
import { ScrollArea as ScrollAreaPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
orientation = "vertical",
9
+
children,
10
+
...restProps
11
+
}: WithoutChild<ScrollAreaPrimitive.ScrollbarProps> = $props();
12
+
</script>
13
+
14
+
<ScrollAreaPrimitive.Scrollbar
15
+
bind:ref
16
+
data-slot="scroll-area-scrollbar"
17
+
{orientation}
18
+
class={cn(
19
+
"flex touch-none select-none p-px transition-colors",
20
+
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
21
+
orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
22
+
className
23
+
)}
24
+
{...restProps}
25
+
>
26
+
{@render children?.()}
27
+
<ScrollAreaPrimitive.Thumb
28
+
data-slot="scroll-area-thumb"
29
+
class="bg-border relative flex-1 rounded-full"
30
+
/>
31
+
</ScrollAreaPrimitive.Scrollbar>
+40
apps/web/src/lib/components/ui/scroll-area/scroll-area.svelte
+40
apps/web/src/lib/components/ui/scroll-area/scroll-area.svelte
···
1
+
<script lang="ts">
2
+
import { ScrollArea as ScrollAreaPrimitive } from "bits-ui";
3
+
import { Scrollbar } from "./index.js";
4
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
orientation = "vertical",
10
+
scrollbarXClasses = "",
11
+
scrollbarYClasses = "",
12
+
children,
13
+
...restProps
14
+
}: WithoutChild<ScrollAreaPrimitive.RootProps> & {
15
+
orientation?: "vertical" | "horizontal" | "both" | undefined;
16
+
scrollbarXClasses?: string | undefined;
17
+
scrollbarYClasses?: string | undefined;
18
+
} = $props();
19
+
</script>
20
+
21
+
<ScrollAreaPrimitive.Root
22
+
bind:ref
23
+
data-slot="scroll-area"
24
+
class={cn("relative", className)}
25
+
{...restProps}
26
+
>
27
+
<ScrollAreaPrimitive.Viewport
28
+
data-slot="scroll-area-viewport"
29
+
class="ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-4"
30
+
>
31
+
{@render children?.()}
32
+
</ScrollAreaPrimitive.Viewport>
33
+
{#if orientation === "vertical" || orientation === "both"}
34
+
<Scrollbar orientation="vertical" class={scrollbarYClasses} />
35
+
{/if}
36
+
{#if orientation === "horizontal" || orientation === "both"}
37
+
<Scrollbar orientation="horizontal" class={scrollbarXClasses} />
38
+
{/if}
39
+
<ScrollAreaPrimitive.Corner />
40
+
</ScrollAreaPrimitive.Root>
+37
apps/web/src/lib/components/ui/select/index.ts
+37
apps/web/src/lib/components/ui/select/index.ts
···
1
+
import { Select as SelectPrimitive } from "bits-ui";
2
+
3
+
import Group from "./select-group.svelte";
4
+
import Label from "./select-label.svelte";
5
+
import Item from "./select-item.svelte";
6
+
import Content from "./select-content.svelte";
7
+
import Trigger from "./select-trigger.svelte";
8
+
import Separator from "./select-separator.svelte";
9
+
import ScrollDownButton from "./select-scroll-down-button.svelte";
10
+
import ScrollUpButton from "./select-scroll-up-button.svelte";
11
+
import GroupHeading from "./select-group-heading.svelte";
12
+
13
+
const Root = SelectPrimitive.Root;
14
+
15
+
export {
16
+
Root,
17
+
Group,
18
+
Label,
19
+
Item,
20
+
Content,
21
+
Trigger,
22
+
Separator,
23
+
ScrollDownButton,
24
+
ScrollUpButton,
25
+
GroupHeading,
26
+
//
27
+
Root as Select,
28
+
Group as SelectGroup,
29
+
Label as SelectLabel,
30
+
Item as SelectItem,
31
+
Content as SelectContent,
32
+
Trigger as SelectTrigger,
33
+
Separator as SelectSeparator,
34
+
ScrollDownButton as SelectScrollDownButton,
35
+
ScrollUpButton as SelectScrollUpButton,
36
+
GroupHeading as SelectGroupHeading,
37
+
};
+40
apps/web/src/lib/components/ui/select/select-content.svelte
+40
apps/web/src/lib/components/ui/select/select-content.svelte
···
1
+
<script lang="ts">
2
+
import { Select as SelectPrimitive } from "bits-ui";
3
+
import SelectScrollUpButton from "./select-scroll-up-button.svelte";
4
+
import SelectScrollDownButton from "./select-scroll-down-button.svelte";
5
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
6
+
7
+
let {
8
+
ref = $bindable(null),
9
+
class: className,
10
+
sideOffset = 4,
11
+
portalProps,
12
+
children,
13
+
...restProps
14
+
}: WithoutChild<SelectPrimitive.ContentProps> & {
15
+
portalProps?: SelectPrimitive.PortalProps;
16
+
} = $props();
17
+
</script>
18
+
19
+
<SelectPrimitive.Portal {...portalProps}>
20
+
<SelectPrimitive.Content
21
+
bind:ref
22
+
{sideOffset}
23
+
data-slot="select-content"
24
+
class={cn(
25
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 max-h-(--bits-select-content-available-height) origin-(--bits-select-content-transform-origin) relative z-50 min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border shadow-md data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
26
+
className
27
+
)}
28
+
{...restProps}
29
+
>
30
+
<SelectScrollUpButton />
31
+
<SelectPrimitive.Viewport
32
+
class={cn(
33
+
"h-(--bits-select-anchor-height) min-w-(--bits-select-anchor-width) w-full scroll-my-1 p-1"
34
+
)}
35
+
>
36
+
{@render children?.()}
37
+
</SelectPrimitive.Viewport>
38
+
<SelectScrollDownButton />
39
+
</SelectPrimitive.Content>
40
+
</SelectPrimitive.Portal>
+21
apps/web/src/lib/components/ui/select/select-group-heading.svelte
+21
apps/web/src/lib/components/ui/select/select-group-heading.svelte
···
1
+
<script lang="ts">
2
+
import { Select as SelectPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
import type { ComponentProps } from "svelte";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
children,
10
+
...restProps
11
+
}: ComponentProps<typeof SelectPrimitive.GroupHeading> = $props();
12
+
</script>
13
+
14
+
<SelectPrimitive.GroupHeading
15
+
bind:ref
16
+
data-slot="select-group-heading"
17
+
class={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
18
+
{...restProps}
19
+
>
20
+
{@render children?.()}
21
+
</SelectPrimitive.GroupHeading>
+7
apps/web/src/lib/components/ui/select/select-group.svelte
+7
apps/web/src/lib/components/ui/select/select-group.svelte
+38
apps/web/src/lib/components/ui/select/select-item.svelte
+38
apps/web/src/lib/components/ui/select/select-item.svelte
···
1
+
<script lang="ts">
2
+
import CheckIcon from "@lucide/svelte/icons/check";
3
+
import { Select as SelectPrimitive } from "bits-ui";
4
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
value,
10
+
label,
11
+
children: childrenProp,
12
+
...restProps
13
+
}: WithoutChild<SelectPrimitive.ItemProps> = $props();
14
+
</script>
15
+
16
+
<SelectPrimitive.Item
17
+
bind:ref
18
+
{value}
19
+
data-slot="select-item"
20
+
class={cn(
21
+
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground outline-hidden *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default select-none items-center gap-2 rounded-sm py-1.5 pl-2 pr-8 text-sm data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
22
+
className
23
+
)}
24
+
{...restProps}
25
+
>
26
+
{#snippet children({ selected, highlighted })}
27
+
<span class="absolute right-2 flex size-3.5 items-center justify-center">
28
+
{#if selected}
29
+
<CheckIcon class="size-4" />
30
+
{/if}
31
+
</span>
32
+
{#if childrenProp}
33
+
{@render childrenProp({ selected, highlighted })}
34
+
{:else}
35
+
{label || value}
36
+
{/if}
37
+
{/snippet}
38
+
</SelectPrimitive.Item>
+20
apps/web/src/lib/components/ui/select/select-label.svelte
+20
apps/web/src/lib/components/ui/select/select-label.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {} = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="select-label"
16
+
class={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+18
apps/web/src/lib/components/ui/select/select-separator.svelte
+18
apps/web/src/lib/components/ui/select/select-separator.svelte
···
1
+
<script lang="ts">
2
+
import type { Separator as SeparatorPrimitive } from "bits-ui";
3
+
import { Separator } from "$lib/components/ui/separator/index.js";
4
+
import { cn } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
...restProps
10
+
}: SeparatorPrimitive.RootProps = $props();
11
+
</script>
12
+
13
+
<Separator
14
+
bind:ref
15
+
data-slot="select-separator"
16
+
class={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
17
+
{...restProps}
18
+
/>
+29
apps/web/src/lib/components/ui/select/select-trigger.svelte
+29
apps/web/src/lib/components/ui/select/select-trigger.svelte
···
1
+
<script lang="ts">
2
+
import { Select as SelectPrimitive } from "bits-ui";
3
+
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
4
+
import { cn, type WithoutChild } from "$lib/utils/cn.js";
5
+
6
+
let {
7
+
ref = $bindable(null),
8
+
class: className,
9
+
children,
10
+
size = "default",
11
+
...restProps
12
+
}: WithoutChild<SelectPrimitive.TriggerProps> & {
13
+
size?: "sm" | "default";
14
+
} = $props();
15
+
</script>
16
+
17
+
<SelectPrimitive.Trigger
18
+
bind:ref
19
+
data-slot="select-trigger"
20
+
data-size={size}
21
+
class={cn(
22
+
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 shadow-xs flex w-fit select-none items-center justify-between gap-2 whitespace-nowrap rounded-md border bg-transparent px-3 py-2 text-sm outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
23
+
className
24
+
)}
25
+
{...restProps}
26
+
>
27
+
{@render children?.()}
28
+
<ChevronDownIcon class="size-4 opacity-50" />
29
+
</SelectPrimitive.Trigger>
+7
apps/web/src/lib/components/ui/separator/index.ts
+7
apps/web/src/lib/components/ui/separator/index.ts
+21
apps/web/src/lib/components/ui/separator/separator.svelte
+21
apps/web/src/lib/components/ui/separator/separator.svelte
···
1
+
<script lang="ts">
2
+
import { Separator as SeparatorPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
"data-slot": dataSlot = "separator",
9
+
...restProps
10
+
}: SeparatorPrimitive.RootProps = $props();
11
+
</script>
12
+
13
+
<SeparatorPrimitive.Root
14
+
bind:ref
15
+
data-slot={dataSlot}
16
+
class={cn(
17
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
/>
+36
apps/web/src/lib/components/ui/sheet/index.ts
+36
apps/web/src/lib/components/ui/sheet/index.ts
···
1
+
import { Dialog as SheetPrimitive } from "bits-ui";
2
+
import Trigger from "./sheet-trigger.svelte";
3
+
import Close from "./sheet-close.svelte";
4
+
import Overlay from "./sheet-overlay.svelte";
5
+
import Content from "./sheet-content.svelte";
6
+
import Header from "./sheet-header.svelte";
7
+
import Footer from "./sheet-footer.svelte";
8
+
import Title from "./sheet-title.svelte";
9
+
import Description from "./sheet-description.svelte";
10
+
11
+
const Root = SheetPrimitive.Root;
12
+
const Portal = SheetPrimitive.Portal;
13
+
14
+
export {
15
+
Root,
16
+
Close,
17
+
Trigger,
18
+
Portal,
19
+
Overlay,
20
+
Content,
21
+
Header,
22
+
Footer,
23
+
Title,
24
+
Description,
25
+
//
26
+
Root as Sheet,
27
+
Close as SheetClose,
28
+
Trigger as SheetTrigger,
29
+
Portal as SheetPortal,
30
+
Overlay as SheetOverlay,
31
+
Content as SheetContent,
32
+
Header as SheetHeader,
33
+
Footer as SheetFooter,
34
+
Title as SheetTitle,
35
+
Description as SheetDescription,
36
+
};
+7
apps/web/src/lib/components/ui/sheet/sheet-close.svelte
+7
apps/web/src/lib/components/ui/sheet/sheet-close.svelte
+58
apps/web/src/lib/components/ui/sheet/sheet-content.svelte
+58
apps/web/src/lib/components/ui/sheet/sheet-content.svelte
···
1
+
<script lang="ts" module>
2
+
import { tv, type VariantProps } from "tailwind-variants";
3
+
export const sheetVariants = tv({
4
+
base: "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
5
+
variants: {
6
+
side: {
7
+
top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
8
+
bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
9
+
left: "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
10
+
right: "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
11
+
},
12
+
},
13
+
defaultVariants: {
14
+
side: "right",
15
+
},
16
+
});
17
+
18
+
export type Side = VariantProps<typeof sheetVariants>["side"];
19
+
</script>
20
+
21
+
<script lang="ts">
22
+
import { Dialog as SheetPrimitive } from "bits-ui";
23
+
import XIcon from "@lucide/svelte/icons/x";
24
+
import type { Snippet } from "svelte";
25
+
import SheetOverlay from "./sheet-overlay.svelte";
26
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
27
+
28
+
let {
29
+
ref = $bindable(null),
30
+
class: className,
31
+
side = "right",
32
+
portalProps,
33
+
children,
34
+
...restProps
35
+
}: WithoutChildrenOrChild<SheetPrimitive.ContentProps> & {
36
+
portalProps?: SheetPrimitive.PortalProps;
37
+
side?: Side;
38
+
children: Snippet;
39
+
} = $props();
40
+
</script>
41
+
42
+
<SheetPrimitive.Portal {...portalProps}>
43
+
<SheetOverlay />
44
+
<SheetPrimitive.Content
45
+
bind:ref
46
+
data-slot="sheet-content"
47
+
class={cn(sheetVariants({ side }), className)}
48
+
{...restProps}
49
+
>
50
+
{@render children?.()}
51
+
<SheetPrimitive.Close
52
+
class="ring-offset-background focus-visible:ring-ring rounded-xs focus-visible:outline-hidden absolute right-4 top-4 opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none"
53
+
>
54
+
<XIcon class="size-4" />
55
+
<span class="sr-only">Close</span>
56
+
</SheetPrimitive.Close>
57
+
</SheetPrimitive.Content>
58
+
</SheetPrimitive.Portal>
+17
apps/web/src/lib/components/ui/sheet/sheet-description.svelte
+17
apps/web/src/lib/components/ui/sheet/sheet-description.svelte
···
1
+
<script lang="ts">
2
+
import { Dialog as SheetPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: SheetPrimitive.DescriptionProps = $props();
10
+
</script>
11
+
12
+
<SheetPrimitive.Description
13
+
bind:ref
14
+
data-slot="sheet-description"
15
+
class={cn("text-muted-foreground text-sm", className)}
16
+
{...restProps}
17
+
/>
+20
apps/web/src/lib/components/ui/sheet/sheet-header.svelte
+20
apps/web/src/lib/components/ui/sheet/sheet-header.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+
</script>
12
+
13
+
<div
14
+
bind:this={ref}
15
+
data-slot="sheet-header"
16
+
class={cn("flex flex-col gap-1.5 p-4", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</div>
+20
apps/web/src/lib/components/ui/sheet/sheet-overlay.svelte
+20
apps/web/src/lib/components/ui/sheet/sheet-overlay.svelte
···
1
+
<script lang="ts">
2
+
import { Dialog as SheetPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: SheetPrimitive.OverlayProps = $props();
10
+
</script>
11
+
12
+
<SheetPrimitive.Overlay
13
+
bind:ref
14
+
data-slot="sheet-overlay"
15
+
class={cn(
16
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+17
apps/web/src/lib/components/ui/sheet/sheet-title.svelte
+17
apps/web/src/lib/components/ui/sheet/sheet-title.svelte
···
1
+
<script lang="ts">
2
+
import { Dialog as SheetPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: SheetPrimitive.TitleProps = $props();
10
+
</script>
11
+
12
+
<SheetPrimitive.Title
13
+
bind:ref
14
+
data-slot="sheet-title"
15
+
class={cn("text-foreground font-semibold", className)}
16
+
{...restProps}
17
+
/>
+7
apps/web/src/lib/components/ui/sheet/sheet-trigger.svelte
+7
apps/web/src/lib/components/ui/sheet/sheet-trigger.svelte
+7
apps/web/src/lib/components/ui/skeleton/index.ts
+7
apps/web/src/lib/components/ui/skeleton/index.ts
+17
apps/web/src/lib/components/ui/skeleton/skeleton.svelte
+17
apps/web/src/lib/components/ui/skeleton/skeleton.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: WithoutChildren<WithElementRef<HTMLAttributes<HTMLDivElement>>> = $props();
10
+
</script>
11
+
12
+
<div
13
+
bind:this={ref}
14
+
data-slot="skeleton"
15
+
class={cn("bg-accent animate-pulse rounded-md", className)}
16
+
{...restProps}
17
+
></div>
+7
apps/web/src/lib/components/ui/slider/index.ts
+7
apps/web/src/lib/components/ui/slider/index.ts
+52
apps/web/src/lib/components/ui/slider/slider.svelte
+52
apps/web/src/lib/components/ui/slider/slider.svelte
···
1
+
<script lang="ts">
2
+
import { Slider as SliderPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
value = $bindable(),
8
+
orientation = "horizontal",
9
+
class: className,
10
+
...restProps
11
+
}: WithoutChildrenOrChild<SliderPrimitive.RootProps> = $props();
12
+
</script>
13
+
14
+
<!--
15
+
Discriminated Unions + Destructing (required for bindable) do not
16
+
get along, so we shut typescript up by casting `value` to `never`.
17
+
-->
18
+
<SliderPrimitive.Root
19
+
bind:ref
20
+
bind:value={value as never}
21
+
data-slot="slider"
22
+
{orientation}
23
+
class={cn(
24
+
"relative flex w-full touch-none select-none items-center data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col data-[disabled]:opacity-50",
25
+
className
26
+
)}
27
+
{...restProps}
28
+
>
29
+
{#snippet children({ thumbs })}
30
+
<span
31
+
data-orientation={orientation}
32
+
data-slot="slider-track"
33
+
class={cn(
34
+
"bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-1.5"
35
+
)}
36
+
>
37
+
<SliderPrimitive.Range
38
+
data-slot="slider-range"
39
+
class={cn(
40
+
"bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
41
+
)}
42
+
/>
43
+
</span>
44
+
{#each thumbs as thumb (thumb)}
45
+
<SliderPrimitive.Thumb
46
+
data-slot="slider-thumb"
47
+
index={thumb}
48
+
class="border-primary bg-background ring-ring/50 focus-visible:outline-hidden block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 disabled:pointer-events-none disabled:opacity-50"
49
+
/>
50
+
{/each}
51
+
{/snippet}
52
+
</SliderPrimitive.Root>
+1
apps/web/src/lib/components/ui/sonner/index.ts
+1
apps/web/src/lib/components/ui/sonner/index.ts
···
1
+
export { default as Toaster } from "./sonner.svelte";
+13
apps/web/src/lib/components/ui/sonner/sonner.svelte
+13
apps/web/src/lib/components/ui/sonner/sonner.svelte
···
1
+
<script lang="ts">
2
+
import { Toaster as Sonner, type ToasterProps as SonnerProps } from "svelte-sonner";
3
+
import { mode } from "mode-watcher";
4
+
5
+
let { ...restProps }: SonnerProps = $props();
6
+
</script>
7
+
8
+
<Sonner
9
+
theme={mode.current}
10
+
class="toaster group"
11
+
style="--normal-bg: var(--color-popover); --normal-text: var(--color-popover-foreground); --normal-border: var(--color-border);"
12
+
{...restProps}
13
+
/>
+1
apps/web/src/lib/components/ui/spinner/index.ts
+1
apps/web/src/lib/components/ui/spinner/index.ts
···
1
+
export { default as Spinner } from "./spinner.svelte";
+16
apps/web/src/lib/components/ui/spinner/spinner.svelte
+16
apps/web/src/lib/components/ui/spinner/spinner.svelte
···
1
+
<script lang="ts">
2
+
import { cn } from "$lib/utils/cn.js";
3
+
import Loader2Icon from "@lucide/svelte/icons/loader-2";
4
+
import type { ComponentProps } from "svelte";
5
+
6
+
type Props = ComponentProps<typeof Loader2Icon>;
7
+
8
+
let { class: className, ...restProps }: Props = $props();
9
+
</script>
10
+
11
+
<Loader2Icon
12
+
role="status"
13
+
aria-label="Loading"
14
+
class={cn("size-4 animate-spin", className)}
15
+
{...restProps}
16
+
/>
+7
apps/web/src/lib/components/ui/switch/index.ts
+7
apps/web/src/lib/components/ui/switch/index.ts
+29
apps/web/src/lib/components/ui/switch/switch.svelte
+29
apps/web/src/lib/components/ui/switch/switch.svelte
···
1
+
<script lang="ts">
2
+
import { Switch as SwitchPrimitive } from "bits-ui";
3
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
checked = $bindable(false),
9
+
...restProps
10
+
}: WithoutChildrenOrChild<SwitchPrimitive.RootProps> = $props();
11
+
</script>
12
+
13
+
<SwitchPrimitive.Root
14
+
bind:ref
15
+
bind:checked
16
+
data-slot="switch"
17
+
class={cn(
18
+
"data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 shadow-xs peer inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent outline-none transition-all focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
19
+
className
20
+
)}
21
+
{...restProps}
22
+
>
23
+
<SwitchPrimitive.Thumb
24
+
data-slot="switch-thumb"
25
+
class={cn(
26
+
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
27
+
)}
28
+
/>
29
+
</SwitchPrimitive.Root>
+28
apps/web/src/lib/components/ui/table/index.ts
+28
apps/web/src/lib/components/ui/table/index.ts
···
1
+
import Root from "./table.svelte";
2
+
import Body from "./table-body.svelte";
3
+
import Caption from "./table-caption.svelte";
4
+
import Cell from "./table-cell.svelte";
5
+
import Footer from "./table-footer.svelte";
6
+
import Head from "./table-head.svelte";
7
+
import Header from "./table-header.svelte";
8
+
import Row from "./table-row.svelte";
9
+
10
+
export {
11
+
Root,
12
+
Body,
13
+
Caption,
14
+
Cell,
15
+
Footer,
16
+
Head,
17
+
Header,
18
+
Row,
19
+
//
20
+
Root as Table,
21
+
Body as TableBody,
22
+
Caption as TableCaption,
23
+
Cell as TableCell,
24
+
Footer as TableFooter,
25
+
Head as TableHead,
26
+
Header as TableHeader,
27
+
Row as TableRow,
28
+
};
+20
apps/web/src/lib/components/ui/table/table-body.svelte
+20
apps/web/src/lib/components/ui/table/table-body.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
11
+
</script>
12
+
13
+
<tbody
14
+
bind:this={ref}
15
+
data-slot="table-body"
16
+
class={cn("[&_tr:last-child]:border-0", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</tbody>
+20
apps/web/src/lib/components/ui/table/table-caption.svelte
+20
apps/web/src/lib/components/ui/table/table-caption.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
11
+
</script>
12
+
13
+
<caption
14
+
bind:this={ref}
15
+
data-slot="table-caption"
16
+
class={cn("text-muted-foreground mt-4 text-sm", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</caption>
+23
apps/web/src/lib/components/ui/table/table-cell.svelte
+23
apps/web/src/lib/components/ui/table/table-cell.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLTdAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLTdAttributes> = $props();
11
+
</script>
12
+
13
+
<td
14
+
bind:this={ref}
15
+
data-slot="table-cell"
16
+
class={cn(
17
+
"whitespace-nowrap bg-clip-padding p-2 align-middle [&:has([role=checkbox])]:pr-0",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
>
22
+
{@render children?.()}
23
+
</td>
+23
apps/web/src/lib/components/ui/table/table-head.svelte
+23
apps/web/src/lib/components/ui/table/table-head.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLThAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLThAttributes> = $props();
11
+
</script>
12
+
13
+
<th
14
+
bind:this={ref}
15
+
data-slot="table-head"
16
+
class={cn(
17
+
"text-foreground h-10 whitespace-nowrap bg-clip-padding px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
>
22
+
{@render children?.()}
23
+
</th>
+20
apps/web/src/lib/components/ui/table/table-header.svelte
+20
apps/web/src/lib/components/ui/table/table-header.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
11
+
</script>
12
+
13
+
<thead
14
+
bind:this={ref}
15
+
data-slot="table-header"
16
+
class={cn("[&_tr]:border-b", className)}
17
+
{...restProps}
18
+
>
19
+
{@render children?.()}
20
+
</thead>
+23
apps/web/src/lib/components/ui/table/table-row.svelte
+23
apps/web/src/lib/components/ui/table/table-row.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
3
+
import type { HTMLAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLAttributes<HTMLTableRowElement>> = $props();
11
+
</script>
12
+
13
+
<tr
14
+
bind:this={ref}
15
+
data-slot="table-row"
16
+
class={cn(
17
+
"hover:[&,&>svelte-css-wrapper]:[&>th,td]:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
18
+
className
19
+
)}
20
+
{...restProps}
21
+
>
22
+
{@render children?.()}
23
+
</tr>
+22
apps/web/src/lib/components/ui/table/table.svelte
+22
apps/web/src/lib/components/ui/table/table.svelte
···
1
+
<script lang="ts">
2
+
import type { HTMLTableAttributes } from "svelte/elements";
3
+
import { cn, type WithElementRef } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
children,
9
+
...restProps
10
+
}: WithElementRef<HTMLTableAttributes> = $props();
11
+
</script>
12
+
13
+
<div data-slot="table-container" class="relative w-full overflow-x-auto">
14
+
<table
15
+
bind:this={ref}
16
+
data-slot="table"
17
+
class={cn("w-full caption-bottom text-sm", className)}
18
+
{...restProps}
19
+
>
20
+
{@render children?.()}
21
+
</table>
22
+
</div>
+16
apps/web/src/lib/components/ui/tabs/index.ts
+16
apps/web/src/lib/components/ui/tabs/index.ts
···
1
+
import Root from "./tabs.svelte";
2
+
import Content from "./tabs-content.svelte";
3
+
import List from "./tabs-list.svelte";
4
+
import Trigger from "./tabs-trigger.svelte";
5
+
6
+
export {
7
+
Root,
8
+
Content,
9
+
List,
10
+
Trigger,
11
+
//
12
+
Root as Tabs,
13
+
Content as TabsContent,
14
+
List as TabsList,
15
+
Trigger as TabsTrigger,
16
+
};
+17
apps/web/src/lib/components/ui/tabs/tabs-content.svelte
+17
apps/web/src/lib/components/ui/tabs/tabs-content.svelte
···
1
+
<script lang="ts">
2
+
import { Tabs as TabsPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: TabsPrimitive.ContentProps = $props();
10
+
</script>
11
+
12
+
<TabsPrimitive.Content
13
+
bind:ref
14
+
data-slot="tabs-content"
15
+
class={cn("flex-1 outline-none", className)}
16
+
{...restProps}
17
+
/>
+20
apps/web/src/lib/components/ui/tabs/tabs-list.svelte
+20
apps/web/src/lib/components/ui/tabs/tabs-list.svelte
···
1
+
<script lang="ts">
2
+
import { Tabs as TabsPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: TabsPrimitive.ListProps = $props();
10
+
</script>
11
+
12
+
<TabsPrimitive.List
13
+
bind:ref
14
+
data-slot="tabs-list"
15
+
class={cn(
16
+
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+20
apps/web/src/lib/components/ui/tabs/tabs-trigger.svelte
+20
apps/web/src/lib/components/ui/tabs/tabs-trigger.svelte
···
1
+
<script lang="ts">
2
+
import { Tabs as TabsPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
...restProps
9
+
}: TabsPrimitive.TriggerProps = $props();
10
+
</script>
11
+
12
+
<TabsPrimitive.Trigger
13
+
bind:ref
14
+
data-slot="tabs-trigger"
15
+
class={cn(
16
+
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 whitespace-nowrap rounded-md border border-transparent px-2 py-1 text-sm font-medium transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
17
+
className
18
+
)}
19
+
{...restProps}
20
+
/>
+19
apps/web/src/lib/components/ui/tabs/tabs.svelte
+19
apps/web/src/lib/components/ui/tabs/tabs.svelte
···
1
+
<script lang="ts">
2
+
import { Tabs as TabsPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
value = $bindable(""),
8
+
class: className,
9
+
...restProps
10
+
}: TabsPrimitive.RootProps = $props();
11
+
</script>
12
+
13
+
<TabsPrimitive.Root
14
+
bind:ref
15
+
bind:value
16
+
data-slot="tabs"
17
+
class={cn("flex flex-col gap-2", className)}
18
+
{...restProps}
19
+
/>
+7
apps/web/src/lib/components/ui/textarea/index.ts
+7
apps/web/src/lib/components/ui/textarea/index.ts
+23
apps/web/src/lib/components/ui/textarea/textarea.svelte
+23
apps/web/src/lib/components/ui/textarea/textarea.svelte
···
1
+
<script lang="ts">
2
+
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils/cn.js";
3
+
import type { HTMLTextareaAttributes } from "svelte/elements";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
value = $bindable(),
8
+
class: className,
9
+
"data-slot": dataSlot = "textarea",
10
+
...restProps
11
+
}: WithoutChildren<WithElementRef<HTMLTextareaAttributes>> = $props();
12
+
</script>
13
+
14
+
<textarea
15
+
bind:this={ref}
16
+
data-slot={dataSlot}
17
+
class={cn(
18
+
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 field-sizing-content shadow-xs flex min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
19
+
className
20
+
)}
21
+
bind:value
22
+
{...restProps}
23
+
></textarea>
+10
apps/web/src/lib/components/ui/toggle-group/index.ts
+10
apps/web/src/lib/components/ui/toggle-group/index.ts
+34
apps/web/src/lib/components/ui/toggle-group/toggle-group-item.svelte
+34
apps/web/src/lib/components/ui/toggle-group/toggle-group-item.svelte
···
1
+
<script lang="ts">
2
+
import { ToggleGroup as ToggleGroupPrimitive } from "bits-ui";
3
+
import { getToggleGroupCtx } from "./toggle-group.svelte";
4
+
import { cn } from "$lib/utils/cn.js";
5
+
import { type ToggleVariants, toggleVariants } from "$lib/components/ui/toggle/index.js";
6
+
7
+
let {
8
+
ref = $bindable(null),
9
+
value = $bindable(),
10
+
class: className,
11
+
size,
12
+
variant,
13
+
...restProps
14
+
}: ToggleGroupPrimitive.ItemProps & ToggleVariants = $props();
15
+
16
+
const ctx = getToggleGroupCtx();
17
+
</script>
18
+
19
+
<ToggleGroupPrimitive.Item
20
+
bind:ref
21
+
data-slot="toggle-group-item"
22
+
data-variant={ctx.variant || variant}
23
+
data-size={ctx.size || size}
24
+
class={cn(
25
+
toggleVariants({
26
+
variant: ctx.variant || variant,
27
+
size: ctx.size || size,
28
+
}),
29
+
"min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l",
30
+
className
31
+
)}
32
+
{value}
33
+
{...restProps}
34
+
/>
+47
apps/web/src/lib/components/ui/toggle-group/toggle-group.svelte
+47
apps/web/src/lib/components/ui/toggle-group/toggle-group.svelte
···
1
+
<script lang="ts" module>
2
+
import { getContext, setContext } from "svelte";
3
+
import type { ToggleVariants } from "$lib/components/ui/toggle/index.js";
4
+
export function setToggleGroupCtx(props: ToggleVariants) {
5
+
setContext("toggleGroup", props);
6
+
}
7
+
8
+
export function getToggleGroupCtx() {
9
+
return getContext<ToggleVariants>("toggleGroup");
10
+
}
11
+
</script>
12
+
13
+
<script lang="ts">
14
+
import { ToggleGroup as ToggleGroupPrimitive } from "bits-ui";
15
+
import { cn } from "$lib/utils/cn.js";
16
+
17
+
let {
18
+
ref = $bindable(null),
19
+
value = $bindable(),
20
+
class: className,
21
+
size = "default",
22
+
variant = "default",
23
+
...restProps
24
+
}: ToggleGroupPrimitive.RootProps & ToggleVariants = $props();
25
+
26
+
setToggleGroupCtx({
27
+
variant,
28
+
size,
29
+
});
30
+
</script>
31
+
32
+
<!--
33
+
Discriminated Unions + Destructing (required for bindable) do not
34
+
get along, so we shut typescript up by casting `value` to `never`.
35
+
-->
36
+
<ToggleGroupPrimitive.Root
37
+
bind:value={value as never}
38
+
bind:ref
39
+
data-slot="toggle-group"
40
+
data-variant={variant}
41
+
data-size={size}
42
+
class={cn(
43
+
"group/toggle-group data-[variant=outline]:shadow-xs flex w-fit items-center rounded-md",
44
+
className
45
+
)}
46
+
{...restProps}
47
+
/>
+13
apps/web/src/lib/components/ui/toggle/index.ts
+13
apps/web/src/lib/components/ui/toggle/index.ts
+52
apps/web/src/lib/components/ui/toggle/toggle.svelte
+52
apps/web/src/lib/components/ui/toggle/toggle.svelte
···
1
+
<script lang="ts" module>
2
+
import { type VariantProps, tv } from "tailwind-variants";
3
+
4
+
export const toggleVariants = tv({
5
+
base: "hover:bg-muted hover:text-muted-foreground data-[state=on]:bg-accent data-[state=on]:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
6
+
variants: {
7
+
variant: {
8
+
default: "bg-transparent",
9
+
outline:
10
+
"border-input shadow-xs hover:bg-accent hover:text-accent-foreground border bg-transparent",
11
+
},
12
+
size: {
13
+
default: "h-9 min-w-9 px-2",
14
+
sm: "h-8 min-w-8 px-1.5",
15
+
lg: "h-10 min-w-10 px-2.5",
16
+
},
17
+
},
18
+
defaultVariants: {
19
+
variant: "default",
20
+
size: "default",
21
+
},
22
+
});
23
+
24
+
export type ToggleVariant = VariantProps<typeof toggleVariants>["variant"];
25
+
export type ToggleSize = VariantProps<typeof toggleVariants>["size"];
26
+
export type ToggleVariants = VariantProps<typeof toggleVariants>;
27
+
</script>
28
+
29
+
<script lang="ts">
30
+
import { Toggle as TogglePrimitive } from "bits-ui";
31
+
import { cn } from "$lib/utils/cn.js";
32
+
33
+
let {
34
+
ref = $bindable(null),
35
+
pressed = $bindable(false),
36
+
class: className,
37
+
size = "default",
38
+
variant = "default",
39
+
...restProps
40
+
}: TogglePrimitive.RootProps & {
41
+
variant?: ToggleVariant;
42
+
size?: ToggleSize;
43
+
} = $props();
44
+
</script>
45
+
46
+
<TogglePrimitive.Root
47
+
bind:ref
48
+
bind:pressed
49
+
data-slot="toggle"
50
+
class={cn(toggleVariants({ variant, size }), className)}
51
+
{...restProps}
52
+
/>
+21
apps/web/src/lib/components/ui/tooltip/index.ts
+21
apps/web/src/lib/components/ui/tooltip/index.ts
···
1
+
import { Tooltip as TooltipPrimitive } from "bits-ui";
2
+
import Trigger from "./tooltip-trigger.svelte";
3
+
import Content from "./tooltip-content.svelte";
4
+
5
+
const Root = TooltipPrimitive.Root;
6
+
const Provider = TooltipPrimitive.Provider;
7
+
const Portal = TooltipPrimitive.Portal;
8
+
9
+
export {
10
+
Root,
11
+
Trigger,
12
+
Content,
13
+
Provider,
14
+
Portal,
15
+
//
16
+
Root as Tooltip,
17
+
Content as TooltipContent,
18
+
Trigger as TooltipTrigger,
19
+
Provider as TooltipProvider,
20
+
Portal as TooltipPortal,
21
+
};
+47
apps/web/src/lib/components/ui/tooltip/tooltip-content.svelte
+47
apps/web/src/lib/components/ui/tooltip/tooltip-content.svelte
···
1
+
<script lang="ts">
2
+
import { Tooltip as TooltipPrimitive } from "bits-ui";
3
+
import { cn } from "$lib/utils/cn.js";
4
+
5
+
let {
6
+
ref = $bindable(null),
7
+
class: className,
8
+
sideOffset = 0,
9
+
side = "top",
10
+
children,
11
+
arrowClasses,
12
+
...restProps
13
+
}: TooltipPrimitive.ContentProps & {
14
+
arrowClasses?: string;
15
+
} = $props();
16
+
</script>
17
+
18
+
<TooltipPrimitive.Portal>
19
+
<TooltipPrimitive.Content
20
+
bind:ref
21
+
data-slot="tooltip-content"
22
+
{sideOffset}
23
+
{side}
24
+
class={cn(
25
+
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--bits-tooltip-content-transform-origin) z-50 w-fit text-balance rounded-md px-3 py-1.5 text-xs",
26
+
className
27
+
)}
28
+
{...restProps}
29
+
>
30
+
{@render children?.()}
31
+
<TooltipPrimitive.Arrow>
32
+
{#snippet child({ props })}
33
+
<div
34
+
class={cn(
35
+
"bg-primary z-50 size-2.5 rotate-45 rounded-[2px]",
36
+
"data-[side=top]:translate-x-1/2 data-[side=top]:translate-y-[calc(-50%_+_2px)]",
37
+
"data-[side=bottom]:-translate-x-1/2 data-[side=bottom]:-translate-y-[calc(-50%_+_1px)]",
38
+
"data-[side=right]:translate-x-[calc(50%_+_2px)] data-[side=right]:translate-y-1/2",
39
+
"data-[side=left]:-translate-y-[calc(50%_-_3px)]",
40
+
arrowClasses
41
+
)}
42
+
{...props}
43
+
></div>
44
+
{/snippet}
45
+
</TooltipPrimitive.Arrow>
46
+
</TooltipPrimitive.Content>
47
+
</TooltipPrimitive.Portal>
+7
apps/web/src/lib/components/ui/tooltip/tooltip-trigger.svelte
+7
apps/web/src/lib/components/ui/tooltip/tooltip-trigger.svelte
+9
apps/web/src/lib/hooks/is-mobile.svelte.ts
+9
apps/web/src/lib/hooks/is-mobile.svelte.ts
+1
apps/web/src/lib/index.ts
+1
apps/web/src/lib/index.ts
···
1
+
// place files you want to import through the `$lib` alias in this folder.
+10
apps/web/src/lib/server/db/index.ts
+10
apps/web/src/lib/server/db/index.ts
···
1
+
import { drizzle } from 'drizzle-orm/libsql';
2
+
import { createClient } from '@libsql/client';
3
+
import * as schema from './schema';
4
+
import { env } from '$env/dynamic/private';
5
+
6
+
if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set');
7
+
8
+
const client = createClient({ url: env.DATABASE_URL });
9
+
10
+
export const db = drizzle(client, { schema });
+66
apps/web/src/lib/server/db/schema.ts
+66
apps/web/src/lib/server/db/schema.ts
···
1
+
import { relations } from 'drizzle-orm';
2
+
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
3
+
4
+
// still unsure about having users at all, but if we do then all users must be completely anonymous
5
+
// export const user = sqliteTable( {
6
+
// id: integer('id').primaryKey(),
7
+
// loginKey: text('loginKey').notNull().unique(),
8
+
// trustRating: integer('trustRating').notNull().default(0),
9
+
// });
10
+
11
+
export const report = sqliteTable('report', {
12
+
id: integer('id').primaryKey(),
13
+
reason: text('reason').notNull().default(''),
14
+
createdAt: text('createdAt').notNull().default(Date.now().toString()),
15
+
16
+
// default expires in 3 hours, will be extended by an hour if confirmed again within 1.5 hours of expiration
17
+
expiresAt: text('expiresAt')
18
+
.notNull()
19
+
.default((Date.now() + 4 * 60 * 60 * 1000).toString()),
20
+
});
21
+
22
+
export const reportRelations = relations(report, ({ many }) => ({
23
+
locations: many(location),
24
+
media: many(reportMedia),
25
+
confirmationFlags: many(confirmationFlag),
26
+
safeFlags: many(safeFlag),
27
+
}));
28
+
29
+
// Allows users to report abuse/etc
30
+
export const moderationReport = sqliteTable('moderationReport', {
31
+
id: integer('id').primaryKey(),
32
+
reason: text('reason').notNull().default(''),
33
+
});
34
+
35
+
export const location = sqliteTable('location', {
36
+
id: integer('id').primaryKey(),
37
+
// latitude and longitude stored as strings for accuracy
38
+
latitude: text('latitude').notNull().default('0'),
39
+
longitude: text('longitude').notNull().default('0'),
40
+
});
41
+
42
+
export const media = sqliteTable('media', {
43
+
id: integer('id').primaryKey(),
44
+
url: text('url').notNull(),
45
+
type: text('type').notNull(),
46
+
altText: text('altText').notNull(),
47
+
});
48
+
49
+
export const reportMedia = sqliteTable('reportMedia', {
50
+
reportId: integer('reportId').references(() => report.id),
51
+
mediaId: integer('mediaId').references(() => media.id),
52
+
});
53
+
54
+
export const confirmationFlag = sqliteTable('confirmationFlag', {
55
+
id: integer('id').primaryKey(),
56
+
reportId: integer('reportId').references(() => report.id),
57
+
createdAt: text('createdAt').notNull().default(Date.now().toString()),
58
+
moreInfo: text('moreInfo').notNull().default(''),
59
+
});
60
+
61
+
export const safeFlag = sqliteTable('safeFlag', {
62
+
id: integer('id').primaryKey(),
63
+
reportId: integer('reportId').references(() => report.id),
64
+
createdAt: text('createdAt').notNull().default(Date.now().toString()),
65
+
moreInfo: text('moreInfo').notNull().default(''),
66
+
});
+13
apps/web/src/lib/utils/cn.ts
+13
apps/web/src/lib/utils/cn.ts
···
1
+
import { clsx, type ClassValue } from "clsx";
2
+
import { twMerge } from "tailwind-merge";
3
+
4
+
export function cn(...inputs: ClassValue[]) {
5
+
return twMerge(clsx(inputs));
6
+
}
7
+
8
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+
export type WithoutChild<T> = T extends { child?: any } ? Omit<T, "child"> : T;
10
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, "children"> : T;
12
+
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
13
+
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
+16
apps/web/src/routes/+layout.svelte
+16
apps/web/src/routes/+layout.svelte
···
1
+
<script lang="ts">
2
+
import '../app.css';
3
+
4
+
import favicon from '$lib/assets/favicon.svg';
5
+
import AppShell from '$lib/components/layout/app-shell.svelte';
6
+
7
+
let { children } = $props();
8
+
</script>
9
+
10
+
<svelte:head>
11
+
<link rel="icon" href={favicon} />
12
+
</svelte:head>
13
+
14
+
<AppShell>
15
+
{@render children?.()}
16
+
</AppShell>
+53
apps/web/src/routes/+page.svelte
+53
apps/web/src/routes/+page.svelte
···
1
+
<script lang="ts">
2
+
import ModeSwitcher from '$lib/components/mode-switcher.svelte';
3
+
import { Button } from '$lib/components/ui/button';
4
+
import { PlusIcon } from '@lucide/svelte';
5
+
import { mode } from 'mode-watcher';
6
+
import { BottomSheet } from 'svelte-bottom-sheet';
7
+
import { MapLibre, NavigationControl, ScaleControl, GlobeControl } from 'svelte-maplibre-gl';
8
+
9
+
// import { Button } from '@iced-tea/ui/shadcn/button';
10
+
11
+
const baseMapStyles = {
12
+
voyager: 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json', // default light
13
+
positron: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json', // grey light map
14
+
'dark-matter': 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
15
+
} as const;
16
+
17
+
let currentStyle: keyof typeof baseMapStyles = $derived(
18
+
mode.current === 'dark' ? 'dark-matter' : 'voyager'
19
+
);
20
+
21
+
let isSheetOpen = $state(false);
22
+
</script>
23
+
24
+
<MapLibre
25
+
class="h-full min-h-screen w-full min-w-screen"
26
+
style={baseMapStyles[currentStyle]}
27
+
zoom={3.5}
28
+
center={{ lng: 137, lat: 36 }}
29
+
>
30
+
<NavigationControl />
31
+
<ScaleControl />
32
+
<GlobeControl />
33
+
</MapLibre>
34
+
35
+
<BottomSheet settings={{ maxHeight: 0.7 }} bind:isSheetOpen>
36
+
<BottomSheet.Overlay>
37
+
<BottomSheet.Sheet class=" !bg-card !text-card-foreground">
38
+
<BottomSheet.Handle class="!bg-transparent" />
39
+
<BottomSheet.Content>
40
+
<h3>Content inside the bottom sheet</h3>
41
+
<p>Here you can put any content you need.</p>
42
+
</BottomSheet.Content>
43
+
</BottomSheet.Sheet>
44
+
</BottomSheet.Overlay>
45
+
</BottomSheet>
46
+
47
+
<div class="absolute bottom-0 left-0 !z-50">
48
+
<Button size="icon" onclick={() => (isSheetOpen = true)} class="rounded-full">
49
+
<PlusIcon />
50
+
</Button>
51
+
52
+
<ModeSwitcher class=" rounded-full" />
53
+
</div>
+3
apps/web/static/robots.txt
+3
apps/web/static/robots.txt
+18
apps/web/svelte.config.js
+18
apps/web/svelte.config.js
···
1
+
import adapter from '@sveltejs/adapter-auto';
2
+
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3
+
4
+
/** @type {import('@sveltejs/kit').Config} */
5
+
const config = {
6
+
// Consult https://svelte.dev/docs/kit/integrations
7
+
// for more information about preprocessors
8
+
preprocess: vitePreprocess(),
9
+
10
+
kit: {
11
+
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
12
+
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
13
+
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
14
+
adapter: adapter()
15
+
}
16
+
};
17
+
18
+
export default config;
+19
apps/web/tsconfig.json
+19
apps/web/tsconfig.json
···
1
+
{
2
+
"extends": "./.svelte-kit/tsconfig.json",
3
+
"compilerOptions": {
4
+
"allowJs": true,
5
+
"checkJs": true,
6
+
"esModuleInterop": true,
7
+
"forceConsistentCasingInFileNames": true,
8
+
"resolveJsonModule": true,
9
+
"skipLibCheck": true,
10
+
"sourceMap": true,
11
+
"strict": true,
12
+
"moduleResolution": "bundler"
13
+
}
14
+
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
15
+
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
16
+
//
17
+
// To make changes to top-level options such as include and exclude, we recommend extending
18
+
// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
19
+
}
+8
apps/web/vite.config.ts
+8
apps/web/vite.config.ts
···
1
+
import devtoolsJson from 'vite-plugin-devtools-json';
2
+
import tailwindcss from '@tailwindcss/vite';
3
+
import { sveltekit } from '@sveltejs/kit/vite';
4
+
import { defineConfig } from 'vite';
5
+
6
+
export default defineConfig({
7
+
plugins: [tailwindcss(), sveltekit(), devtoolsJson()]
8
+
});
+1080
bun.lock
+1080
bun.lock
···
1
+
{
2
+
"lockfileVersion": 1,
3
+
"workspaces": {
4
+
"": {
5
+
"name": "teatime",
6
+
},
7
+
"apps/web": {
8
+
"name": "@iced-tea/web",
9
+
"version": "0.0.1",
10
+
"dependencies": {
11
+
"@fontsource/roboto": "^5.2.8",
12
+
"@lucide/svelte": "^0.544.0",
13
+
"framework7-icons": "^5.0.5",
14
+
"konsta": "^4.0.0-next.1",
15
+
"svelte-bottom-sheet": "^2.2.2",
16
+
"svelte-maplibre-gl": "^1.0.1",
17
+
},
18
+
"devDependencies": {
19
+
"@eslint/compat": "^1.4.0",
20
+
"@eslint/js": "^9.36.0",
21
+
"@internationalized/date": "^3.8.1",
22
+
"@libsql/client": "^0.15.15",
23
+
"@sveltejs/adapter-auto": "^6.1.0",
24
+
"@sveltejs/kit": "^2.43.2",
25
+
"@sveltejs/vite-plugin-svelte": "^6.2.0",
26
+
"@tailwindcss/forms": "^0.5.10",
27
+
"@tailwindcss/typography": "^0.5.18",
28
+
"@tailwindcss/vite": "^4.1.13",
29
+
"@tanstack/table-core": "^8.20.5",
30
+
"@types/node": "^22",
31
+
"bits-ui": "^2.11.0",
32
+
"clsx": "^2.1.1",
33
+
"drizzle-kit": "^0.31.4",
34
+
"drizzle-orm": "^0.44.5",
35
+
"embla-carousel-svelte": "^8.6.0",
36
+
"eslint": "^9.36.0",
37
+
"eslint-config-prettier": "^10.1.8",
38
+
"eslint-plugin-svelte": "^3.12.4",
39
+
"formsnap": "^2.0.1",
40
+
"globals": "^16.4.0",
41
+
"layerchart": "2.0.0-next.27",
42
+
"mode-watcher": "^1.1.0",
43
+
"paneforge": "^1.0.2",
44
+
"prettier": "^3.6.2",
45
+
"prettier-plugin-svelte": "^3.4.0",
46
+
"prettier-plugin-tailwindcss": "^0.6.14",
47
+
"svelte": "^5.39.5",
48
+
"svelte-check": "^4.3.2",
49
+
"svelte-sonner": "^1.0.5",
50
+
"sveltekit-superforms": "^2.26.1",
51
+
"tailwind-merge": "^3.3.1",
52
+
"tailwind-variants": "^3.1.1",
53
+
"tailwindcss": "^4.1.13",
54
+
"tw-animate-css": "^1.4.0",
55
+
"typescript": "^5.9.2",
56
+
"typescript-eslint": "^8.44.1",
57
+
"vaul-svelte": "^1.0.0-next.7",
58
+
"vite": "^7.1.7",
59
+
"vite-plugin-devtools-json": "^1.0.0",
60
+
},
61
+
},
62
+
},
63
+
"packages": {
64
+
"@ark/schema": ["@ark/schema@0.49.0", "", { "dependencies": { "@ark/util": "0.49.0" } }, "sha512-GphZBLpW72iS0v4YkeUtV3YIno35Gimd7+ezbPO9GwEi9kzdUrPVjvf6aXSBAfHikaFc/9pqZOpv3pOXnC71tw=="],
65
+
66
+
"@ark/util": ["@ark/util@0.49.0", "", {}, "sha512-/BtnX7oCjNkxi2vi6y1399b+9xd1jnCrDYhZ61f0a+3X8x8DxlK52VgEEzyuC2UQMPACIfYrmHkhD3lGt2GaMA=="],
67
+
68
+
"@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
69
+
70
+
"@dagrejs/dagre": ["@dagrejs/dagre@1.1.5", "", { "dependencies": { "@dagrejs/graphlib": "2.2.4" } }, "sha512-Ghgrh08s12DCL5SeiR6AoyE80mQELTWhJBRmXfFoqDiFkR458vPEdgTbbjA0T+9ETNxUblnD0QW55tfdvi5pjQ=="],
71
+
72
+
"@dagrejs/graphlib": ["@dagrejs/graphlib@2.2.4", "", {}, "sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw=="],
73
+
74
+
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
75
+
76
+
"@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
77
+
78
+
"@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
79
+
80
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.10", "", { "os": "aix", "cpu": "ppc64" }, "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw=="],
81
+
82
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.10", "", { "os": "android", "cpu": "arm" }, "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w=="],
83
+
84
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.10", "", { "os": "android", "cpu": "arm64" }, "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg=="],
85
+
86
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.10", "", { "os": "android", "cpu": "x64" }, "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg=="],
87
+
88
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA=="],
89
+
90
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg=="],
91
+
92
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.10", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg=="],
93
+
94
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.10", "", { "os": "freebsd", "cpu": "x64" }, "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA=="],
95
+
96
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.10", "", { "os": "linux", "cpu": "arm" }, "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg=="],
97
+
98
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ=="],
99
+
100
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.10", "", { "os": "linux", "cpu": "ia32" }, "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ=="],
101
+
102
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg=="],
103
+
104
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA=="],
105
+
106
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.10", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA=="],
107
+
108
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA=="],
109
+
110
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.10", "", { "os": "linux", "cpu": "s390x" }, "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew=="],
111
+
112
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA=="],
113
+
114
+
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A=="],
115
+
116
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.10", "", { "os": "none", "cpu": "x64" }, "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig=="],
117
+
118
+
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.10", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw=="],
119
+
120
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.10", "", { "os": "openbsd", "cpu": "x64" }, "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw=="],
121
+
122
+
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag=="],
123
+
124
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.10", "", { "os": "sunos", "cpu": "x64" }, "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ=="],
125
+
126
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw=="],
127
+
128
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="],
129
+
130
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="],
131
+
132
+
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="],
133
+
134
+
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
135
+
136
+
"@eslint/compat": ["@eslint/compat@1.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0" }, "peerDependencies": { "eslint": "^8.40 || 9" }, "optionalPeers": ["eslint"] }, "sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg=="],
137
+
138
+
"@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="],
139
+
140
+
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0" } }, "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog=="],
141
+
142
+
"@eslint/core": ["@eslint/core@0.16.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q=="],
143
+
144
+
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
145
+
146
+
"@eslint/js": ["@eslint/js@9.37.0", "", {}, "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg=="],
147
+
148
+
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
149
+
150
+
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0", "levn": "^0.4.1" } }, "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A=="],
151
+
152
+
"@exodus/schemasafe": ["@exodus/schemasafe@1.3.0", "", {}, "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw=="],
153
+
154
+
"@finom/zod-to-json-schema": ["@finom/zod-to-json-schema@3.24.11", "", { "peerDependencies": { "zod": "^4.0.14" } }, "sha512-fL656yBPiWebtfGItvtXLWrFNGlF1NcDFS0WdMQXMs9LluVg0CfT5E2oXYp0pidl0vVG53XkW55ysijNkU5/hA=="],
155
+
156
+
"@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="],
157
+
158
+
"@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="],
159
+
160
+
"@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
161
+
162
+
"@fontsource/roboto": ["@fontsource/roboto@5.2.8", "", {}, "sha512-oh9g4Cg3loVMz9MWeKWfDI+ooxxG1aRVetkiKIb2ESS2rrryGecQ/y4pAj4z5A5ebyw450dYRi/c4k/I3UBhHA=="],
163
+
164
+
"@gcornut/valibot-json-schema": ["@gcornut/valibot-json-schema@0.42.0", "", { "dependencies": { "valibot": "~0.42.0" }, "optionalDependencies": { "@types/json-schema": ">= 7.0.14", "esbuild-runner": ">= 2.2.2" }, "bin": { "valibot-json-schema": "bin/index.js" } }, "sha512-4Et4AN6wmqeA0PfU5Clkv/IS27wiefsWf6TemAZrb75uzkClYEFavim7SboeKwbll9Nbsn2Iv0LT/HS5H7orZg=="],
165
+
166
+
"@hapi/hoek": ["@hapi/hoek@9.3.0", "", {}, "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="],
167
+
168
+
"@hapi/topo": ["@hapi/topo@5.1.0", "", { "dependencies": { "@hapi/hoek": "^9.0.0" } }, "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg=="],
169
+
170
+
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
171
+
172
+
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
173
+
174
+
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
175
+
176
+
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
177
+
178
+
"@iced-tea/web": ["@iced-tea/web@workspace:apps/web"],
179
+
180
+
"@internationalized/date": ["@internationalized/date@3.10.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw=="],
181
+
182
+
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
183
+
184
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
185
+
186
+
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
187
+
188
+
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
189
+
190
+
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
191
+
192
+
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
193
+
194
+
"@layerstack/svelte-actions": ["@layerstack/svelte-actions@1.0.1-next.12", "", { "dependencies": { "@floating-ui/dom": "^1.7.0", "@layerstack/utils": "2.0.0-next.12", "d3-scale": "^4.0.2" } }, "sha512-dndWTlYu8b1u6vw2nrO7NssccoACArGG75WoNlyVC13KuENZlWdKE9Q79/wlnbq00NeQMNKMjJwRMsrKQj2ULA=="],
195
+
196
+
"@layerstack/svelte-state": ["@layerstack/svelte-state@0.1.0-next.17", "", { "dependencies": { "@layerstack/utils": "2.0.0-next.12" } }, "sha512-z7e6mPJnypD80LEI/UDuH0bI6s8/nut06MB7rEkRcEfHJekhKSJgFhMnrYzLED7Mc2gTTD0X/wcYlakauWlU8A=="],
197
+
198
+
"@layerstack/tailwind": ["@layerstack/tailwind@2.0.0-next.15", "", { "dependencies": { "@layerstack/utils": "^2.0.0-next.12", "clsx": "^2.1.1", "d3-array": "^3.2.4", "lodash-es": "^4.17.21", "tailwind-merge": "^3.2.0" } }, "sha512-7tqKE3OV7/ybeDOORX++USYYCBJa7IgTya2czFpzbgXGo7CQDVyuv+0J1DggjRcEqhhXQA4MUhgnhcRaZvHxWg=="],
199
+
200
+
"@layerstack/utils": ["@layerstack/utils@2.0.0-next.12", "", { "dependencies": { "d3-array": "^3.2.4", "d3-time": "^3.1.0", "d3-time-format": "^4.1.0", "lodash-es": "^4.17.21" } }, "sha512-fhGZUlSr3N+D44BYm37WKMGSEFyZBW+dwIqtGU8Cl54mR4TLQ/UwyGhdpgIHyH/x/8q1abE0fP0Dn6ZsrDE3BA=="],
201
+
202
+
"@libsql/client": ["@libsql/client@0.15.15", "", { "dependencies": { "@libsql/core": "^0.15.14", "@libsql/hrana-client": "^0.7.0", "js-base64": "^3.7.5", "libsql": "^0.5.22", "promise-limit": "^2.7.0" } }, "sha512-twC0hQxPNHPKfeOv3sNT6u2pturQjLcI+CnpTM0SjRpocEGgfiZ7DWKXLNnsothjyJmDqEsBQJ5ztq9Wlu470w=="],
203
+
204
+
"@libsql/core": ["@libsql/core@0.15.15", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-C88Z6UKl+OyuKKPwz224riz02ih/zHYI3Ho/LAcVOgjsunIRZoBw7fjRfaH9oPMmSNeQfhGklSG2il1URoOIsA=="],
205
+
206
+
"@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.22", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA=="],
207
+
208
+
"@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.22", "", { "os": "darwin", "cpu": "x64" }, "sha512-ny2HYWt6lFSIdNFzUFIJ04uiW6finXfMNJ7wypkAD8Pqdm6nAByO+Fdqu8t7sD0sqJGeUCiOg480icjyQ2/8VA=="],
209
+
210
+
"@libsql/hrana-client": ["@libsql/hrana-client@0.7.0", "", { "dependencies": { "@libsql/isomorphic-fetch": "^0.3.1", "@libsql/isomorphic-ws": "^0.1.5", "js-base64": "^3.7.5", "node-fetch": "^3.3.2" } }, "sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw=="],
211
+
212
+
"@libsql/isomorphic-fetch": ["@libsql/isomorphic-fetch@0.3.1", "", {}, "sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw=="],
213
+
214
+
"@libsql/isomorphic-ws": ["@libsql/isomorphic-ws@0.1.5", "", { "dependencies": { "@types/ws": "^8.5.4", "ws": "^8.13.0" } }, "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg=="],
215
+
216
+
"@libsql/linux-arm-gnueabihf": ["@libsql/linux-arm-gnueabihf@0.5.22", "", { "os": "linux", "cpu": "arm" }, "sha512-3Uo3SoDPJe/zBnyZKosziRGtszXaEtv57raWrZIahtQDsjxBVjuzYQinCm9LRCJCUT5t2r5Z5nLDPJi2CwZVoA=="],
217
+
218
+
"@libsql/linux-arm-musleabihf": ["@libsql/linux-arm-musleabihf@0.5.22", "", { "os": "linux", "cpu": "arm" }, "sha512-LCsXh07jvSojTNJptT9CowOzwITznD+YFGGW+1XxUr7fS+7/ydUrpDfsMX7UqTqjm7xG17eq86VkWJgHJfvpNg=="],
219
+
220
+
"@libsql/linux-arm64-gnu": ["@libsql/linux-arm64-gnu@0.5.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-KSdnOMy88c9mpOFKUEzPskSaF3VLflfSUCBwas/pn1/sV3pEhtMF6H8VUCd2rsedwoukeeCSEONqX7LLnQwRMA=="],
221
+
222
+
"@libsql/linux-arm64-musl": ["@libsql/linux-arm64-musl@0.5.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-mCHSMAsDTLK5YH//lcV3eFEgiR23Ym0U9oEvgZA0667gqRZg/2px+7LshDvErEKv2XZ8ixzw3p1IrBzLQHGSsw=="],
223
+
224
+
"@libsql/linux-x64-gnu": ["@libsql/linux-x64-gnu@0.5.22", "", { "os": "linux", "cpu": "x64" }, "sha512-kNBHaIkSg78Y4BqAdgjcR2mBilZXs4HYkAmi58J+4GRwDQZh5fIUWbnQvB9f95DkWUIGVeenqLRFY2pcTmlsew=="],
225
+
226
+
"@libsql/linux-x64-musl": ["@libsql/linux-x64-musl@0.5.22", "", { "os": "linux", "cpu": "x64" }, "sha512-UZ4Xdxm4pu3pQXjvfJiyCzZop/9j/eA2JjmhMaAhe3EVLH2g11Fy4fwyUp9sT1QJYR1kpc2JLuybPM0kuXv/Tg=="],
227
+
228
+
"@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.22", "", { "os": "win32", "cpu": "x64" }, "sha512-Fj0j8RnBpo43tVZUVoNK6BV/9AtDUM5S7DF3LB4qTYg1LMSZqi3yeCneUTLJD6XomQJlZzbI4mst89yspVSAnA=="],
229
+
230
+
"@lucide/svelte": ["@lucide/svelte@0.544.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-9f9O6uxng2pLB01sxNySHduJN3HTl5p0HDu4H26VR51vhZfiMzyOMe9Mhof3XAk4l813eTtl+/DYRvGyoRR+yw=="],
231
+
232
+
"@mapbox/geojson-rewind": ["@mapbox/geojson-rewind@0.5.2", "", { "dependencies": { "get-stream": "^6.0.1", "minimist": "^1.2.6" }, "bin": { "geojson-rewind": "geojson-rewind" } }, "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA=="],
233
+
234
+
"@mapbox/jsonlint-lines-primitives": ["@mapbox/jsonlint-lines-primitives@2.0.2", "", {}, "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ=="],
235
+
236
+
"@mapbox/point-geometry": ["@mapbox/point-geometry@1.1.0", "", {}, "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ=="],
237
+
238
+
"@mapbox/tiny-sdf": ["@mapbox/tiny-sdf@2.0.7", "", {}, "sha512-25gQLQMcpivjOSA40g3gO6qgiFPDpWRoMfd+G/GoppPIeP6JDaMMkMrEJnMZhKyyS6iKwVt5YKu02vCUyJM3Ug=="],
239
+
240
+
"@mapbox/unitbezier": ["@mapbox/unitbezier@0.0.1", "", {}, "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw=="],
241
+
242
+
"@mapbox/vector-tile": ["@mapbox/vector-tile@2.0.4", "", { "dependencies": { "@mapbox/point-geometry": "~1.1.0", "@types/geojson": "^7946.0.16", "pbf": "^4.0.1" } }, "sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg=="],
243
+
244
+
"@mapbox/whoots-js": ["@mapbox/whoots-js@3.1.0", "", {}, "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q=="],
245
+
246
+
"@maplibre/maplibre-gl-style-spec": ["@maplibre/maplibre-gl-style-spec@24.2.0", "", { "dependencies": { "@mapbox/jsonlint-lines-primitives": "~2.0.2", "@mapbox/unitbezier": "^0.0.1", "json-stringify-pretty-compact": "^4.0.0", "minimist": "^1.2.8", "quickselect": "^3.0.0", "rw": "^1.3.3", "tinyqueue": "^3.0.0" }, "bin": { "gl-style-migrate": "dist/gl-style-migrate.mjs", "gl-style-validate": "dist/gl-style-validate.mjs", "gl-style-format": "dist/gl-style-format.mjs" } }, "sha512-cE80g83fRcBbZbQC70siOUxUK6YJ/5ZkClDZbmm+hzrUbv+J6yntkMmcpdz9DbOrWOM7FHKR5rruc6Q/hWx5cA=="],
247
+
248
+
"@maplibre/vt-pbf": ["@maplibre/vt-pbf@4.0.3", "", { "dependencies": { "@mapbox/point-geometry": "^1.1.0", "@mapbox/vector-tile": "^2.0.4", "@types/geojson-vt": "3.2.5", "@types/supercluster": "^7.1.3", "geojson-vt": "^4.0.2", "pbf": "^4.0.1", "supercluster": "^8.0.1" } }, "sha512-YsW99BwnT+ukJRkseBcLuZHfITB4puJoxnqPVjo72rhW/TaawVYsgQHcqWLzTxqknttYoDpgyERzWSa/XrETdA=="],
249
+
250
+
"@neon-rs/load": ["@neon-rs/load@0.0.4", "", {}, "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw=="],
251
+
252
+
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
253
+
254
+
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
255
+
256
+
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
257
+
258
+
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
259
+
260
+
"@poppinss/macroable": ["@poppinss/macroable@1.1.0", "", {}, "sha512-y/YKzZDuG8XrpXpM7Z1RdQpiIc0MAKyva24Ux1PB4aI7RiSI/79K8JVDcdyubriTm7vJ1LhFs8CrZpmPnx/8Pw=="],
261
+
262
+
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.4", "", { "os": "android", "cpu": "arm" }, "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA=="],
263
+
264
+
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.4", "", { "os": "android", "cpu": "arm64" }, "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w=="],
265
+
266
+
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg=="],
267
+
268
+
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw=="],
269
+
270
+
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ=="],
271
+
272
+
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw=="],
273
+
274
+
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.4", "", { "os": "linux", "cpu": "arm" }, "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ=="],
275
+
276
+
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.4", "", { "os": "linux", "cpu": "arm" }, "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q=="],
277
+
278
+
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg=="],
279
+
280
+
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g=="],
281
+
282
+
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ=="],
283
+
284
+
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g=="],
285
+
286
+
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg=="],
287
+
288
+
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA=="],
289
+
290
+
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA=="],
291
+
292
+
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.4", "", { "os": "linux", "cpu": "x64" }, "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg=="],
293
+
294
+
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.4", "", { "os": "linux", "cpu": "x64" }, "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw=="],
295
+
296
+
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.4", "", { "os": "none", "cpu": "arm64" }, "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA=="],
297
+
298
+
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ=="],
299
+
300
+
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw=="],
301
+
302
+
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.4", "", { "os": "win32", "cpu": "x64" }, "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ=="],
303
+
304
+
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.4", "", { "os": "win32", "cpu": "x64" }, "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w=="],
305
+
306
+
"@sideway/address": ["@sideway/address@4.1.5", "", { "dependencies": { "@hapi/hoek": "^9.0.0" } }, "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q=="],
307
+
308
+
"@sideway/formula": ["@sideway/formula@3.0.1", "", {}, "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg=="],
309
+
310
+
"@sideway/pinpoint": ["@sideway/pinpoint@2.0.0", "", {}, "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="],
311
+
312
+
"@sinclair/typebox": ["@sinclair/typebox@0.34.41", "", {}, "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g=="],
313
+
314
+
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
315
+
316
+
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.6", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ=="],
317
+
318
+
"@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@6.1.1", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-cBNt4jgH4KuaNO5gRSB2CZKkGtz+OCZ8lPjRQGjhvVUD4akotnj2weUia6imLl2v07K3IgsQRyM36909miSwoQ=="],
319
+
320
+
"@sveltejs/kit": ["@sveltejs/kit@2.43.8", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-z21dG8W4g6XtAnK8bMpaSahtPOV6JVhghhco1+GR4H39XEgIxrjIpRoT1Js84c7TmhBzbTkVpZVVPFNNPFsXkQ=="],
321
+
322
+
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.1", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", "deepmerge": "^4.3.1", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ=="],
323
+
324
+
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.1", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA=="],
325
+
326
+
"@swc/helpers": ["@swc/helpers@0.5.17", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A=="],
327
+
328
+
"@tailwindcss/forms": ["@tailwindcss/forms@0.5.10", "", { "dependencies": { "mini-svg-data-uri": "^1.2.3" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" } }, "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw=="],
329
+
330
+
"@tailwindcss/node": ["@tailwindcss/node@4.1.14", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.0", "lightningcss": "1.30.1", "magic-string": "^0.30.19", "source-map-js": "^1.2.1", "tailwindcss": "4.1.14" } }, "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw=="],
331
+
332
+
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.14", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.5.1" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.14", "@tailwindcss/oxide-darwin-arm64": "4.1.14", "@tailwindcss/oxide-darwin-x64": "4.1.14", "@tailwindcss/oxide-freebsd-x64": "4.1.14", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14", "@tailwindcss/oxide-linux-arm64-musl": "4.1.14", "@tailwindcss/oxide-linux-x64-gnu": "4.1.14", "@tailwindcss/oxide-linux-x64-musl": "4.1.14", "@tailwindcss/oxide-wasm32-wasi": "4.1.14", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14", "@tailwindcss/oxide-win32-x64-msvc": "4.1.14" } }, "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw=="],
333
+
334
+
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.14", "", { "os": "android", "cpu": "arm64" }, "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ=="],
335
+
336
+
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA=="],
337
+
338
+
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw=="],
339
+
340
+
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.14", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw=="],
341
+
342
+
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14", "", { "os": "linux", "cpu": "arm" }, "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw=="],
343
+
344
+
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w=="],
345
+
346
+
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ=="],
347
+
348
+
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.14", "", { "os": "linux", "cpu": "x64" }, "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg=="],
349
+
350
+
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.14", "", { "os": "linux", "cpu": "x64" }, "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q=="],
351
+
352
+
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.14", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.0.5", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ=="],
353
+
354
+
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA=="],
355
+
356
+
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.14", "", { "os": "win32", "cpu": "x64" }, "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA=="],
357
+
358
+
"@tailwindcss/typography": ["@tailwindcss/typography@0.5.19", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg=="],
359
+
360
+
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.14", "", { "dependencies": { "@tailwindcss/node": "4.1.14", "@tailwindcss/oxide": "4.1.14", "tailwindcss": "4.1.14" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA=="],
361
+
362
+
"@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="],
363
+
364
+
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
365
+
366
+
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
367
+
368
+
"@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
369
+
370
+
"@types/geojson-vt": ["@types/geojson-vt@3.2.5", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g=="],
371
+
372
+
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
373
+
374
+
"@types/node": ["@types/node@22.18.8", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw=="],
375
+
376
+
"@types/supercluster": ["@types/supercluster@7.1.3", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA=="],
377
+
378
+
"@types/validator": ["@types/validator@13.15.3", "", {}, "sha512-7bcUmDyS6PN3EuD9SlGGOxM77F8WLVsrwkxyWxKnxzmXoequ6c7741QBrANq6htVRGOITJ7z72mTP6Z4XyuG+Q=="],
379
+
380
+
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
381
+
382
+
"@typeschema/class-validator": ["@typeschema/class-validator@0.3.0", "", { "dependencies": { "@typeschema/core": "0.14.0" }, "peerDependencies": { "class-validator": "^0.14.1" }, "optionalPeers": ["class-validator"] }, "sha512-OJSFeZDIQ8EK1HTljKLT5CItM2wsbgczLN8tMEfz3I1Lmhc5TBfkZ0eikFzUC16tI3d1Nag7um6TfCgp2I2Bww=="],
383
+
384
+
"@typeschema/core": ["@typeschema/core@0.14.0", "", { "peerDependencies": { "@types/json-schema": "^7.0.15" }, "optionalPeers": ["@types/json-schema"] }, "sha512-Ia6PtZHcL3KqsAWXjMi5xIyZ7XMH4aSnOQes8mfMLx+wGFGtGRNlwe6Y7cYvX+WfNK67OL0/HSe9t8QDygV0/w=="],
385
+
386
+
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.45.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.45.0", "@typescript-eslint/type-utils": "8.45.0", "@typescript-eslint/utils": "8.45.0", "@typescript-eslint/visitor-keys": "8.45.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.45.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg=="],
387
+
388
+
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.45.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.45.0", "@typescript-eslint/types": "8.45.0", "@typescript-eslint/typescript-estree": "8.45.0", "@typescript-eslint/visitor-keys": "8.45.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ=="],
389
+
390
+
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.45.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.45.0", "@typescript-eslint/types": "^8.45.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg=="],
391
+
392
+
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.45.0", "", { "dependencies": { "@typescript-eslint/types": "8.45.0", "@typescript-eslint/visitor-keys": "8.45.0" } }, "sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA=="],
393
+
394
+
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.45.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w=="],
395
+
396
+
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.45.0", "", { "dependencies": { "@typescript-eslint/types": "8.45.0", "@typescript-eslint/typescript-estree": "8.45.0", "@typescript-eslint/utils": "8.45.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A=="],
397
+
398
+
"@typescript-eslint/types": ["@typescript-eslint/types@8.45.0", "", {}, "sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA=="],
399
+
400
+
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.45.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.45.0", "@typescript-eslint/tsconfig-utils": "8.45.0", "@typescript-eslint/types": "8.45.0", "@typescript-eslint/visitor-keys": "8.45.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA=="],
401
+
402
+
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.45.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.45.0", "@typescript-eslint/types": "8.45.0", "@typescript-eslint/typescript-estree": "8.45.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg=="],
403
+
404
+
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.45.0", "", { "dependencies": { "@typescript-eslint/types": "8.45.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag=="],
405
+
406
+
"@vinejs/compiler": ["@vinejs/compiler@3.0.0", "", {}, "sha512-v9Lsv59nR56+bmy2p0+czjZxsLHwaibJ+SV5iK9JJfehlJMa501jUJQqqz4X/OqKXrxtE3uTQmSqjUqzF3B2mw=="],
407
+
408
+
"@vinejs/vine": ["@vinejs/vine@3.0.1", "", { "dependencies": { "@poppinss/macroable": "^1.0.4", "@types/validator": "^13.12.2", "@vinejs/compiler": "^3.0.0", "camelcase": "^8.0.0", "dayjs": "^1.11.13", "dlv": "^1.1.3", "normalize-url": "^8.0.1", "validator": "^13.12.0" } }, "sha512-ZtvYkYpZOYdvbws3uaOAvTFuvFXoQGAtmzeiXu+XSMGxi5GVsODpoI9Xu9TplEMuD/5fmAtBbKb9cQHkWkLXDQ=="],
409
+
410
+
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
411
+
412
+
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
413
+
414
+
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
415
+
416
+
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
417
+
418
+
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
419
+
420
+
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
421
+
422
+
"arktype": ["arktype@2.1.22", "", { "dependencies": { "@ark/schema": "0.49.0", "@ark/util": "0.49.0" } }, "sha512-xdzl6WcAhrdahvRRnXaNwsipCgHuNoLobRqhiP8RjnfL9Gp947abGlo68GAIyLtxbD+MLzNyH2YR4kEqioMmYQ=="],
423
+
424
+
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
425
+
426
+
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
427
+
428
+
"bits-ui": ["bits-ui@2.11.5", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.31.1", "svelte-toolbelt": "^0.10.4", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-d7b6HrrCUeK261c777agFz0G5lx13RMA0DT022e4SRuIjI3bZ8ci53YxIZ2/jpXTmeAeqeShyC+Mgibh9OeW9A=="],
429
+
430
+
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
431
+
432
+
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
433
+
434
+
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
435
+
436
+
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
437
+
438
+
"camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="],
439
+
440
+
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
441
+
442
+
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
443
+
444
+
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
445
+
446
+
"class-validator": ["class-validator@0.14.2", "", { "dependencies": { "@types/validator": "^13.11.8", "libphonenumber-js": "^1.11.1", "validator": "^13.9.0" } }, "sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw=="],
447
+
448
+
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
449
+
450
+
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
451
+
452
+
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
453
+
454
+
"commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
455
+
456
+
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
457
+
458
+
"cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
459
+
460
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
461
+
462
+
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
463
+
464
+
"d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
465
+
466
+
"d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
467
+
468
+
"d3-delaunay": ["d3-delaunay@6.0.4", "", { "dependencies": { "delaunator": "5" } }, "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="],
469
+
470
+
"d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="],
471
+
472
+
"d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="],
473
+
474
+
"d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="],
475
+
476
+
"d3-format": ["d3-format@3.1.0", "", {}, "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="],
477
+
478
+
"d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="],
479
+
480
+
"d3-geo-voronoi": ["d3-geo-voronoi@2.1.0", "", { "dependencies": { "d3-array": "3", "d3-delaunay": "6", "d3-geo": "3", "d3-tricontour": "1" } }, "sha512-kqE4yYuOjPbKdBXG0xztCacPwkVSK2REF1opSNrnqqtXJmNcM++UbwQ8SxvwP6IQTj9RvIjjK4qeiVsEfj0Z2Q=="],
481
+
482
+
"d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="],
483
+
484
+
"d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
485
+
486
+
"d3-interpolate-path": ["d3-interpolate-path@2.3.0", "", {}, "sha512-tZYtGXxBmbgHsIc9Wms6LS5u4w6KbP8C09a4/ZYc4KLMYYqub57rRBUgpUr2CIarIrJEpdAWWxWQvofgaMpbKQ=="],
487
+
488
+
"d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
489
+
490
+
"d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="],
491
+
492
+
"d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="],
493
+
494
+
"d3-sankey": ["d3-sankey@0.12.3", "", { "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" } }, "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="],
495
+
496
+
"d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
497
+
498
+
"d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="],
499
+
500
+
"d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
501
+
502
+
"d3-tile": ["d3-tile@1.0.0", "", {}, "sha512-79fnTKpPMPDS5xQ0xuS9ir0165NEwwkFpe/DSOmc2Gl9ldYzKKRDWogmTTE8wAJ8NA7PMapNfEcyKhI9Lxdu5Q=="],
503
+
504
+
"d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
505
+
506
+
"d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
507
+
508
+
"d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
509
+
510
+
"d3-tricontour": ["d3-tricontour@1.1.0", "", { "dependencies": { "d3-delaunay": "6", "d3-scale": "4" } }, "sha512-G7gHKj89n2owmkGb6WX6ixcnQ0Kf/0wpa9VIh9DGdbHu8wdrlaHU4ir3/bFNERl8N8nn4G7e7qbtBG8N9caihQ=="],
511
+
512
+
"data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],
513
+
514
+
"dayjs": ["dayjs@1.11.18", "", {}, "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA=="],
515
+
516
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
517
+
518
+
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
519
+
520
+
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
521
+
522
+
"delaunator": ["delaunator@5.0.1", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw=="],
523
+
524
+
"detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="],
525
+
526
+
"devalue": ["devalue@5.3.2", "", {}, "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw=="],
527
+
528
+
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
529
+
530
+
"drizzle-kit": ["drizzle-kit@0.31.5", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-+CHgPFzuoTQTt7cOYCV6MOw2w8vqEn/ap1yv4bpZOWL03u7rlVRQhUY0WYT3rHsgVTXwYQDZaSUJSQrMBUKuWg=="],
531
+
532
+
"drizzle-orm": ["drizzle-orm@0.44.6", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-uy6uarrrEOc9K1u5/uhBFJbdF5VJ5xQ/Yzbecw3eAYOunv5FDeYkR2m8iitocdHBOHbvorviKOW5GVw0U1j4LQ=="],
533
+
534
+
"earcut": ["earcut@3.0.2", "", {}, "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ=="],
535
+
536
+
"effect": ["effect@3.18.4", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA=="],
537
+
538
+
"embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
539
+
540
+
"embla-carousel-reactive-utils": ["embla-carousel-reactive-utils@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A=="],
541
+
542
+
"embla-carousel-svelte": ["embla-carousel-svelte@8.6.0", "", { "dependencies": { "embla-carousel": "8.6.0", "embla-carousel-reactive-utils": "8.6.0" }, "peerDependencies": { "svelte": "^3.49.0 || ^4.0.0 || ^5.0.0" } }, "sha512-ZDsKk8Sdv+AUTygMYcwZjfRd1DTh+JSUzxkOo8b9iKAkYjg+39mzbY/lwHsE3jXSpKxdKWS69hPSNuzlOGtR2Q=="],
543
+
544
+
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
545
+
546
+
"esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="],
547
+
548
+
"esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
549
+
550
+
"esbuild-runner": ["esbuild-runner@2.2.2", "", { "dependencies": { "source-map-support": "0.5.21", "tslib": "2.4.0" }, "peerDependencies": { "esbuild": "*" }, "bin": { "esr": "bin/esr.js" } }, "sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw=="],
551
+
552
+
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
553
+
554
+
"eslint": ["eslint@9.37.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.4.0", "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.37.0", "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig=="],
555
+
556
+
"eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="],
557
+
558
+
"eslint-plugin-svelte": ["eslint-plugin-svelte@3.12.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.6.1", "@jridgewell/sourcemap-codec": "^1.5.0", "esutils": "^2.0.3", "globals": "^16.0.0", "known-css-properties": "^0.37.0", "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^7.0.0", "semver": "^7.6.3", "svelte-eslint-parser": "^1.3.0" }, "peerDependencies": { "eslint": "^8.57.1 || ^9.0.0", "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-hD7wPe+vrPgx3U2X2b/wyTMtWobm660PygMGKrWWYTc9lvtY8DpNFDaU2CJQn1szLjGbn/aJ3g8WiXuKakrEkw=="],
559
+
560
+
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
561
+
562
+
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
563
+
564
+
"esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],
565
+
566
+
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
567
+
568
+
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
569
+
570
+
"esrap": ["esrap@2.1.0", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA=="],
571
+
572
+
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
573
+
574
+
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
575
+
576
+
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
577
+
578
+
"fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="],
579
+
580
+
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
581
+
582
+
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
583
+
584
+
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
585
+
586
+
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
587
+
588
+
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
589
+
590
+
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
591
+
592
+
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
593
+
594
+
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
595
+
596
+
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
597
+
598
+
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
599
+
600
+
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
601
+
602
+
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
603
+
604
+
"formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
605
+
606
+
"formsnap": ["formsnap@2.0.1", "", { "dependencies": { "svelte-toolbelt": "^0.5.0" }, "peerDependencies": { "svelte": "^5.0.0", "sveltekit-superforms": "^2.19.0" } }, "sha512-iJSe4YKd/W6WhLwKDVJU9FQeaJRpEFuolhju7ZXlRpUVyDdqFdMP8AUBICgnVvQPyP41IPAlBa/v0Eo35iE6wQ=="],
607
+
608
+
"framework7-icons": ["framework7-icons@5.0.5", "", {}, "sha512-bvHMLyujV9TFuudehd3ORZ/EvNp19Ir3ckVzYAOf3MkLymHba/9oHLsgopCh0x5UsrYZUpkrE+fd7ggj5y4wRw=="],
609
+
610
+
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
611
+
612
+
"geojson-vt": ["geojson-vt@4.0.2", "", {}, "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A=="],
613
+
614
+
"get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
615
+
616
+
"get-tsconfig": ["get-tsconfig@4.12.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw=="],
617
+
618
+
"gl-matrix": ["gl-matrix@3.4.4", "", {}, "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ=="],
619
+
620
+
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
621
+
622
+
"globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="],
623
+
624
+
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
625
+
626
+
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
627
+
628
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
629
+
630
+
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
631
+
632
+
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
633
+
634
+
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
635
+
636
+
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
637
+
638
+
"inline-style-parser": ["inline-style-parser@0.2.4", "", {}, "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="],
639
+
640
+
"internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="],
641
+
642
+
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
643
+
644
+
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
645
+
646
+
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
647
+
648
+
"is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="],
649
+
650
+
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
651
+
652
+
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
653
+
654
+
"joi": ["joi@17.13.3", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA=="],
655
+
656
+
"js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="],
657
+
658
+
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
659
+
660
+
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
661
+
662
+
"json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="],
663
+
664
+
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
665
+
666
+
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
667
+
668
+
"json-stringify-pretty-compact": ["json-stringify-pretty-compact@4.0.0", "", {}, "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q=="],
669
+
670
+
"kdbush": ["kdbush@4.0.2", "", {}, "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="],
671
+
672
+
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
673
+
674
+
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
675
+
676
+
"known-css-properties": ["known-css-properties@0.37.0", "", {}, "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ=="],
677
+
678
+
"konsta": ["konsta@4.0.0-next.1", "", {}, "sha512-AViI7CvqtJiW3ZlLcXevNk+7697vRAxPwdKhbkgfO/jf0n2WcuMl58IroKvLq7pBX3DD2cCbL/BBB7+nPkvW8g=="],
679
+
680
+
"layerchart": ["layerchart@2.0.0-next.27", "", { "dependencies": { "@dagrejs/dagre": "^1.1.4", "@layerstack/svelte-actions": "1.0.1-next.12", "@layerstack/svelte-state": "0.1.0-next.17", "@layerstack/tailwind": "2.0.0-next.15", "@layerstack/utils": "2.0.0-next.12", "d3-array": "^3.2.4", "d3-color": "^3.1.0", "d3-delaunay": "^6.0.4", "d3-dsv": "^3.0.1", "d3-force": "^3.0.0", "d3-geo": "^3.1.1", "d3-geo-voronoi": "^2.1.0", "d3-hierarchy": "^3.1.2", "d3-interpolate": "^3.0.1", "d3-interpolate-path": "^2.3.0", "d3-path": "^3.1.0", "d3-quadtree": "^3.0.1", "d3-random": "^3.0.1", "d3-sankey": "^0.12.3", "d3-scale": "^4.0.2", "d3-scale-chromatic": "^3.1.0", "d3-shape": "^3.2.0", "d3-tile": "^1.0.0", "d3-time": "^3.1.0", "lodash-es": "^4.17.21", "memoize": "^10.1.0", "runed": "^0.28.0" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-yt28xU8WzXq0AliX7eiC0JKZGQtO8M9FmHvt8sESNitSc/yC+fYeTghaO9lMRwcYCmi6D1NjbFyD9mWFeazNIQ=="],
681
+
682
+
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
683
+
684
+
"libphonenumber-js": ["libphonenumber-js@1.12.24", "", {}, "sha512-l5IlyL9AONj4voSd7q9xkuQOL4u8Ty44puTic7J88CmdXkxfGsRfoVLXHCxppwehgpb/Chdb80FFehHqjN3ItQ=="],
685
+
686
+
"libsql": ["libsql@0.5.22", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.22", "@libsql/darwin-x64": "0.5.22", "@libsql/linux-arm-gnueabihf": "0.5.22", "@libsql/linux-arm-musleabihf": "0.5.22", "@libsql/linux-arm64-gnu": "0.5.22", "@libsql/linux-arm64-musl": "0.5.22", "@libsql/linux-x64-gnu": "0.5.22", "@libsql/linux-x64-musl": "0.5.22", "@libsql/win32-x64-msvc": "0.5.22" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-NscWthMQt7fpU8lqd7LXMvT9pi+KhhmTHAJWUB/Lj6MWa0MKFv0F2V4C6WKKpjCVZl0VwcDz4nOI3CyaT1DDiA=="],
687
+
688
+
"lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
689
+
690
+
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
691
+
692
+
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
693
+
694
+
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
695
+
696
+
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
697
+
698
+
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
699
+
700
+
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
701
+
702
+
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
703
+
704
+
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
705
+
706
+
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
707
+
708
+
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
709
+
710
+
"lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="],
711
+
712
+
"locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="],
713
+
714
+
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
715
+
716
+
"lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
717
+
718
+
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
719
+
720
+
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
721
+
722
+
"maplibre-gl": ["maplibre-gl@5.9.0", "", { "dependencies": { "@mapbox/geojson-rewind": "^0.5.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/point-geometry": "^1.1.0", "@mapbox/tiny-sdf": "^2.0.7", "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^2.0.4", "@mapbox/whoots-js": "^3.1.0", "@maplibre/maplibre-gl-style-spec": "^24.2.0", "@maplibre/vt-pbf": "^4.0.3", "@types/geojson": "^7946.0.16", "@types/geojson-vt": "3.2.5", "@types/supercluster": "^7.1.3", "earcut": "^3.0.2", "geojson-vt": "^4.0.2", "gl-matrix": "^3.4.4", "kdbush": "^4.0.2", "murmurhash-js": "^1.0.0", "pbf": "^4.0.1", "potpack": "^2.1.0", "quickselect": "^3.0.0", "supercluster": "^8.0.1", "tinyqueue": "^3.0.0" } }, "sha512-YxW9glb/YrDXGDhqy1u+aG113+L86ttAUpTd6sCkGHyUKMXOX8qbGHJQVqxOczy+4CtRKnqcCfSura2MzB0nQA=="],
723
+
724
+
"memoize": ["memoize@10.1.0", "", { "dependencies": { "mimic-function": "^5.0.1" } }, "sha512-MMbFhJzh4Jlg/poq1si90XRlTZRDHVqdlz2mPyGJ6kqMpyHUyVpDd5gpFAvVehW64+RA1eKE9Yt8aSLY7w2Kgg=="],
725
+
726
+
"memoize-weak": ["memoize-weak@1.0.2", "", {}, "sha512-gj39xkrjEw7nCn4nJ1M5ms6+MyMlyiGmttzsqAUsAKn6bYKwuTHh/AO3cKPF8IBrTIYTxb0wWXFs3E//Y8VoWQ=="],
727
+
728
+
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
729
+
730
+
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
731
+
732
+
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
733
+
734
+
"mini-svg-data-uri": ["mini-svg-data-uri@1.4.4", "", { "bin": { "mini-svg-data-uri": "cli.js" } }, "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg=="],
735
+
736
+
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
737
+
738
+
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
739
+
740
+
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
741
+
742
+
"minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
743
+
744
+
"mode-watcher": ["mode-watcher@1.1.0", "", { "dependencies": { "runed": "^0.25.0", "svelte-toolbelt": "^0.7.1" }, "peerDependencies": { "svelte": "^5.27.0" } }, "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g=="],
745
+
746
+
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
747
+
748
+
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
749
+
750
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
751
+
752
+
"murmurhash-js": ["murmurhash-js@1.0.0", "", {}, "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw=="],
753
+
754
+
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
755
+
756
+
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
757
+
758
+
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
759
+
760
+
"node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
761
+
762
+
"normalize-url": ["normalize-url@8.1.0", "", {}, "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w=="],
763
+
764
+
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
765
+
766
+
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
767
+
768
+
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
769
+
770
+
"paneforge": ["paneforge@1.0.2", "", { "dependencies": { "runed": "^0.23.4", "svelte-toolbelt": "^0.9.2" }, "peerDependencies": { "svelte": "^5.29.0" } }, "sha512-KzmIXQH1wCfwZ4RsMohD/IUtEjVhteR+c+ulb/CHYJHX8SuDXoJmChtsc/Xs5Wl8NHS4L5Q7cxL8MG40gSU1bA=="],
771
+
772
+
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
773
+
774
+
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
775
+
776
+
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
777
+
778
+
"pbf": ["pbf@4.0.1", "", { "dependencies": { "resolve-protobuf-schema": "^2.1.0" }, "bin": { "pbf": "bin/pbf" } }, "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA=="],
779
+
780
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
781
+
782
+
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
783
+
784
+
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
785
+
786
+
"postcss-load-config": ["postcss-load-config@3.1.4", "", { "dependencies": { "lilconfig": "^2.0.5", "yaml": "^1.10.2" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg=="],
787
+
788
+
"postcss-safe-parser": ["postcss-safe-parser@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A=="],
789
+
790
+
"postcss-scss": ["postcss-scss@4.0.9", "", { "peerDependencies": { "postcss": "^8.4.29" } }, "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A=="],
791
+
792
+
"postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="],
793
+
794
+
"potpack": ["potpack@2.1.0", "", {}, "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ=="],
795
+
796
+
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
797
+
798
+
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
799
+
800
+
"prettier-plugin-svelte": ["prettier-plugin-svelte@3.4.0", "", { "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ=="],
801
+
802
+
"prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.14", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-hermes": "*", "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-hermes", "@prettier/plugin-oxc", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg=="],
803
+
804
+
"promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="],
805
+
806
+
"property-expr": ["property-expr@2.0.6", "", {}, "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="],
807
+
808
+
"protocol-buffers-schema": ["protocol-buffers-schema@3.6.0", "", {}, "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="],
809
+
810
+
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
811
+
812
+
"pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
813
+
814
+
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
815
+
816
+
"quickselect": ["quickselect@3.0.0", "", {}, "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g=="],
817
+
818
+
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
819
+
820
+
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
821
+
822
+
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
823
+
824
+
"resolve-protobuf-schema": ["resolve-protobuf-schema@2.1.0", "", { "dependencies": { "protocol-buffers-schema": "^3.3.1" } }, "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ=="],
825
+
826
+
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
827
+
828
+
"robust-predicates": ["robust-predicates@3.0.2", "", {}, "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="],
829
+
830
+
"rollup": ["rollup@4.52.4", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.4", "@rollup/rollup-android-arm64": "4.52.4", "@rollup/rollup-darwin-arm64": "4.52.4", "@rollup/rollup-darwin-x64": "4.52.4", "@rollup/rollup-freebsd-arm64": "4.52.4", "@rollup/rollup-freebsd-x64": "4.52.4", "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", "@rollup/rollup-linux-arm-musleabihf": "4.52.4", "@rollup/rollup-linux-arm64-gnu": "4.52.4", "@rollup/rollup-linux-arm64-musl": "4.52.4", "@rollup/rollup-linux-loong64-gnu": "4.52.4", "@rollup/rollup-linux-ppc64-gnu": "4.52.4", "@rollup/rollup-linux-riscv64-gnu": "4.52.4", "@rollup/rollup-linux-riscv64-musl": "4.52.4", "@rollup/rollup-linux-s390x-gnu": "4.52.4", "@rollup/rollup-linux-x64-gnu": "4.52.4", "@rollup/rollup-linux-x64-musl": "4.52.4", "@rollup/rollup-openharmony-arm64": "4.52.4", "@rollup/rollup-win32-arm64-msvc": "4.52.4", "@rollup/rollup-win32-ia32-msvc": "4.52.4", "@rollup/rollup-win32-x64-gnu": "4.52.4", "@rollup/rollup-win32-x64-msvc": "4.52.4", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ=="],
831
+
832
+
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
833
+
834
+
"runed": ["runed@0.31.1", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-v3czcTnO+EJjiPvD4dwIqfTdHLZ8oH0zJheKqAHh9QMViY7Qb29UlAMRpX7ZtHh7AFqV60KmfxaJ9QMy+L1igQ=="],
835
+
836
+
"rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="],
837
+
838
+
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
839
+
840
+
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
841
+
842
+
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
843
+
844
+
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
845
+
846
+
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
847
+
848
+
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
849
+
850
+
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
851
+
852
+
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
853
+
854
+
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
855
+
856
+
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
857
+
858
+
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
859
+
860
+
"style-to-object": ["style-to-object@1.0.11", "", { "dependencies": { "inline-style-parser": "0.2.4" } }, "sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow=="],
861
+
862
+
"supercluster": ["supercluster@8.0.1", "", { "dependencies": { "kdbush": "^4.0.2" } }, "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ=="],
863
+
864
+
"superstruct": ["superstruct@2.0.2", "", {}, "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A=="],
865
+
866
+
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
867
+
868
+
"svelte": ["svelte@5.39.8", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-KfZ3hCITdxIXTOvrea4nFZX2o+47HPTChKeocgj9BwJQYqWrviVCcPj4boXHF5yf8+eBKqhHY8xii//XaakKXA=="],
869
+
870
+
"svelte-bottom-sheet": ["svelte-bottom-sheet@2.2.2", "", { "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-tvlc173kTiNgyfX/T88ewQoA6dYALtabWDaq6xATkpiiuuIUjji78PWMRvuy+do5ZxmJQn4pBcK1KBHob211NQ=="],
871
+
872
+
"svelte-check": ["svelte-check@4.3.2", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-71udP5w2kaSTcX8iV0hn3o2FWlabQHhJTJLIQrCqMsrcOeDUO2VhCQKKCA8AMVHSPwdxLEWkUWh9OKxns5PD9w=="],
873
+
874
+
"svelte-eslint-parser": ["svelte-eslint-parser@1.3.3", "", { "dependencies": { "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.0", "postcss": "^8.4.49", "postcss-scss": "^4.0.9", "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-oTrDR8Z7Wnguut7QH3YKh7JR19xv1seB/bz4dxU5J/86eJtZOU4eh0/jZq4dy6tAlz/KROxnkRQspv5ZEt7t+Q=="],
875
+
876
+
"svelte-maplibre-gl": ["svelte-maplibre-gl@1.0.1", "", { "peerDependencies": { "maplibre-gl": "^5.0.0 || ^4.0.0", "svelte": ">=5.0.0" } }, "sha512-DbDLwXIQ8sGJ4VSAheAIMwJBM/bpQ3EBryaYvMIZWwgGhKSBsfkaPJrKR3dblIrMfhfRBsHnZ/bAWvk0pHgSmQ=="],
877
+
878
+
"svelte-sonner": ["svelte-sonner@1.0.5", "", { "dependencies": { "runed": "^0.28.0" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-9dpGPFqKb/QWudYqGnEz93vuY+NgCEvyNvxoCLMVGw6sDN/3oVeKV1xiEirW2E1N3vJEyj5imSBNOGltQHA7mg=="],
879
+
880
+
"svelte-toolbelt": ["svelte-toolbelt@0.10.5", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.29.0", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.30.2" } }, "sha512-8e+eWTgxw1aiLxhDE8Rb1X6AoLitqpJz+WhAul2W7W58C8KoLoJQf1TgQdFPBiCPJ0Jg5y0Zi1uyua9em4VS0w=="],
881
+
882
+
"sveltekit-superforms": ["sveltekit-superforms@2.27.2", "", { "dependencies": { "devalue": "^5.3.2", "memoize-weak": "^1.0.2", "ts-deepmerge": "^7.0.3" }, "optionalDependencies": { "@exodus/schemasafe": "^1.3.0", "@finom/zod-to-json-schema": "^3.24.11", "@gcornut/valibot-json-schema": "^0.42.0", "@sinclair/typebox": "^0.34.41", "@typeschema/class-validator": "^0.3.0", "@vinejs/vine": "^3.0.1", "arktype": "^2.1.22", "class-validator": "^0.14.2", "effect": "^3.18.1", "joi": "^17.13.3", "json-schema-to-ts": "^3.1.1", "superstruct": "^2.0.2", "valibot": "^1.1.0", "yup": "^1.7.1", "zod": "^4.1.11" }, "peerDependencies": { "@sveltejs/kit": "1.x || 2.x", "svelte": "3.x || 4.x || >=5.0.0-next.51" } }, "sha512-RwVJiII0StFW0RZ3k5sLAiSavngTxl0gJR2P5m6Bck0Zw1FYM8qW4NQGUQEF1YieO4fwWOZgg6iyByDC5pO8fA=="],
883
+
884
+
"tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="],
885
+
886
+
"tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="],
887
+
888
+
"tailwind-variants": ["tailwind-variants@3.1.1", "", { "peerDependencies": { "tailwind-merge": ">=3.0.0", "tailwindcss": "*" }, "optionalPeers": ["tailwind-merge"] }, "sha512-ftLXe3krnqkMHsuBTEmaVUXYovXtPyTK7ckEfDRXS8PBZx0bAUas+A0jYxuKA5b8qg++wvQ3d2MQ7l/xeZxbZQ=="],
889
+
890
+
"tailwindcss": ["tailwindcss@4.1.14", "", {}, "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA=="],
891
+
892
+
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
893
+
894
+
"tar": ["tar@7.5.1", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g=="],
895
+
896
+
"tiny-case": ["tiny-case@1.0.3", "", {}, "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="],
897
+
898
+
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
899
+
900
+
"tinyqueue": ["tinyqueue@3.0.0", "", {}, "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g=="],
901
+
902
+
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
903
+
904
+
"toposort": ["toposort@2.0.2", "", {}, "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="],
905
+
906
+
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
907
+
908
+
"ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="],
909
+
910
+
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
911
+
912
+
"ts-deepmerge": ["ts-deepmerge@7.0.3", "", {}, "sha512-Du/ZW2RfwV/D4cmA5rXafYjBQVuvu4qGiEEla4EmEHVHgRdx68Gftx7i66jn2bzHPwSVZY36Ae6OuDn9el4ZKA=="],
913
+
914
+
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
915
+
916
+
"tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
917
+
918
+
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
919
+
920
+
"type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="],
921
+
922
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
923
+
924
+
"typescript-eslint": ["typescript-eslint@8.45.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.45.0", "@typescript-eslint/parser": "8.45.0", "@typescript-eslint/typescript-estree": "8.45.0", "@typescript-eslint/utils": "8.45.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg=="],
925
+
926
+
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
927
+
928
+
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
929
+
930
+
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
931
+
932
+
"uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
933
+
934
+
"valibot": ["valibot@1.1.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw=="],
935
+
936
+
"validator": ["validator@13.15.15", "", {}, "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A=="],
937
+
938
+
"vaul-svelte": ["vaul-svelte@1.0.0-next.7", "", { "dependencies": { "runed": "^0.23.2", "svelte-toolbelt": "^0.7.1" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-7zN7Bi3dFQixvvbUJY9uGDe7Ws/dGZeBQR2pXdXmzQiakjrxBvWo0QrmsX3HK+VH+SZOltz378cmgmCS9f9rSg=="],
939
+
940
+
"vite": ["vite@7.1.9", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg=="],
941
+
942
+
"vite-plugin-devtools-json": ["vite-plugin-devtools-json@1.0.0", "", { "dependencies": { "uuid": "^11.1.0" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-MobvwqX76Vqt/O4AbnNMNWoXWGrKUqZbphCUle/J2KXH82yKQiunOeKnz/nqEPosPsoWWPP9FtNuPBSYpiiwkw=="],
943
+
944
+
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
945
+
946
+
"web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
947
+
948
+
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
949
+
950
+
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
951
+
952
+
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
953
+
954
+
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
955
+
956
+
"yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="],
957
+
958
+
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
959
+
960
+
"yup": ["yup@1.7.1", "", { "dependencies": { "property-expr": "^2.0.5", "tiny-case": "^1.0.3", "toposort": "^2.0.2", "type-fest": "^2.19.0" } }, "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw=="],
961
+
962
+
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
963
+
964
+
"zod": ["zod@4.1.12", "", {}, "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ=="],
965
+
966
+
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
967
+
968
+
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
969
+
970
+
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
971
+
972
+
"@gcornut/valibot-json-schema/valibot": ["valibot@0.42.1", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw=="],
973
+
974
+
"@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.1", "", {}, "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw=="],
975
+
976
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="],
977
+
978
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
979
+
980
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
981
+
982
+
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.6", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-DXj75ewm11LIWUk198QSKUTxjyRjsBwk09MuMk5DGK+GDUtyPhhEHOGP/Xwwj3DjQXXkivoBirmOnKrLfc0+9g=="],
983
+
984
+
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
985
+
986
+
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
987
+
988
+
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
989
+
990
+
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
991
+
992
+
"d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="],
993
+
994
+
"d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="],
995
+
996
+
"esbuild-runner/tslib": ["tslib@2.4.0", "", {}, "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="],
997
+
998
+
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
999
+
1000
+
"formsnap/svelte-toolbelt": ["svelte-toolbelt@0.5.0", "", { "dependencies": { "clsx": "^2.1.1", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0-next.126" } }, "sha512-t3tenZcnfQoIeRuQf/jBU7bvTeT3TGkcEE+1EUr5orp0lR7NEpprflpuie3x9Dn0W9nOKqs3HwKGJeeN5Ok1sQ=="],
1001
+
1002
+
"layerchart/runed": ["runed@0.28.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ=="],
1003
+
1004
+
"lightningcss/detect-libc": ["detect-libc@2.1.1", "", {}, "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw=="],
1005
+
1006
+
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
1007
+
1008
+
"mode-watcher/runed": ["runed@0.25.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-7+ma4AG9FT2sWQEA0Egf6mb7PBT2vHyuHail1ie8ropfSjvZGtEAx8YTmUjv/APCsdRRxEVvArNjALk9zFSOrg=="],
1009
+
1010
+
"mode-watcher/svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="],
1011
+
1012
+
"paneforge/runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="],
1013
+
1014
+
"paneforge/svelte-toolbelt": ["svelte-toolbelt@0.9.3", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.29.0", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.30.2" } }, "sha512-HCSWxCtVmv+c6g1ACb8LTwHVbDqLKJvHpo6J8TaqwUme2hj9ATJCpjCPNISR1OCq2Q4U1KT41if9ON0isINQZw=="],
1015
+
1016
+
"svelte-eslint-parser/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="],
1017
+
1018
+
"svelte-sonner/runed": ["runed@0.28.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ=="],
1019
+
1020
+
"svelte-toolbelt/runed": ["runed@0.29.2", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-0cq6cA6sYGZwl/FvVqjx9YN+1xEBu9sDDyuWdDW1yWX7JF2wmvmVKfH+hVCZs+csW+P3ARH92MjI3H9QTagOQA=="],
1021
+
1022
+
"vaul-svelte/runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="],
1023
+
1024
+
"vaul-svelte/svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="],
1025
+
1026
+
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
1027
+
1028
+
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
1029
+
1030
+
"@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
1031
+
1032
+
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
1033
+
1034
+
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
1035
+
1036
+
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
1037
+
1038
+
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
1039
+
1040
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
1041
+
1042
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
1043
+
1044
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
1045
+
1046
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
1047
+
1048
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
1049
+
1050
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
1051
+
1052
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
1053
+
1054
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
1055
+
1056
+
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
1057
+
1058
+
"@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
1059
+
1060
+
"@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
1061
+
1062
+
"@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
1063
+
1064
+
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
1065
+
1066
+
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
1067
+
1068
+
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
1069
+
1070
+
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
1071
+
1072
+
"d3-sankey/d3-array/internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="],
1073
+
1074
+
"d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="],
1075
+
1076
+
"mode-watcher/svelte-toolbelt/runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="],
1077
+
1078
+
"paneforge/svelte-toolbelt/runed": ["runed@0.29.2", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-0cq6cA6sYGZwl/FvVqjx9YN+1xEBu9sDDyuWdDW1yWX7JF2wmvmVKfH+hVCZs+csW+P3ARH92MjI3H9QTagOQA=="],
1079
+
}
1080
+
}
+13
package.json
+13
package.json
···
1
+
{
2
+
"name": "iced-tea",
3
+
"description": "Fuck ICE, Fuck Nazis, Free Palestine. Track and report locations of pigs and ICE officers and help keep our community safe from fascists",
4
+
"version": "0.0.1",
5
+
"workspaces": [
6
+
"packages/*",
7
+
"apps/*"
8
+
],
9
+
"scripts": {
10
+
"dev": "npm run --filter '@iced-tea/*' dev",
11
+
"dev:web": "npm run --filter '@iced-tea/web' dev"
12
+
}
13
+
}