` from `mergeProcessedZipArchive`.
+ - Add the pure helpers: `createSubDocument`, `moveAttachmentIntoSubDocument`, `moveSubDocument`, `removeAttachmentFromSubDocument` (returns attachments to the loose list), `flattenArchiveForMerge`, `buildArchiveExport`.
+- Verification: TypeScript compiles (`pnpm check` / `svelte-check`); existing tests (if any) still pass; existing UI still renders unchanged.
+
+### Phase 2 — Sub-document block component
+- New `src/lib/components/SubDocumentEditor.svelte`:
+ - Props: `subDocument`, `thumbnailWidth`, `onSubDocumentChange`, `onRemove`, `drag handlers` (or pass a generic reorder callback).
+ - Renders the editable name, count, remove button, draggable header, horizontal attachment list (reusing `AttachmentPreview` + the same DnD styling).
+ - Internally mirrors `ProcessedZipArchiveEditor`'s drag logic, scoped to the block.
+- Verify: can be unit-rendered in isolation (storybook-equivalent or a throwaway page snippet).
+
+### Phase 3 — Selection mode + sub-document creation in `ProcessedZipArchiveEditor`
+- Add `selectionMode` and `selectedPaths` state and the "Auswählen" / "Fertig" header toggle.
+- While `selectionMode` is on, render a checkbox on each loose thumbnail and make the whole card a click-to-toggle target; suspend drag-to-reorder to avoid click/drag ambiguity.
+- Add the inline action bar with **"Teildokument erstellen"**, visible when a selection exists.
+- On create: call `createSubDocument`, remove the selected attachments from the loose list, clear `selectedPaths`, keep `selectionMode` on, and emit `onArchiveChange`.
+- `Esc` / "Fertig" exits selection mode and clears the selection.
+- On sub-document removal: push its attachments back into the loose list (appended at the end by default).
+- Verify: toggling selection mode shows/hides checkboxes; in normal mode the editor looks identical to today; creating, populating, and removing sub-documents works end-to-end with reordering still working for loose attachments.
+
+### Phase 4 — Sub-document drag interactions
+- Generalise the existing HTML5 DnD handlers to support the three move scenarios listed above. Use the `dataTransfer` payload to encode `{ source: 'loose' | `sub:${id}`, index }`.
+- Reorder sub-document blocks via header drag.
+- Verify: items can be moved loose↔sub and sub↔sub; sub-document order can be changed; nothing is duplicated or lost (count invariant: `loose.length + Σ sub.attachments.length === total attachments`).
+
+### Phase 5 — Export modes
+- Replace header download button with the segmented control + button when sub-documents exist.
+- Wire `buildArchiveExport(archive, mode)` to `downloadPdfBytes` (single) and the sequential loop (separate).
+- `+page.svelte`: keep `exportAllZipArchivesAsPdf` in single mode; optionally surface a small hint when an archive has sub-documents.
+- Verify:
+ - No sub-documents → existing single-PDF download unchanged.
+ - With sub-documents, "Eine PDF" flattens and downloads one PDF.
+ - With sub-documents, "Getrennt" downloads N files named `{archiveName} - {subName}.pdf`.
+
+### Phase 6 — Polish
+- Empty states (e.g. empty sub-document block, no loose attachments).
+- Disable the create-sub-document button when selection is empty.
+- Accessible labels + keyboard operability for checkboxes / segmented control (`bits-ui` SegmentedControl if available, otherwise native radio group).
+- Update `agents.md` "ZIP/PDF processing details" + "UI/state details" sections to mention sub-documents.
+- Manual smoke test on a real `xjustiz` ZIP with nested archives.
+
+---
+
+## Verification checklist (definition of done)
+
+- [ ] `pnpm check` (or `svelte-check`) passes with no new errors.
+- [ ] `pnpm build` succeeds.
+- [ ] Loading a ZIP without creating sub-documents produces the exact same merged PDF as today.
+- [ ] Toggling "Auswählen" shows checkboxes on thumbnails; toggling "Fertig" (or pressing Esc) hides them and clears the selection. In normal mode the editor looks identical to today (no checkboxes).
+- [ ] Selecting ≥1 attachments and clicking "Teildokument erstellen" removes them from the loose list and adds a named sub-document block, then clears the selection while staying in selection mode for the next group.
+- [ ] Drag-reordering works for: loose attachments, attachments inside a sub-document, sub-document blocks themselves, and moving an attachment loose↔sub.
+- [ ] With sub-documents present:
+ - "Eine PDF" downloads a single PDF containing every attachment (sub-documents first, then loose).
+ - "Getrennt" downloads one PDF per sub-document, each correctly named.
+- [ ] Removing a sub-document returns its attachments to the loose list; total attachment count is invariant.
+- [ ] Bulk "Alle ZIP-Archive als PDF exportieren" still works (single mode).
+- [ ] `agents.md` updated.
+
+---
+
+## Out of scope (follow-ups)
+
+- Persisting sub-document structure to `localStorage`.
+- Renaming attachments themselves (only sub-document names are editable in v1).
+- Exporting "separate" as ZIPs or original-format files (see D4-C).
+- Per-archive export mode remembered by the bulk exporter (D3 follow-up).
+- Drag-and-drop between *different archives* in `+page.svelte` (today each editor is self-contained).
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 32f3ff5..82f7eed 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,16 +8,25 @@ importers:
.:
dependencies:
- '@skeletonlabs/skeleton':
- specifier: ^4.15.2
- version: 4.15.2(tailwindcss@4.3.0)
- '@skeletonlabs/skeleton-svelte':
- specifier: ^4.15.2
- version: 4.15.2(svelte@5.56.3)
+ fflate:
+ specifier: ^0.8.3
+ version: 0.8.3
+ pdf-lib:
+ specifier: ^1.17.1
+ version: 1.17.1
+ pdfjs-dist:
+ specifier: ^6.0.227
+ version: 6.0.227
devDependencies:
- '@sveltejs/adapter-auto':
- specifier: ^7.0.1
- version: 7.0.1(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))
+ '@fontsource-variable/geist':
+ specifier: ^5.2.9
+ version: 5.2.9
+ '@lucide/svelte':
+ specifier: ^1.18.0
+ version: 1.18.0(svelte@5.56.3)
+ '@sveltejs/adapter-node':
+ specifier: ^5.5.7
+ version: 5.5.7(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))
'@sveltejs/kit':
specifier: ^2.63.0
version: 2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0))
@@ -33,6 +42,15 @@ importers:
'@tailwindcss/vite':
specifier: ^4.3.0
version: 4.3.0(vite@8.0.16(jiti@2.7.0))
+ bits-ui:
+ specifier: 2.18.1
+ version: 2.18.1(@internationalized/date@3.12.2)(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)
+ class-variance-authority:
+ specifier: 0.7.1
+ version: 0.7.1
+ clsx:
+ specifier: 2.1.1
+ version: 2.1.1
prettier:
specifier: ^3.8.3
version: 3.8.4
@@ -42,15 +60,27 @@ importers:
prettier-plugin-tailwindcss:
specifier: ^0.8.0
version: 0.8.0(prettier-plugin-svelte@4.1.0(prettier@3.8.4)(svelte@5.56.3))(prettier@3.8.4)
+ shadcn-svelte:
+ specifier: 1.3.0
+ version: 1.3.0(svelte@5.56.3)
svelte:
specifier: ^5.56.1
version: 5.56.3
svelte-check:
specifier: ^4.6.0
version: 4.6.0(picomatch@4.0.4)(svelte@5.56.3)(typescript@6.0.3)
+ tailwind-merge:
+ specifier: 3.6.0
+ version: 3.6.0
+ tailwind-variants:
+ specifier: ^3.2.2
+ version: 3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0)
tailwindcss:
specifier: ^4.3.0
version: 4.3.0
+ tw-animate-css:
+ specifier: ^1.4.0
+ version: 1.4.0
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -78,8 +108,11 @@ packages:
'@floating-ui/utils@0.2.11':
resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
- '@internationalized/date@3.12.0':
- resolution: {integrity: sha512-/PyIMzK29jtXaGU23qTvNZxvBXRtKbNnGDFD+PY6CZw/Y8Ex8pFUzkuCJCG9aOqmShjqhS9mPqP6Dk5onQY8rQ==}
+ '@fontsource-variable/geist@5.2.9':
+ resolution: {integrity: sha512-TP+QSBG3wxKGPE33CbMy/L0Nu3qvJ6Fy81Yc4LnQ95xH+i+cfEp8fyU8/kfV14YwszxIFPhnoMTbjL71waVpyQ==}
+
+ '@internationalized/date@3.12.2':
+ resolution: {integrity: sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==}
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
@@ -97,6 +130,86 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@lucide/svelte@1.18.0':
+ resolution: {integrity: sha512-S1cjiJflMLIirDZtZ8ou2Vy0xMrOqEQzYzDo29AUxoJiOjUfMHUeClvprJsGUEr60RYDJzEgkjSkWm1nlN9iyQ==}
+ peerDependencies:
+ svelte: ^5
+
+ '@napi-rs/canvas-android-arm64@1.0.0':
+ resolution: {integrity: sha512-3hNKJObUK7JsCF9aJlVCs1J0/KE/gGfZNeK8MO1ge6bB3aicr5walGme9t9No1f/oyk9GgvdAT/rjSdsx3gbIw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@napi-rs/canvas-darwin-arm64@1.0.0':
+ resolution: {integrity: sha512-ZIja19/BiGz2puhki+WUYSRriwFeFJ8Mi9eK3hZdSS85w4Y60cuEAJVhMCfKwswQkKkUtrnzdKMBuO7TupvexA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@napi-rs/canvas-darwin-x64@1.0.0':
+ resolution: {integrity: sha512-hImggWc82jqZVpEsFR9S7PE9OQYjq/H/D7vwCGB6X1jRH+UVBP1+1niJTPBOat1B154T6GKK7/kcFtoWgjgFzQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@napi-rs/canvas-linux-arm-gnueabihf@1.0.0':
+ resolution: {integrity: sha512-hlJRy6d+kWLKVOG/+1rEvNQVURZ0DxxRPJsLmEWwhwiXZUJc0BF5o9esALHSEP4CoJK4wChRtj3hnyBgVx2oWA==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-arm64-gnu@1.0.0':
+ resolution: {integrity: sha512-5Hru4T3RXkosRQafcjelv7AUzw9mXqmGYsxnzeDDOWveFCJyEPMSJltvGCM+jfH98seOCbfwm9KyFg6Jm5FhAA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@napi-rs/canvas-linux-arm64-musl@1.0.0':
+ resolution: {integrity: sha512-LTUl9jS8WsLSUGaxQZKQkxfluOJRpgvBuxxdM4pYcjib+di8AU4OzQc6+L6SzGMLcKc9H0RAjojRatBhTMqYdg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@napi-rs/canvas-linux-riscv64-gnu@1.0.0':
+ resolution: {integrity: sha512-Iz931SAZf+WVDzpjk52Q3ffW3zw0YflFwEZMgs036Wfu1kX/LrwT9wGjsuSqyduqefUkl91/vTdAjn8hQu5ezA==}
+ engines: {node: '>= 10'}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@napi-rs/canvas-linux-x64-gnu@1.0.0':
+ resolution: {integrity: sha512-pFEQ5eFK4JusgN1K6KkO9DKP/Hi1WMJOkF8Ch03/khTc4bFbCKkCCsJG4YcOMOW9bI4XbT2/eMAWxhO0xaWgPA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@napi-rs/canvas-linux-x64-musl@1.0.0':
+ resolution: {integrity: sha512-jnvr8NrLHiZ3NCiOKWqDbkI4Ah+QDrqtZ+sddPZBltEb1mQ2coSvCSJYfict+oAwcm0c970oTmVySpjKP/lnaA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@napi-rs/canvas-win32-arm64-msvc@1.0.0':
+ resolution: {integrity: sha512-y2j9/Gfd5joqiqxdP/L1smqjQ+uAx3C4N0EC7bDHrnZEEH8ToM/OC5p3uHvtj4Lq591aHj+ArL01UDLNwT5HgQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@napi-rs/canvas-win32-x64-msvc@1.0.0':
+ resolution: {integrity: sha512-qwdhh9N6Gge/hC4pL9S1tQp0iKwhSl/dYjg7+RGp9k26iRGRi5MqqUyKGOXIWli0zOcuy5Y2wIH/jk2ry6i/jA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@napi-rs/canvas@1.0.0':
+ resolution: {integrity: sha512-Jqxcy1XOIqj+lH9sl1GT+il6GR3uQv13vI2mrwubP3uT8Olak2ClDrK2RnxlQKjwv8BRr4b3ug0YR7c6hBX8wg==}
+ engines: {node: '>= 10'}
+
'@napi-rs/wasm-runtime@1.1.5':
resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==}
peerDependencies:
@@ -106,6 +219,12 @@ packages:
'@oxc-project/types@0.133.0':
resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==}
+ '@pdf-lib/standard-fonts@1.0.0':
+ resolution: {integrity: sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==}
+
+ '@pdf-lib/upng@1.0.1':
+ resolution: {integrity: sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==}
+
'@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
@@ -207,18 +326,188 @@ packages:
'@rolldown/pluginutils@1.0.1':
resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
- '@skeletonlabs/skeleton-common@4.15.2':
- resolution: {integrity: sha512-y7KZn++Av8UHdoeaaguQ7zIS1HlK7Y5jyPDnHy65wJ60iS97fMtQV0kGhqVoYCWhor+xrjbAFjWtaPOPPDEMYA==}
-
- '@skeletonlabs/skeleton-svelte@4.15.2':
- resolution: {integrity: sha512-vZkRhR701EOHVXVKh/NFRSY8D9LPBvmdNFdtfgqO7TEg77sypJUvERl2dxErTLY1QjVklVpjsHRCTaSLn+1Ntg==}
+ '@rollup/plugin-commonjs@29.0.3':
+ resolution: {integrity: sha512-ZaOxZceP7SOUW7Lqw5IRVweSQYWaeIPnXIGLiB690EBA3FGJTO40EEr2L5yZplJWsgTCogILRSpcAe7+U0Otdg==}
+ engines: {node: '>=16.0.0 || 14 >= 14.17'}
peerDependencies:
- svelte: ^5.29.0
+ rollup: ^2.68.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
- '@skeletonlabs/skeleton@4.15.2':
- resolution: {integrity: sha512-5O23Py76nw56aoieV2b2T7MJ6xS0DwDjUULpwLnCXxXOnmzADEoWoQxb/ABbqg04IMOygtRzK3HO22I1+kFsog==}
+ '@rollup/plugin-json@6.1.0':
+ resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==}
+ engines: {node: '>=14.0.0'}
peerDependencies:
- tailwindcss: ^4.0.0
+ rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/plugin-node-resolve@16.0.3':
+ resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^2.78.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/plugin-replace@6.0.3':
+ resolution: {integrity: sha512-J4RZarRvQAm5IF0/LwUUg+obsm+xZhYnbMXmXROyoSE1ATJe3oXSb9L5MMppdxP2ylNSjv6zFBwKYjcKMucVfA==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/pluginutils@5.4.0':
+ resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@rollup/rollup-android-arm-eabi@4.62.2':
+ resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.62.2':
+ resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.62.2':
+ resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.62.2':
+ resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.62.2':
+ resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.62.2':
+ resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.62.2':
+ resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.62.2':
+ resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==}
+ cpu: [arm]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-arm64-gnu@4.62.2':
+ resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm64-musl@4.62.2':
+ resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-loong64-gnu@4.62.2':
+ resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-loong64-musl@4.62.2':
+ resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.62.2':
+ resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-ppc64-musl@4.62.2':
+ resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.62.2':
+ resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-riscv64-musl@4.62.2':
+ resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-s390x-gnu@4.62.2':
+ resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-gnu@4.62.2':
+ resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-musl@4.62.2':
+ resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-openbsd-x64@4.62.2':
+ resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@rollup/rollup-openharmony-arm64@4.62.2':
+ resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.62.2':
+ resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.62.2':
+ resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.62.2':
+ resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.62.2':
+ resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==}
+ cpu: [x64]
+ os: [win32]
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
@@ -228,10 +517,10 @@ packages:
peerDependencies:
acorn: ^8.9.0
- '@sveltejs/adapter-auto@7.0.1':
- resolution: {integrity: sha512-dvuPm1E7M9NI/+canIQ6KKQDU2AkEefEZ2Dp7cY6uKoPq9Z/PhOXABe526UdW2mN986gjVkuSLkOYIBnS/M2LQ==}
+ '@sveltejs/adapter-node@5.5.7':
+ resolution: {integrity: sha512-uOfc9eVlI3A37RRSaKcgrheBYPrfJwC9VMqDp8x/O6tlKdcLLvHThSWD0KNIbjQ/d+7bwLGx3vx6aowAcRfd2g==}
peerDependencies:
- '@sveltejs/kit': ^2.0.0
+ '@sveltejs/kit': ^2.4.0
'@sveltejs/kit@2.64.0':
resolution: {integrity: sha512-24MXA/xyugUqJd09DD4v4bLd4k7FaYhdBck/pTXiu3XFtDBcwXYpJc1SO1+lqdjkNBUo1r4eek5FS7cfzBQUmA==}
@@ -376,156 +665,12 @@ packages:
'@types/estree@1.0.9':
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+ '@types/resolve@1.20.2':
+ resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
+
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
- '@zag-js/accordion@1.39.1':
- resolution: {integrity: sha512-GA3m7gRTm3weSe1eMlHIsTNztcjZ6joIaRgxxKil7q/UX0xIVVGDy0aCr6oo7FAuoMiOOBVurYXILpFZ30nOXA==}
-
- '@zag-js/anatomy@1.39.1':
- resolution: {integrity: sha512-p2iFAs2pVQgv5iCDAftA7g9Z/fUYXW94dRIGk415TSbkp/YDENydm/JtRoNctp302UIx4Eeuc5QBR+7h5kuISA==}
-
- '@zag-js/aria-hidden@1.39.1':
- resolution: {integrity: sha512-wiwcz3N086qBMEU3VKfHhcvGm6Jm1PIcDXys/jEqiKPtHoYZhDip0n0cPOoasss/A1oS39QFVdk3WpLXGu3Izw==}
-
- '@zag-js/auto-resize@1.39.1':
- resolution: {integrity: sha512-ditIo9mW7fapq+4yx3/8hMpMZlWaoOy66EOzUz8dSVqnxnTWAjnTICu/9zFh8pkWerlzGTtDOJPP1oZ8S/rgVg==}
-
- '@zag-js/avatar@1.39.1':
- resolution: {integrity: sha512-LWrgJ0bebnXPSL+uehA9z6BlCD/MZEOQBJqH/F2QQFSAAZXUUDKtzVDmc+UtwjDsHXqqTghi+v2atQJHNMcJ2g==}
-
- '@zag-js/carousel@1.39.1':
- resolution: {integrity: sha512-5z5z3IldUgZ/R+KZLNQDoJFNTXzYd28YOmgfWH61Vvyv+RarX8kwZW8ajW/fNiqcWXyhW3/VMU0lArrfjbQVtQ==}
-
- '@zag-js/collapsible@1.39.1':
- resolution: {integrity: sha512-Zgccg/t7M8i0JVwZPPgW7XB7kGhTO475hsmwkF/8CYLqBBckVDHUARp2we24hENCm/98eez6R0eDEmE+tldFWA==}
-
- '@zag-js/collection@1.39.1':
- resolution: {integrity: sha512-fyOyKmP7MRo0/U8mBmB7KgHRXHhXP27LCcasy3x+qTAQtuEfYG1EPhKuj07oBWlX/2qfcKYn2R3YopHcqFcCiA==}
-
- '@zag-js/combobox@1.39.1':
- resolution: {integrity: sha512-fmStpG+k4xrxCzqUX0ssnOMeoSietWm5ir3qmEZcagzNqNycAXMvOELAIeyXi87Kut6aDGhxLOV7o395HVXl/w==}
-
- '@zag-js/core@1.39.1':
- resolution: {integrity: sha512-Yp0r49QLYXe2j7fgyAiilH4umXFydCnr5hcRDwJU+sxvUAlq00JQIJIEK2pT6k8cJiNNsFEV5WkOX7jsqpAX2A==}
-
- '@zag-js/date-picker@1.39.1':
- resolution: {integrity: sha512-t9q1H0aZQJkbzKTR2Bn5vMwaoFoirxekiSxw8ju0F0vr4Kg4BJ9yueOQm5I2wALKnJbZu4Ua5MgzlrDF3CQt3A==}
- peerDependencies:
- '@internationalized/date': '>=3.0.0'
-
- '@zag-js/date-utils@1.39.1':
- resolution: {integrity: sha512-i4SvBhru2Yz/zsHT0XvyFhf4a+pAKYkWXeVfU0RvF2S6mPTfgaMFF9ZNPq5Sy8K31EtAa6AVXcybYaYnibn1FA==}
- peerDependencies:
- '@internationalized/date': '>=3.0.0'
-
- '@zag-js/dialog@1.39.1':
- resolution: {integrity: sha512-q+HTmfuRDRZthln9mb7i52wdltQOZlw3+nw3a2uygEe9xuEtHBwUz31XJzkn2UWQqhAt7cC39OwykhNLKrfkqA==}
-
- '@zag-js/dismissable@1.39.1':
- resolution: {integrity: sha512-7/soy93Ersd5qedhSL/+CDcZ9gNTQV0ooDcqKtM8b4IxwD4rgWwGsewJY+tbKmOqaZobwa0YcWV2+YGgI23ESw==}
-
- '@zag-js/dom-query@1.39.1':
- resolution: {integrity: sha512-k01aXeUWLyJfB61CODaXj4PLhYmVpnVMFrC+3nk/XCn1MW7my8L/8KVg0m4W8n+X9MhpaLWsZDmK/dwED/3qSw==}
-
- '@zag-js/file-upload@1.39.1':
- resolution: {integrity: sha512-cErPOnPwPyneUXpelsfm75DKn0/4SI8aqQnlbrqo522PEqAQyDfDdBsqebGgKWG3F0A++kKFp9LO9A5zCrw5gA==}
-
- '@zag-js/file-utils@1.39.1':
- resolution: {integrity: sha512-ll/W5o74SMmoAS+l7PkmmGjPj4PLCSG/cwQh1Y/+LpaSev0YiR3Nk2OzRIIPtm3NivYVxKGawaCOf1RvT/82LQ==}
-
- '@zag-js/floating-panel@1.39.1':
- resolution: {integrity: sha512-IfPbf3pwJGqBWHec/rPzpdPjfMCLed59LlEophvRy49FEdksv8eN6nr9DXl2wWZEoQhH99scXfLMbtEZsPsFWg==}
-
- '@zag-js/focus-trap@1.39.1':
- resolution: {integrity: sha512-2ZzVefHMotvtxUo/gP4R45Szw/EPaPkTKEHaug6/il62SPDbkFODF+5r1zXyLbLuwCHq0apvQasg/ONLihwlXw==}
-
- '@zag-js/focus-visible@1.39.1':
- resolution: {integrity: sha512-iEuTOYHE8HRn/7ULC9c9BTTWo0C0MJRCbYVxbh/d7v8qAuq4CS76pdfceNo3KeWbb968T+yiG6q0AjiHsr8IOw==}
-
- '@zag-js/i18n-utils@1.39.1':
- resolution: {integrity: sha512-TKRLQQlHgJ4cxsHo3tZPtbFjGu9m1UPtfezRGFKq7A8czhdqRhaCpaWF849cd6dI7x6rWvvTan858gOFpyANnQ==}
-
- '@zag-js/interact-outside@1.39.1':
- resolution: {integrity: sha512-LnSbA+txMsFmzNPn84QKH01x2yJv4At/eKHn6rT2PyxXkJQIh8PvCTS3zVz4Syw11cmhcXt2eRwhzx8yImV92w==}
-
- '@zag-js/listbox@1.39.1':
- resolution: {integrity: sha512-Mz0UpdXobdTQTyjM+Avgi7pDVB2dKyaUHqw3TloeleQL3VwTqClclkwHXtLYYE+oXa0zOet37wI9mzfaYx9iZQ==}
-
- '@zag-js/live-region@1.39.1':
- resolution: {integrity: sha512-E7YNd0QGzJ2n1ZhnI2smv+klwifsNRf9QaDCx7quVJCVYywpupsBK4R25KN75S1z8XaK+jAy6HYKj8DIhYjYeg==}
-
- '@zag-js/menu@1.39.1':
- resolution: {integrity: sha512-bRDGLGkiGhzNtORBXkbBQV/xp2zEkwpYIepfWCaUoFwKUmx7GGnShTBFxJyq0u2D4IkS9GOwcqm20EhMv6V+TA==}
-
- '@zag-js/pagination@1.39.1':
- resolution: {integrity: sha512-3Q1B9/g3ajhvXjuGffJ7otyXcXK5+uhdbE5A9CZa4bsW3pf25L9Cp+ZAjdXQMDc8T4jhZJAKFmDJfQgtr1oEIw==}
-
- '@zag-js/popover@1.39.1':
- resolution: {integrity: sha512-aO3ExO/O7Sa3ovdozFI6SujhNOpYdCca4bImnAiovDL8DY8zN3UNQebu35IQvw9/aRsx9VKSJL1AqzJJUImFRw==}
-
- '@zag-js/popper@1.39.1':
- resolution: {integrity: sha512-h0UMY2dXJNfM3OvMQ9t9LzlmwvpCgjloz2IvU1txY3r32UIy7ve1H70zkKagLtLRxFTuWmhumYUPULPo/6a1DA==}
-
- '@zag-js/progress@1.39.1':
- resolution: {integrity: sha512-1IHyOw8DqPs3YH149Oj7W9a5oEfY5pc9GAVOPGbzYxVK/W8d/NIjVxa565I3J5cDJ0s6z3FrMSXMWUwr1ML4tw==}
-
- '@zag-js/radio-group@1.39.1':
- resolution: {integrity: sha512-+sC9xcAyY/GbY+8HpKlbPgSyOxBLUSB18s6fe6K1wdmyom4PM0nmhLouuxisbFZYHOyfQwAOMo+ainRENB2hzQ==}
-
- '@zag-js/rating-group@1.39.1':
- resolution: {integrity: sha512-IfdxWmM+3zpztx/HcE3bWob72sZNb1+BzK4tSySLVyjeqs8OzLDzrCbKqt10DmibnNOvpbjbq4eX4P5hV9YN7Q==}
-
- '@zag-js/rect-utils@1.39.1':
- resolution: {integrity: sha512-5gJ0PzeUme76xTWG+4XythWgmGgDKV4XAxEUaB3KKDtXgjDHwtu7PwKLIzFtlaaSf/U23PY+RNVBVCYg1GmZog==}
-
- '@zag-js/remove-scroll@1.39.1':
- resolution: {integrity: sha512-uZfPR3Gl9sQFo+tJ7kbuwsBhw+RIZwWFnMDgrz5LIwSNGN6hsyC4HGOxe29clkWQ2X2AjqqmEMETwgX7Jg+wxA==}
-
- '@zag-js/scroll-snap@1.39.1':
- resolution: {integrity: sha512-AzCc8MAAVqkiK5Y0cJZ24OIBZDQrUmEexACMuR6M5yZmlcEbS0EA/d6Wq+LSR1JMVTD4B+UwcMj1D3vJQ90ZTw==}
-
- '@zag-js/slider@1.39.1':
- resolution: {integrity: sha512-OEA9R7Ly5cw+6ANofnMpuHH3rAo8gZEnxy7iEwePu11pq2RCnt8DSj2V+uqU+dTq15Uup1LSzRgJfTnAC4Z85A==}
-
- '@zag-js/steps@1.39.1':
- resolution: {integrity: sha512-DC6swMpwITTB0DyCSxlpWyPNSUN9ul9jz4N6aAyQ0L1IK/noF/YYTZRAcXNSRzN4iutO/2mFGGbwGq/oVf+gPA==}
-
- '@zag-js/store@1.39.1':
- resolution: {integrity: sha512-zFpwP4lhiBVD9987rwAfZNVa2/f/xx4mhbCE1EEw31zxLAozY2jONeJ3UzPP05VbzKlRHBcvkaXAJQQGegTwFA==}
-
- '@zag-js/svelte@1.39.1':
- resolution: {integrity: sha512-ZOyZjyvjePZdrkNTy5fa92ijeeID9e+3LRGziKGIII3JSEvwfkG/Buf8W84N8VHFxi0G0GcKmgVCDgKHyGQYoQ==}
- peerDependencies:
- svelte: '>=5'
-
- '@zag-js/switch@1.39.1':
- resolution: {integrity: sha512-ikeQ42c0vyyPLeyW9U0dvcqTV1Ekpx5jZ050R905HGJ2GeWE0uBGuHbMpTG5U6Pwb0a+TMzqAr+jMsquVTCwzg==}
-
- '@zag-js/tabs@1.39.1':
- resolution: {integrity: sha512-P2RThO1gX9SFsNqrAGPsXJxrjn5YqP6MFs9mdExU+tzzZyVjJQADkAmh98C0eEaCb6HKLpJZ/17hrnLDhm1Tig==}
-
- '@zag-js/tags-input@1.39.1':
- resolution: {integrity: sha512-tc0+bd9FiUJwa+wY2hSVVGHLIBC3C3rOZX/4zjchRMs1xgl92c1/tYbytXny7ABB8ZMHveG7MtgDppVF4VkwBg==}
-
- '@zag-js/toast@1.39.1':
- resolution: {integrity: sha512-K7ndEfBTKDds10iQKCQUmin74s6V4BEIypAIyQxs18gQB9TCn5+wff886JAzecIKPY97PDQHDKjYR71yzRC7/g==}
-
- '@zag-js/toggle-group@1.39.1':
- resolution: {integrity: sha512-KS4Bo17foMKXVBhQjocRf4GQxMV4pMXclTo14IWjldaHs2HIrNJ0Ar0Ri+vo47BBKBNsXs4HuNvfbMdQj94wEA==}
-
- '@zag-js/tooltip@1.39.1':
- resolution: {integrity: sha512-IsxFj7l8kPciwIyYJWlmQ7mhXocbjXxLj3m9z099slYOF7lApA33/ndY32w9ptrI4/nUh2nldzw6eRfSpVnuOA==}
-
- '@zag-js/tree-view@1.39.1':
- resolution: {integrity: sha512-sm6qUZjO0OaqBqO5s55KU+l5p1wXfUVScoen7BYVoFBuROH7qAZJi8YMclGvnnlyV506i8Hk0qqWnLg0F38jCA==}
-
- '@zag-js/types@1.39.1':
- resolution: {integrity: sha512-w3vVpgxmdJvMDvv19DXTtFI6kJL6TXw//U0Z1BAc3rnDA9orcB9Ryw4uMNvIzFA607CgssyJcWDaQ/M3yAcbJw==}
-
- '@zag-js/utils@1.39.1':
- resolution: {integrity: sha512-9k741cH7L655Ua3tedTkuMblcXVXVgCLTB9svp9oTjA7oatpOpYF4z43kgAQVjyThNXMJ7AvtO4C80ajQLTScg==}
-
acorn@8.16.0:
resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
engines: {node: '>=0.4.0'}
@@ -539,14 +684,31 @@ packages:
resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
engines: {node: '>= 0.4'}
+ bits-ui@2.18.1:
+ resolution: {integrity: sha512-KkemzKFH4T3gt3H+P86JcnAWExjByv/6vlwjm/BoCwTPHu03yiCdxbghdJLvFReQTe0acCAiRcKfmixxD6XvlA==}
+ engines: {node: '>=20'}
+ peerDependencies:
+ '@internationalized/date': ^3.8.1
+ svelte: ^5.33.0
+
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
+ class-variance-authority@0.7.1:
+ resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
+
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
+ commander@14.0.3:
+ resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
+ engines: {node: '>=20'}
+
+ commondir@1.0.1:
+ resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
+
cookie@0.6.0:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
engines: {node: '>= 0.6'}
@@ -556,13 +718,14 @@ packages:
engines: {node: '>=4'}
hasBin: true
- csstype@3.2.3:
- resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
-
deepmerge@4.3.1:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'}
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@@ -574,6 +737,10 @@ packages:
resolution: {integrity: sha512-yJN/BOOLxcOW2aQgeif9mSnaUB8KtvmMMp56oA1kx1CRfBKbhZm2pJ+NBY+3eOboHxix8lfjWpHE0Ei5U8RbSA==}
engines: {node: '>=10.13.0'}
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
esm-env@1.2.2:
resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==}
@@ -585,6 +752,9 @@ packages:
'@typescript-eslint/types':
optional: true
+ estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -594,14 +764,37 @@ packages:
picomatch:
optional: true
+ fflate@0.8.3:
+ resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==}
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ hasown@2.0.4:
+ resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
+ engines: {node: '>= 0.4'}
+
+ inline-style-parser@0.2.7:
+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+
+ is-core-module@2.16.2:
+ resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==}
+ engines: {node: '>= 0.4'}
+
+ is-module@1.0.0:
+ resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
+
+ is-reference@1.2.1:
+ resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
+
is-reference@3.0.3:
resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
@@ -690,6 +883,10 @@ packages:
locate-character@3.0.0:
resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
+ lz-string@1.5.0:
+ resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
+ hasBin: true
+
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
@@ -710,10 +907,26 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ node-fetch-native@1.6.7:
+ resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
+
obug@2.1.2:
resolution: {integrity: sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==}
engines: {node: '>=12.20.0'}
+ pako@1.0.11:
+ resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
+
+ path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ pdf-lib@1.17.1:
+ resolution: {integrity: sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==}
+
+ pdfjs-dist@6.0.227:
+ resolution: {integrity: sha512-/P6M4SXw+70waMVLUM7rdRtvo+dEzqE1t6W/zQNvBETo2MaRa5rrvCcAYdfWGiUzadTgM0lJmRApUrW0d9zgKg==}
+ engines: {node: '>=22.13.0 || >=24'}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -796,18 +1009,34 @@ packages:
engines: {node: '>=14'}
hasBin: true
- proxy-compare@3.0.1:
- resolution: {integrity: sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==}
-
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
+ resolve@1.22.12:
+ resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
rolldown@1.0.3:
resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
+ rollup@4.62.2:
+ resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ runed@0.35.1:
+ resolution: {integrity: sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==}
+ peerDependencies:
+ '@sveltejs/kit': ^2.21.0
+ svelte: ^5.7.0
+ peerDependenciesMeta:
+ '@sveltejs/kit':
+ optional: true
+
sade@1.8.1:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'}
@@ -815,6 +1044,12 @@ packages:
set-cookie-parser@3.1.0:
resolution: {integrity: sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==}
+ shadcn-svelte@1.3.0:
+ resolution: {integrity: sha512-Pd4ICWTkTks/b2YU4c9vF2XsX1x5HFPRl5bKszS1LcnWS83x+7T4WiIvbWz8Qh9knkcGZ+SCz1+Dmhdq+AYooA==}
+ hasBin: true
+ peerDependencies:
+ svelte: ^5.0.0
+
sirv@3.0.2:
resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
engines: {node: '>=18'}
@@ -823,6 +1058,13 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
+ style-to-object@1.0.14:
+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
+
+ supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
svelte-check@4.6.0:
resolution: {integrity: sha512-KhVnDFDSid57mmZtHz8gfW8AAGylOZ0vPnOIzVmAL+urzwK8sBYXRss953gD8T0OdgAQ11mdWhE6uadmtOz8TQ==}
engines: {node: '>= 18.0.0'}
@@ -831,10 +1073,32 @@ packages:
svelte: ^4.0.0 || ^5.0.0-next.0
typescript: '>=5.0.0'
+ svelte-toolbelt@0.10.6:
+ resolution: {integrity: sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==}
+ engines: {node: '>=18', pnpm: '>=8.7.0'}
+ peerDependencies:
+ svelte: ^5.30.2
+
svelte@5.56.3:
resolution: {integrity: sha512-w7JvrM5IFl5cmfbY0TLik9o7mjRUJmRMhOR51tBPu708Gr/MjbGs7VnJnr/B0CaXeI4vtnOh7RKxDr0cwhMdDA==}
engines: {node: '>=18'}
+ tabbable@6.4.0:
+ resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==}
+
+ tailwind-merge@3.6.0:
+ resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==}
+
+ tailwind-variants@3.2.2:
+ resolution: {integrity: sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==}
+ engines: {node: '>=16.x', pnpm: '>=7.x'}
+ peerDependencies:
+ tailwind-merge: '>=3.0.0'
+ tailwindcss: '*'
+ peerDependenciesMeta:
+ tailwind-merge:
+ optional: true
+
tailwindcss@4.3.0:
resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==}
@@ -850,9 +1114,15 @@ packages:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
+ tslib@1.14.1:
+ resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+ tw-animate-css@1.4.0:
+ resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==}
+
typescript@6.0.3:
resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==}
engines: {node: '>=14.17'}
@@ -944,7 +1214,9 @@ snapshots:
'@floating-ui/utils@0.2.11': {}
- '@internationalized/date@3.12.0':
+ '@fontsource-variable/geist@5.2.9': {}
+
+ '@internationalized/date@3.12.2':
dependencies:
'@swc/helpers': 0.5.23
@@ -967,6 +1239,58 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
+ '@lucide/svelte@1.18.0(svelte@5.56.3)':
+ dependencies:
+ svelte: 5.56.3
+
+ '@napi-rs/canvas-android-arm64@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-darwin-arm64@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-darwin-x64@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm-gnueabihf@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm64-gnu@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm64-musl@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-linux-riscv64-gnu@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-linux-x64-gnu@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-linux-x64-musl@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-win32-arm64-msvc@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas-win32-x64-msvc@1.0.0':
+ optional: true
+
+ '@napi-rs/canvas@1.0.0':
+ optionalDependencies:
+ '@napi-rs/canvas-android-arm64': 1.0.0
+ '@napi-rs/canvas-darwin-arm64': 1.0.0
+ '@napi-rs/canvas-darwin-x64': 1.0.0
+ '@napi-rs/canvas-linux-arm-gnueabihf': 1.0.0
+ '@napi-rs/canvas-linux-arm64-gnu': 1.0.0
+ '@napi-rs/canvas-linux-arm64-musl': 1.0.0
+ '@napi-rs/canvas-linux-riscv64-gnu': 1.0.0
+ '@napi-rs/canvas-linux-x64-gnu': 1.0.0
+ '@napi-rs/canvas-linux-x64-musl': 1.0.0
+ '@napi-rs/canvas-win32-arm64-msvc': 1.0.0
+ '@napi-rs/canvas-win32-x64-msvc': 1.0.0
+ optional: true
+
'@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
dependencies:
'@emnapi/core': 1.10.0
@@ -976,6 +1300,14 @@ snapshots:
'@oxc-project/types@0.133.0': {}
+ '@pdf-lib/standard-fonts@1.0.0':
+ dependencies:
+ pako: 1.0.11
+
+ '@pdf-lib/upng@1.0.1':
+ dependencies:
+ pako: 1.0.11
+
'@polka/url@1.0.0-next.29': {}
'@rolldown/binding-android-arm64@1.0.3':
@@ -1029,44 +1361,123 @@ snapshots:
'@rolldown/pluginutils@1.0.1': {}
- '@skeletonlabs/skeleton-common@4.15.2': {}
-
- '@skeletonlabs/skeleton-svelte@4.15.2(svelte@5.56.3)':
+ '@rollup/plugin-commonjs@29.0.3(rollup@4.62.2)':
dependencies:
- '@internationalized/date': 3.12.0
- '@skeletonlabs/skeleton-common': 4.15.2
- '@zag-js/accordion': 1.39.1
- '@zag-js/avatar': 1.39.1
- '@zag-js/carousel': 1.39.1
- '@zag-js/collapsible': 1.39.1
- '@zag-js/collection': 1.39.1
- '@zag-js/combobox': 1.39.1
- '@zag-js/date-picker': 1.39.1(@internationalized/date@3.12.0)
- '@zag-js/dialog': 1.39.1
- '@zag-js/file-upload': 1.39.1
- '@zag-js/floating-panel': 1.39.1
- '@zag-js/listbox': 1.39.1
- '@zag-js/menu': 1.39.1
- '@zag-js/pagination': 1.39.1
- '@zag-js/popover': 1.39.1
- '@zag-js/progress': 1.39.1
- '@zag-js/radio-group': 1.39.1
- '@zag-js/rating-group': 1.39.1
- '@zag-js/slider': 1.39.1
- '@zag-js/steps': 1.39.1
- '@zag-js/svelte': 1.39.1(svelte@5.56.3)
- '@zag-js/switch': 1.39.1
- '@zag-js/tabs': 1.39.1
- '@zag-js/tags-input': 1.39.1
- '@zag-js/toast': 1.39.1
- '@zag-js/toggle-group': 1.39.1
- '@zag-js/tooltip': 1.39.1
- '@zag-js/tree-view': 1.39.1
- svelte: 5.56.3
+ '@rollup/pluginutils': 5.4.0(rollup@4.62.2)
+ commondir: 1.0.1
+ estree-walker: 2.0.2
+ fdir: 6.5.0(picomatch@4.0.4)
+ is-reference: 1.2.1
+ magic-string: 0.30.21
+ picomatch: 4.0.4
+ optionalDependencies:
+ rollup: 4.62.2
- '@skeletonlabs/skeleton@4.15.2(tailwindcss@4.3.0)':
+ '@rollup/plugin-json@6.1.0(rollup@4.62.2)':
dependencies:
- tailwindcss: 4.3.0
+ '@rollup/pluginutils': 5.4.0(rollup@4.62.2)
+ optionalDependencies:
+ rollup: 4.62.2
+
+ '@rollup/plugin-node-resolve@16.0.3(rollup@4.62.2)':
+ dependencies:
+ '@rollup/pluginutils': 5.4.0(rollup@4.62.2)
+ '@types/resolve': 1.20.2
+ deepmerge: 4.3.1
+ is-module: 1.0.0
+ resolve: 1.22.12
+ optionalDependencies:
+ rollup: 4.62.2
+
+ '@rollup/plugin-replace@6.0.3(rollup@4.62.2)':
+ dependencies:
+ '@rollup/pluginutils': 5.4.0(rollup@4.62.2)
+ magic-string: 0.30.21
+ optionalDependencies:
+ rollup: 4.62.2
+
+ '@rollup/pluginutils@5.4.0(rollup@4.62.2)':
+ dependencies:
+ '@types/estree': 1.0.9
+ estree-walker: 2.0.2
+ picomatch: 4.0.4
+ optionalDependencies:
+ rollup: 4.62.2
+
+ '@rollup/rollup-android-arm-eabi@4.62.2':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-openbsd-x64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.62.2':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.62.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.62.2':
+ optional: true
'@standard-schema/spec@1.1.0': {}
@@ -1074,9 +1485,14 @@ snapshots:
dependencies:
acorn: 8.16.0
- '@sveltejs/adapter-auto@7.0.1(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))':
+ '@sveltejs/adapter-node@5.5.7(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))':
dependencies:
+ '@rollup/plugin-commonjs': 29.0.3(rollup@4.62.2)
+ '@rollup/plugin-json': 6.1.0(rollup@4.62.2)
+ '@rollup/plugin-node-resolve': 16.0.3(rollup@4.62.2)
+ '@rollup/plugin-replace': 6.0.3(rollup@4.62.2)
'@sveltejs/kit': 2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0))
+ rollup: 4.62.2
'@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0))':
dependencies:
@@ -1200,357 +1616,51 @@ snapshots:
'@types/estree@1.0.9': {}
+ '@types/resolve@1.20.2': {}
+
'@types/trusted-types@2.0.7': {}
- '@zag-js/accordion@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/anatomy@1.39.1': {}
-
- '@zag-js/aria-hidden@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
-
- '@zag-js/auto-resize@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
-
- '@zag-js/avatar@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/carousel@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/scroll-snap': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/collapsible@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/collection@1.39.1':
- dependencies:
- '@zag-js/utils': 1.39.1
-
- '@zag-js/combobox@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/collection': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dismissable': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/focus-visible': 1.39.1
- '@zag-js/live-region': 1.39.1
- '@zag-js/popper': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/core@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/date-picker@1.39.1(@internationalized/date@3.12.0)':
- dependencies:
- '@internationalized/date': 3.12.0
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/date-utils': 1.39.1(@internationalized/date@3.12.0)
- '@zag-js/dismissable': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/live-region': 1.39.1
- '@zag-js/popper': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/date-utils@1.39.1(@internationalized/date@3.12.0)':
- dependencies:
- '@internationalized/date': 3.12.0
-
- '@zag-js/dialog@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/aria-hidden': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dismissable': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/focus-trap': 1.39.1
- '@zag-js/remove-scroll': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/dismissable@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
- '@zag-js/interact-outside': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/dom-query@1.39.1':
- dependencies:
- '@zag-js/types': 1.39.1
-
- '@zag-js/file-upload@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/file-utils': 1.39.1
- '@zag-js/i18n-utils': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/file-utils@1.39.1':
- dependencies:
- '@zag-js/i18n-utils': 1.39.1
-
- '@zag-js/floating-panel@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/popper': 1.39.1
- '@zag-js/rect-utils': 1.39.1
- '@zag-js/store': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/focus-trap@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
-
- '@zag-js/focus-visible@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
-
- '@zag-js/i18n-utils@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
-
- '@zag-js/interact-outside@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/listbox@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/collection': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/focus-visible': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/live-region@1.39.1': {}
-
- '@zag-js/menu@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dismissable': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/focus-visible': 1.39.1
- '@zag-js/popper': 1.39.1
- '@zag-js/rect-utils': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/pagination@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/popover@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/aria-hidden': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dismissable': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/focus-trap': 1.39.1
- '@zag-js/popper': 1.39.1
- '@zag-js/remove-scroll': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/popper@1.39.1':
- dependencies:
- '@floating-ui/dom': 1.7.6
- '@zag-js/dom-query': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/progress@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/radio-group@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/focus-visible': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/rating-group@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/rect-utils@1.39.1': {}
-
- '@zag-js/remove-scroll@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
-
- '@zag-js/scroll-snap@1.39.1':
- dependencies:
- '@zag-js/dom-query': 1.39.1
-
- '@zag-js/slider@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/steps@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/store@1.39.1':
- dependencies:
- proxy-compare: 3.0.1
-
- '@zag-js/svelte@1.39.1(svelte@5.56.3)':
- dependencies:
- '@zag-js/core': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
- svelte: 5.56.3
-
- '@zag-js/switch@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/focus-visible': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/tabs@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/tags-input@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/auto-resize': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/interact-outside': 1.39.1
- '@zag-js/live-region': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/toast@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dismissable': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/toggle-group@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/tooltip@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/focus-visible': 1.39.1
- '@zag-js/popper': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/tree-view@1.39.1':
- dependencies:
- '@zag-js/anatomy': 1.39.1
- '@zag-js/collection': 1.39.1
- '@zag-js/core': 1.39.1
- '@zag-js/dom-query': 1.39.1
- '@zag-js/types': 1.39.1
- '@zag-js/utils': 1.39.1
-
- '@zag-js/types@1.39.1':
- dependencies:
- csstype: 3.2.3
-
- '@zag-js/utils@1.39.1': {}
-
acorn@8.16.0: {}
aria-query@5.3.1: {}
axobject-query@4.1.0: {}
+ bits-ui@2.18.1(@internationalized/date@3.12.2)(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3):
+ dependencies:
+ '@floating-ui/core': 1.7.5
+ '@floating-ui/dom': 1.7.6
+ '@internationalized/date': 3.12.2
+ esm-env: 1.2.2
+ runed: 0.35.1(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)
+ svelte: 5.56.3
+ svelte-toolbelt: 0.10.6(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)
+ tabbable: 6.4.0
+ transitivePeerDependencies:
+ - '@sveltejs/kit'
+
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
+ class-variance-authority@0.7.1:
+ dependencies:
+ clsx: 2.1.1
+
clsx@2.1.1: {}
+ commander@14.0.3: {}
+
+ commondir@1.0.1: {}
+
cookie@0.6.0: {}
cssesc@3.0.0: {}
- csstype@3.2.3: {}
-
deepmerge@4.3.1: {}
+ dequal@2.0.3: {}
+
detect-libc@2.1.2: {}
devalue@5.8.1: {}
@@ -1560,21 +1670,45 @@ snapshots:
graceful-fs: 4.2.11
tapable: 2.3.3
+ es-errors@1.3.0: {}
+
esm-env@1.2.2: {}
esrap@2.2.11:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ estree-walker@2.0.2: {}
+
fdir@6.5.0(picomatch@4.0.4):
optionalDependencies:
picomatch: 4.0.4
+ fflate@0.8.3: {}
+
fsevents@2.3.3:
optional: true
+ function-bind@1.1.2: {}
+
graceful-fs@4.2.11: {}
+ hasown@2.0.4:
+ dependencies:
+ function-bind: 1.1.2
+
+ inline-style-parser@0.2.7: {}
+
+ is-core-module@2.16.2:
+ dependencies:
+ hasown: 2.0.4
+
+ is-module@1.0.0: {}
+
+ is-reference@1.2.1:
+ dependencies:
+ '@types/estree': 1.0.9
+
is-reference@3.0.3:
dependencies:
'@types/estree': 1.0.9
@@ -1634,6 +1768,8 @@ snapshots:
locate-character@3.0.0: {}
+ lz-string@1.5.0: {}
+
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -1646,8 +1782,25 @@ snapshots:
nanoid@3.3.12: {}
+ node-fetch-native@1.6.7: {}
+
obug@2.1.2: {}
+ pako@1.0.11: {}
+
+ path-parse@1.0.7: {}
+
+ pdf-lib@1.17.1:
+ dependencies:
+ '@pdf-lib/standard-fonts': 1.0.0
+ '@pdf-lib/upng': 1.0.1
+ pako: 1.0.11
+ tslib: 1.14.1
+
+ pdfjs-dist@6.0.227:
+ optionalDependencies:
+ '@napi-rs/canvas': 1.0.0
+
picocolors@1.1.1: {}
picomatch@4.0.4: {}
@@ -1676,10 +1829,15 @@ snapshots:
prettier@3.8.4: {}
- proxy-compare@3.0.1: {}
-
readdirp@4.1.2: {}
+ resolve@1.22.12:
+ dependencies:
+ es-errors: 1.3.0
+ is-core-module: 2.16.2
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
rolldown@1.0.3:
dependencies:
'@oxc-project/types': 0.133.0
@@ -1701,12 +1859,60 @@ snapshots:
'@rolldown/binding-win32-arm64-msvc': 1.0.3
'@rolldown/binding-win32-x64-msvc': 1.0.3
+ rollup@4.62.2:
+ dependencies:
+ '@types/estree': 1.0.9
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.62.2
+ '@rollup/rollup-android-arm64': 4.62.2
+ '@rollup/rollup-darwin-arm64': 4.62.2
+ '@rollup/rollup-darwin-x64': 4.62.2
+ '@rollup/rollup-freebsd-arm64': 4.62.2
+ '@rollup/rollup-freebsd-x64': 4.62.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.62.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.62.2
+ '@rollup/rollup-linux-arm64-gnu': 4.62.2
+ '@rollup/rollup-linux-arm64-musl': 4.62.2
+ '@rollup/rollup-linux-loong64-gnu': 4.62.2
+ '@rollup/rollup-linux-loong64-musl': 4.62.2
+ '@rollup/rollup-linux-ppc64-gnu': 4.62.2
+ '@rollup/rollup-linux-ppc64-musl': 4.62.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.62.2
+ '@rollup/rollup-linux-riscv64-musl': 4.62.2
+ '@rollup/rollup-linux-s390x-gnu': 4.62.2
+ '@rollup/rollup-linux-x64-gnu': 4.62.2
+ '@rollup/rollup-linux-x64-musl': 4.62.2
+ '@rollup/rollup-openbsd-x64': 4.62.2
+ '@rollup/rollup-openharmony-arm64': 4.62.2
+ '@rollup/rollup-win32-arm64-msvc': 4.62.2
+ '@rollup/rollup-win32-ia32-msvc': 4.62.2
+ '@rollup/rollup-win32-x64-gnu': 4.62.2
+ '@rollup/rollup-win32-x64-msvc': 4.62.2
+ fsevents: 2.3.3
+
+ runed@0.35.1(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3):
+ dependencies:
+ dequal: 2.0.3
+ esm-env: 1.2.2
+ lz-string: 1.5.0
+ svelte: 5.56.3
+ optionalDependencies:
+ '@sveltejs/kit': 2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0))
+
sade@1.8.1:
dependencies:
mri: 1.2.0
set-cookie-parser@3.1.0: {}
+ shadcn-svelte@1.3.0(svelte@5.56.3):
+ dependencies:
+ commander: 14.0.3
+ node-fetch-native: 1.6.7
+ postcss: 8.5.15
+ svelte: 5.56.3
+ tailwind-merge: 3.6.0
+
sirv@3.0.2:
dependencies:
'@polka/url': 1.0.0-next.29
@@ -1715,6 +1921,12 @@ snapshots:
source-map-js@1.2.1: {}
+ style-to-object@1.0.14:
+ dependencies:
+ inline-style-parser: 0.2.7
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
svelte-check@4.6.0(picomatch@4.0.4)(svelte@5.56.3)(typescript@6.0.3):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -1728,6 +1940,15 @@ snapshots:
transitivePeerDependencies:
- picomatch
+ svelte-toolbelt@0.10.6(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3):
+ dependencies:
+ clsx: 2.1.1
+ runed: 0.35.1(@sveltejs/kit@2.64.0(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)(typescript@6.0.3)(vite@8.0.16(jiti@2.7.0)))(svelte@5.56.3)
+ style-to-object: 1.0.14
+ svelte: 5.56.3
+ transitivePeerDependencies:
+ - '@sveltejs/kit'
+
svelte@5.56.3:
dependencies:
'@jridgewell/remapping': 2.3.5
@@ -1749,6 +1970,16 @@ snapshots:
transitivePeerDependencies:
- '@typescript-eslint/types'
+ tabbable@6.4.0: {}
+
+ tailwind-merge@3.6.0: {}
+
+ tailwind-variants@3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0):
+ dependencies:
+ tailwindcss: 4.3.0
+ optionalDependencies:
+ tailwind-merge: 3.6.0
+
tailwindcss@4.3.0: {}
tapable@2.3.3: {}
@@ -1760,8 +1991,12 @@ snapshots:
totalist@3.0.1: {}
+ tslib@1.14.1: {}
+
tslib@2.8.1: {}
+ tw-animate-css@1.4.0: {}
+
typescript@6.0.3: {}
util-deprecate@1.0.2: {}
diff --git a/src/lib/actions/ripple.ts b/src/lib/actions/ripple.ts
new file mode 100644
index 0000000..c934a96
--- /dev/null
+++ b/src/lib/actions/ripple.ts
@@ -0,0 +1,31 @@
+export function ripple(node: HTMLElement) {
+ function handleClick(event: MouseEvent) {
+ const circle = document.createElement("span");
+
+ const rect = node.getBoundingClientRect();
+ const size = Math.max(rect.width, rect.height);
+
+ circle.style.width = `${size}px`;
+ circle.style.height = `${size}px`;
+
+ circle.style.left = `${event.clientX - rect.left - size / 2}px`;
+ circle.style.top = `${event.clientY - rect.top - size / 2}px`;
+
+ circle.className =
+ "absolute rounded-full bg-white/30 animate-ripple pointer-events-none";
+
+ node.appendChild(circle);
+
+ circle.addEventListener("animationend", () => {
+ circle.remove();
+ });
+ }
+
+ node.addEventListener("click", handleClick);
+
+ return {
+ destroy() {
+ node.removeEventListener("click", handleClick);
+ }
+ };
+}
\ No newline at end of file
diff --git a/src/lib/components/AttachmentPreview.svelte b/src/lib/components/AttachmentPreview.svelte
new file mode 100644
index 0000000..eadfa78
--- /dev/null
+++ b/src/lib/components/AttachmentPreview.svelte
@@ -0,0 +1,129 @@
+
+
+
+ {#if previewError}
+
+ {previewError}
+
+ {:else if imageUrl}
+

+ {:else}
+
+ Vorschau wird erstellt
+
+ {/if}
+
diff --git a/src/lib/components/Button.svelte b/src/lib/components/Button.svelte
deleted file mode 100644
index 9f09578..0000000
--- a/src/lib/components/Button.svelte
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
diff --git a/src/lib/components/Card.svelte b/src/lib/components/Card.svelte
deleted file mode 100644
index 7b26b8e..0000000
--- a/src/lib/components/Card.svelte
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- {#if title}
-
- {/if}
- {#if content}
- {@render content()}
- {/if}
- {#if footer}
-
- {/if}
-
\ No newline at end of file
diff --git a/src/lib/components/ProcessedZipArchiveEditor.svelte b/src/lib/components/ProcessedZipArchiveEditor.svelte
new file mode 100644
index 0000000..086f9d6
--- /dev/null
+++ b/src/lib/components/ProcessedZipArchiveEditor.svelte
@@ -0,0 +1,502 @@
+
+
+
+
+
+
+
+
+
+ {looseAttachments.length} lose Datei{looseAttachments.length === 1 ? '' : 'en'}
+ {#if hasSubDocuments}
+ · {subDocuments.length} Teildokument{subDocuments.length === 1 ? '' : 'e'}
+ {/if}
+
+
+
+
+
+
+ {#if hasSubDocuments}
+
+ {#each [{ value: 'single', label: 'Eine PDF' }, { value: 'separate', label: 'Getrennt' }] as option (option.value)}
+
+ {/each}
+
+ {/if}
+
+
+
+
+
+ {#if mergeError}
+
+ {mergeError}
+
+ {/if}
+
+ {#if selectionMode && selectedPaths.size > 0}
+
+ {selectedPaths.size} Datei{selectedPaths.size === 1 ? '' : 'en'} ausgewählt
+
+
+ {/if}
+
+
+ {#each looseAttachments as attachment, index (attachment.path)}
+ - handleLooseDragStart(index, event)}
+ ondragover={(event) => handleLooseDragOver(index, event)}
+ ondrop={(event) => handleLooseDrop(index, event)}
+ ondragend={handleLooseDragEnd}
+ >
+ {#if selectionMode}
+
+ {:else}
+
+
+
+
+ {attachment.name}
+
+
+
+ {/if}
+
+ {/each}
+
+
+ {#if looseAttachments.length === 0 && subDocuments.length === 0}
+
+ Keine Dateien in diesem Archiv. Lade ein anderes ZIP, um weiterzuarbeiten.
+
+ {/if}
+
+ {#if hasSubDocuments}
+
+ {#each subDocuments as subDocument, blockIndex (subDocument.id)}
+ dissolveSubDocumentBlock(subDocument.id)}
+ onAttachmentMove={handleAttachmentMove}
+ onBlockDragStart={handleBlockDragStart}
+ onBlockDragOver={handleBlockDragOver}
+ onBlockDrop={handleBlockDrop}
+ onBlockDragEnd={handleBlockDragEnd}
+ />
+ {/each}
+
+ {/if}
+
diff --git a/src/lib/components/SubDocumentEditor.svelte b/src/lib/components/SubDocumentEditor.svelte
new file mode 100644
index 0000000..81164fe
--- /dev/null
+++ b/src/lib/components/SubDocumentEditor.svelte
@@ -0,0 +1,286 @@
+
+
+
+
+
+ {#if attachments.length === 0}
+ {
+ if (event.dataTransfer?.types.includes(ATTACHMENT_MIME)) {
+ event.preventDefault();
+ }
+ }}
+ ondrop={(event) => {
+ const source = parseAttachmentPayload(event);
+
+ if (!source) {
+ return;
+ }
+
+ event.preventDefault();
+
+ const target: AttachmentLocation = {
+ kind: 'subDocument',
+ id: subDocument.id,
+ index: 0
+ };
+
+ onAttachmentMove(source, target);
+ dragIndex = null;
+ dropIndex = null;
+ }}
+ >
+ -
+ Dieses Teildokument ist leer. Ziehe Dateien hierher, um sie hinzuzufügen.
+
+
+ {:else}
+
+ {#each attachments as attachment, index (attachment.path)}
+ - handleCardDragStart(index, event)}
+ ondragover={(event) => handleCardDragOver(index, event)}
+ ondrop={(event) => handleCardDrop(index, event)}
+ ondragend={handleCardDragEnd}
+ >
+
+
+
+
+ {attachment.name}
+
+
+
+
+ {/each}
+
+ {/if}
+
diff --git a/src/lib/components/ZipDropzone.svelte b/src/lib/components/ZipDropzone.svelte
index 213f926..ae4e919 100644
--- a/src/lib/components/ZipDropzone.svelte
+++ b/src/lib/components/ZipDropzone.svelte
@@ -62,7 +62,7 @@
diff --git a/src/lib/components/icons/IconChain.svelte b/src/lib/components/icons/IconChain.svelte
new file mode 100644
index 0000000..a60f9fb
--- /dev/null
+++ b/src/lib/components/icons/IconChain.svelte
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/src/lib/components/icons/IconFile.svelte b/src/lib/components/icons/IconFile.svelte
new file mode 100644
index 0000000..413e422
--- /dev/null
+++ b/src/lib/components/icons/IconFile.svelte
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/src/lib/components/icons/IconMenu.svelte b/src/lib/components/icons/IconMenu.svelte
new file mode 100644
index 0000000..68ca63d
--- /dev/null
+++ b/src/lib/components/icons/IconMenu.svelte
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/src/lib/components/icons/IconNeedle.svelte b/src/lib/components/icons/IconNeedle.svelte
new file mode 100644
index 0000000..20ce66b
--- /dev/null
+++ b/src/lib/components/icons/IconNeedle.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/src/lib/components/icons/IconOffice.svelte b/src/lib/components/icons/IconOffice.svelte
new file mode 100644
index 0000000..035e0ec
--- /dev/null
+++ b/src/lib/components/icons/IconOffice.svelte
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/src/lib/components/icons/IconPerson.svelte b/src/lib/components/icons/IconPerson.svelte
new file mode 100644
index 0000000..a11a6c0
--- /dev/null
+++ b/src/lib/components/icons/IconPerson.svelte
@@ -0,0 +1,4 @@
+
diff --git a/src/lib/components/icons/IconSettings.svelte b/src/lib/components/icons/IconSettings.svelte
new file mode 100644
index 0000000..21b9306
--- /dev/null
+++ b/src/lib/components/icons/IconSettings.svelte
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/src/lib/components/icons/IconTag.svelte b/src/lib/components/icons/IconTag.svelte
new file mode 100644
index 0000000..b732550
--- /dev/null
+++ b/src/lib/components/icons/IconTag.svelte
@@ -0,0 +1,4 @@
+
diff --git a/src/lib/components/icons/IconTrash.svelte b/src/lib/components/icons/IconTrash.svelte
new file mode 100644
index 0000000..60a4e0a
--- /dev/null
+++ b/src/lib/components/icons/IconTrash.svelte
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/src/lib/components/icons/IconUnknown.svelte b/src/lib/components/icons/IconUnknown.svelte
new file mode 100644
index 0000000..1491e90
--- /dev/null
+++ b/src/lib/components/icons/IconUnknown.svelte
@@ -0,0 +1,7 @@
+
+
+
diff --git a/src/lib/components/ui/button.svelte b/src/lib/components/ui/button.svelte
new file mode 100644
index 0000000..71b850a
--- /dev/null
+++ b/src/lib/components/ui/button.svelte
@@ -0,0 +1,89 @@
+
+
+
+
+{#if href}
+
+ {@render children?.()}
+ {#if icon}
+ {@const Icon = icon}
+
+ {/if}
+
+{:else}
+
+{/if}
diff --git a/src/lib/components/ui/card/card-action.svelte b/src/lib/components/ui/card/card-action.svelte
new file mode 100644
index 0000000..7c48844
--- /dev/null
+++ b/src/lib/components/ui/card/card-action.svelte
@@ -0,0 +1,23 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/card/card-content.svelte b/src/lib/components/ui/card/card-content.svelte
new file mode 100644
index 0000000..4f60ee3
--- /dev/null
+++ b/src/lib/components/ui/card/card-content.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/card/card-description.svelte b/src/lib/components/ui/card/card-description.svelte
new file mode 100644
index 0000000..9b20ac7
--- /dev/null
+++ b/src/lib/components/ui/card/card-description.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/card/card-footer.svelte b/src/lib/components/ui/card/card-footer.svelte
new file mode 100644
index 0000000..1efff6d
--- /dev/null
+++ b/src/lib/components/ui/card/card-footer.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/card/card-header.svelte b/src/lib/components/ui/card/card-header.svelte
new file mode 100644
index 0000000..7eb69e1
--- /dev/null
+++ b/src/lib/components/ui/card/card-header.svelte
@@ -0,0 +1,23 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/card/card-title.svelte b/src/lib/components/ui/card/card-title.svelte
new file mode 100644
index 0000000..1523fc5
--- /dev/null
+++ b/src/lib/components/ui/card/card-title.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/card/card.svelte b/src/lib/components/ui/card/card.svelte
new file mode 100644
index 0000000..2b4f81a
--- /dev/null
+++ b/src/lib/components/ui/card/card.svelte
@@ -0,0 +1,22 @@
+
+
+img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)}
+ {...restProps}
+>
+ {@render children?.()}
+
diff --git a/src/lib/components/ui/card/index.ts b/src/lib/components/ui/card/index.ts
new file mode 100644
index 0000000..4d3fce4
--- /dev/null
+++ b/src/lib/components/ui/card/index.ts
@@ -0,0 +1,25 @@
+import Root from "./card.svelte";
+import Content from "./card-content.svelte";
+import Description from "./card-description.svelte";
+import Footer from "./card-footer.svelte";
+import Header from "./card-header.svelte";
+import Title from "./card-title.svelte";
+import Action from "./card-action.svelte";
+
+export {
+ Root,
+ Content,
+ Description,
+ Footer,
+ Header,
+ Title,
+ Action,
+ //
+ Root as Card,
+ Content as CardContent,
+ Description as CardDescription,
+ Footer as CardFooter,
+ Header as CardHeader,
+ Title as CardTitle,
+ Action as CardAction,
+};
diff --git a/src/lib/nom-theme.css b/src/lib/nom-theme.css
deleted file mode 100644
index 67d7e22..0000000
--- a/src/lib/nom-theme.css
+++ /dev/null
@@ -1,108 +0,0 @@
-[data-theme='nominandum'] {
- --text-scaling: 1.067;
-
- --base-font-color: var(--color-surface-900);
- --base-font-color-dark: var(--color-surface-50);
- --base-font-family: Nunito, Helvetica Neue, sans-serif;
- --base-font-size: inherit;
- --base-line-height: 1.5;
- --base-font-weight: 400;
-
- --heading-font-color: var(--color-primary-900);
- --heading-font-color-dark: var(--color-primary-900);
- --heading-font-family: Nunito, Helvetica Neue, sans-serif;
- --heading-font-weight: 400;
-
- --anchor-font-color: var(--color-primary-600);
- --anchor-font-color-dark: var(--color-primary-300);
- --anchor-text-decoration: none;
- --anchor-text-decoration-hover: underline;
-
- --spacing: 0.25rem;
- --radius-base: 0.5rem;
- --radius-container: 24px;
-
- --default-border-width: 1px;
- --default-divide-width: 1px;
- --default-ring-width: 2px;
-
- --body-background-color: #EEF4F6;
- --body-background-color-dark: #0f172a;
-
- /* Primary: Material Blue */
- /* Very Light / Ghostly */
- --color-primary-50: oklch(96.8% 0.010 253deg);
- --color-primary-100: oklch(92.8% 0.020 253deg);
- --color-primary-200: oklch(86.5% 0.040 253deg);
- --color-primary-300: oklch(77.5% 0.060 253deg);
- --color-primary-400: oklch(68.5% 0.080 253deg);
-
- /* Mid-range / Muted Tones */
- --color-primary-500: oklch(59.5% 0.090 253deg);
- --color-primary-600: oklch(52.5% 0.095 253deg);
- --color-primary-700: oklch(45.5% 0.095 253deg);
-
- /* Dark Range (Matching your base color) */
- --color-primary-800: oklch(38.5% 0.090 253deg);
- --color-primary-900: oklch(31.5% 0.090 253deg); /* YOUR BASE COLOR */
- --color-primary-950: oklch(23.5% 0.070 253deg);
-
- --color-primary-contrast-dark: var(--color-primary-950);
- --color-primary-contrast-light: white;
- --color-primary-contrast-50: var(--color-primary-contrast-dark);
- --color-primary-contrast-100: var(--color-primary-contrast-dark);
- --color-primary-contrast-200: var(--color-primary-contrast-dark);
- --color-primary-contrast-300: var(--color-primary-contrast-dark);
- --color-primary-contrast-400: white;
- --color-primary-contrast-500: white;
- --color-primary-contrast-600: white;
- --color-primary-contrast-700: white;
- --color-primary-contrast-800: white;
- --color-primary-contrast-900: white;
- --color-primary-contrast-950: white;
-
- /* Secondary: dezentes Blau-Grau */
- --color-secondary-50: oklch(97% 0.01 250deg);
- --color-secondary-100: oklch(93.5% 0.015 250deg);
- --color-secondary-200: oklch(88.5% 0.022 250deg);
- --color-secondary-300: oklch(80% 0.035 250deg);
- --color-secondary-400: oklch(68% 0.045 250deg);
- --color-secondary-500: oklch(56% 0.055 250deg);
- --color-secondary-600: oklch(48% 0.05 250deg);
- --color-secondary-700: oklch(40% 0.045 250deg);
- --color-secondary-800: oklch(32% 0.04 250deg);
- --color-secondary-900: oklch(24% 0.035 250deg);
- --color-secondary-950: oklch(17% 0.03 250deg);
-
- --color-secondary-contrast-dark: var(--color-secondary-950);
- --color-secondary-contrast-light: white;
-
- /* Tertiary: Akzent Cyan */
- --color-tertiary-50: oklch(97% 0.025 220deg);
- --color-tertiary-100: oklch(93% 0.045 220deg);
- --color-tertiary-200: oklch(87% 0.07 220deg);
- --color-tertiary-300: oklch(78% 0.105 220deg);
- --color-tertiary-400: oklch(69% 0.135 220deg);
- --color-tertiary-500: oklch(60% 0.15 220deg);
- --color-tertiary-600: oklch(52% 0.135 220deg);
- --color-tertiary-700: oklch(44% 0.115 220deg);
- --color-tertiary-800: oklch(36% 0.09 220deg);
- --color-tertiary-900: oklch(29% 0.065 220deg);
- --color-tertiary-950: oklch(21% 0.045 220deg);
-
- /* Surface: Material-nahe kühle Grautöne */
- --color-surface-50: oklch(98.5% 0.004 255deg);
- --color-surface-100: oklch(96.5% 0.006 255deg);
- --color-surface-200: oklch(92.5% 0.01 255deg);
- --color-surface-300: oklch(86.5% 0.015 255deg);
- --color-surface-400: oklch(74% 0.02 255deg);
- --color-surface-500: oklch(62% 0.025 255deg);
- --color-surface-600: oklch(50% 0.025 255deg);
- --color-surface-700: oklch(39% 0.025 255deg);
- --color-surface-800: oklch(29% 0.025 255deg);
- --color-surface-900: oklch(21% 0.025 255deg);
- --color-surface-950: oklch(14% 0.025 255deg);
-
- --color-surface-contrast-dark: var(--color-surface-950);
- --color-surface-contrast-light: white;
-}
\ No newline at end of file
diff --git a/src/lib/services/xml-reading.service.ts b/src/lib/services/xml-reading.service.ts
new file mode 100644
index 0000000..a35f855
--- /dev/null
+++ b/src/lib/services/xml-reading.service.ts
@@ -0,0 +1,93 @@
+export type XJustizMetadata = {
+ sender: string;
+ receiver: string;
+ documentNames: string[];
+};
+
+const XML_TEXT_DECODER = new TextDecoder();
+
+const matchesElementName = (element: Element, requestedName: string) => {
+ const requestedLocalName = requestedName.split('.').pop() ?? requestedName;
+
+ return (
+ element.localName === requestedName ||
+ element.localName === requestedLocalName ||
+ element.tagName === requestedName ||
+ element.tagName === requestedLocalName ||
+ element.tagName.endsWith(`:${requestedLocalName}`)
+ );
+};
+
+const getDirectChildByLocalName = (element: Element, localName: string) =>
+ Array.from(element.children).find((child) => matchesElementName(child, localName)) ?? null;
+
+const getFirstDescendantByLocalName = (root: Document | Element, localName: string) =>
+ Array.from(root.querySelectorAll('*')).find((element) =>
+ matchesElementName(element, localName)
+ ) ?? null;
+
+const getTextContentByPath = (root: Element, path: string[]) => {
+ let current: Element | null = root;
+
+ for (const localName of path) {
+ current = current ? getDirectChildByLocalName(current, localName) : null;
+
+ if (!current) {
+ return null;
+ }
+ }
+
+ const textContent = current.textContent?.trim();
+
+ return textContent ? textContent : null;
+};
+
+const getTextContentByLocalName = (root: Document | Element, localName: string) =>
+ getFirstDescendantByLocalName(root, localName)?.textContent?.trim() ?? null;
+
+const parseXmlDocument = (xmlBytes: Uint8Array) => {
+ const parser = new DOMParser();
+ const document = parser.parseFromString(XML_TEXT_DECODER.decode(xmlBytes), 'application/xml');
+
+ if (document.querySelector('parsererror')) {
+ return null;
+ }
+
+ return document;
+};
+
+export const parseXJustizMetadata = (xmlBytes: Uint8Array): XJustizMetadata | null => {
+ const document = parseXmlDocument(xmlBytes);
+
+ if (!document) {
+ return null;
+ }
+
+ const sender = getTextContentByLocalName(document, 'aktenzeichen.absender') ?? '';
+ const receiver = getTextContentByLocalName(document, 'aktenzeichen.empfaenger') ?? '';
+ const schriftgutobjekte = getFirstDescendantByLocalName(document, 'schriftgutobjekte');
+
+ if (!schriftgutobjekte) {
+ return {
+ sender,
+ receiver,
+ documentNames: []
+ };
+ }
+
+ const dokumentNodes = Array.from(schriftgutobjekte.children).filter((child) =>
+ matchesElementName(child, 'dokument')
+ );
+
+ const documentNames = dokumentNodes
+ .map((dokument) =>
+ getTextContentByPath(dokument, ['xjustiz.fachspezifischeDaten', 'datei', 'dateiname'])
+ )
+ .filter((name): name is string => Boolean(name));
+
+ return {
+ sender,
+ receiver,
+ documentNames
+ };
+};
diff --git a/src/lib/services/zip-inflating.service.ts b/src/lib/services/zip-inflating.service.ts
new file mode 100644
index 0000000..4082758
--- /dev/null
+++ b/src/lib/services/zip-inflating.service.ts
@@ -0,0 +1,13 @@
+import { unzip } from 'fflate';
+
+export const unzipArchive = (data: Uint8Array) =>
+ new Promise>((resolve, reject) => {
+ unzip(data, (error, files) => {
+ if (error) {
+ reject(error);
+ return;
+ }
+
+ resolve(files);
+ });
+ });
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..55b3a91
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,13 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type WithoutChild = T extends { child?: any } ? Omit : T;
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type WithoutChildren = T extends { children?: any } ? Omit : T;
+export type WithoutChildrenOrChild = WithoutChildren>;
+export type WithElementRef = T & { ref?: U | null };
diff --git a/src/lib/zip-processing.ts b/src/lib/zip-processing.ts
new file mode 100644
index 0000000..2137660
--- /dev/null
+++ b/src/lib/zip-processing.ts
@@ -0,0 +1,628 @@
+import { PDFDocument } from 'pdf-lib';
+
+import { parseXJustizMetadata, type XJustizMetadata } from './services/xml-reading.service';
+import { unzipArchive } from './services/zip-inflating.service';
+
+export type ZipAttachmentKind = 'pdf' | 'image';
+
+export type ZipAttachment = {
+ name: string;
+ path: string;
+ kind: ZipAttachmentKind;
+ data: Uint8Array;
+};
+
+export type SubDocument = {
+ id: string;
+ name: string;
+ attachments: ZipAttachment[];
+};
+
+export type ProcessedZipArchive = {
+ name: string;
+ attachments: ZipAttachment[];
+ subDocuments: SubDocument[];
+};
+
+export type ExportMode = 'single' | 'separate';
+
+export type ExportUnit = {
+ name: string;
+ bytes: Uint8Array;
+};
+
+/**
+ * Drag source/target descriptors shared between the archive editor and the
+ * sub-document editor so HTML5 `dataTransfer` payloads stay consistent.
+ */
+export type AttachmentLocation =
+ | { kind: 'loose'; index: number }
+ | { kind: 'subDocument'; id: string; index: number };
+
+const IMAGE_EXTENSIONS = new Set([
+ '.avif',
+ '.bmp',
+ '.gif',
+ '.heic',
+ '.jpeg',
+ '.jpg',
+ '.jp2',
+ '.png',
+ '.tif',
+ '.tiff',
+ '.webp'
+]);
+
+const ZIP_META_FILE_NAME = 'xjustiz_nachricht.xml';
+
+const getBaseName = (path: string) => path.split('/').pop() ?? path;
+
+const getCurrentDateString = (date: Date) =>
+ `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
+
+const createArchiveName = (date: Date, metadata: XJustizMetadata | null) => {
+ const datePrefix = getCurrentDateString(date);
+
+ if (!metadata) {
+ return `${datePrefix}_unbekannt_unbekannt.pdf`;
+ }
+
+ return `${datePrefix}_${metadata.sender}_${metadata.receiver}.pdf`;
+};
+
+const getExtension = (path: string) => {
+ const baseName = getBaseName(path).toLowerCase();
+ const lastDotIndex = baseName.lastIndexOf('.');
+
+ return lastDotIndex === -1 ? '' : baseName.slice(lastDotIndex);
+};
+
+const isPdf = (path: string) => getExtension(path) === '.pdf';
+
+const isImage = (path: string) => IMAGE_EXTENSIONS.has(getExtension(path));
+
+const isZipArchive = (path: string) => getExtension(path) === '.zip';
+
+const normalizeKey = (value: string) => value.replaceAll('\\', '/').toLowerCase().trim();
+
+const isMacMetadataEntry = (path: string) => {
+ const normalizedPath = normalizeKey(path);
+ const baseName = getBaseName(normalizedPath);
+
+ return (
+ normalizedPath.startsWith('__macosx/') ||
+ normalizedPath.includes('/__macosx/') ||
+ baseName === '.ds_store' ||
+ baseName.startsWith('._')
+ );
+};
+const orderAttachmentsByDocumentNames = (attachments: ZipAttachment[], documentNames: string[]) => {
+ const buckets = new Map();
+
+ for (const attachment of attachments) {
+ const keys = new Set([normalizeKey(attachment.path), normalizeKey(attachment.name)]);
+
+ for (const key of keys) {
+ const bucket = buckets.get(key) ?? [];
+ bucket.push(attachment);
+ buckets.set(key, bucket);
+ }
+ }
+
+ const usedAttachments = new Set();
+ const orderedAttachments: ZipAttachment[] = [];
+
+ const takeAttachment = (key: string) => {
+ const bucket = buckets.get(key);
+
+ if (!bucket) {
+ return null;
+ }
+
+ const nextAttachment = bucket.find((attachment) => !usedAttachments.has(attachment)) ?? null;
+
+ if (nextAttachment) {
+ usedAttachments.add(nextAttachment);
+ }
+
+ return nextAttachment;
+ };
+
+ for (const documentName of documentNames) {
+ const normalizedName = normalizeKey(documentName);
+ const normalizedBaseName = normalizeKey(getBaseName(documentName));
+ const matchedAttachment = takeAttachment(normalizedName) ?? takeAttachment(normalizedBaseName);
+
+ if (matchedAttachment) {
+ orderedAttachments.push(matchedAttachment);
+ }
+ }
+
+ for (const attachment of attachments) {
+ if (!usedAttachments.has(attachment)) {
+ orderedAttachments.push(attachment);
+ }
+ }
+
+ return orderedAttachments;
+};
+
+const shouldSkipZipEntry = (path: string) => isMacMetadataEntry(path);
+
+const isMetadataFile = (path: string) => getBaseName(path).toLowerCase() === ZIP_META_FILE_NAME;
+
+const createAttachment = (path: string, data: Uint8Array): ZipAttachment => ({
+ name: getBaseName(path),
+ path,
+ kind: isPdf(path) ? 'pdf' : 'image',
+ data
+});
+
+const extractZipEntries = async (archiveBytes: Uint8Array): Promise => {
+ const files = await unzipArchive(archiveBytes);
+ const attachments: ZipAttachment[] = [];
+ const nestedArchives: ProcessedZipArchive[] = [];
+ let xjustizNachrichtXml: Uint8Array | null = null;
+
+ for (const [path, data] of Object.entries(files)) {
+ if (shouldSkipZipEntry(path)) {
+ continue;
+ }
+
+ if (isMetadataFile(path)) {
+ xjustizNachrichtXml = data;
+ continue;
+ }
+
+ if (isZipArchive(path)) {
+ const childArchives = await extractZipEntries(data);
+ nestedArchives.push(...childArchives);
+ continue;
+ }
+
+ if (isPdf(path) || isImage(path)) {
+ attachments.push(createAttachment(path, data));
+ }
+ }
+
+ const metadata = xjustizNachrichtXml ? parseXJustizMetadata(xjustizNachrichtXml) : null;
+ const documentNames = metadata?.documentNames ?? [];
+ const orderedAttachments = orderAttachmentsByDocumentNames(attachments, documentNames);
+ const archiveName = createArchiveName(new Date(), metadata);
+ const archives: ProcessedZipArchive[] = [];
+
+ if (orderedAttachments.length > 0) {
+ archives.push({
+ name: archiveName,
+ attachments: orderedAttachments,
+ subDocuments: []
+ });
+ }
+
+ return [...archives, ...nestedArchives];
+};
+
+export const extractZipArchives = async (file: File): Promise => {
+ const archiveBytes = new Uint8Array(await file.arrayBuffer());
+
+ return extractZipEntries(archiveBytes);
+};
+
+const loadImageElement = (src: string) =>
+ new Promise((resolve, reject) => {
+ const image = new Image();
+ image.decoding = 'async';
+ image.onload = () => resolve(image);
+ image.onerror = () => reject(new Error(`Unable to decode image asset: ${src}`));
+ image.src = src;
+ });
+
+const toArrayBuffer = (bytes: Uint8Array) =>
+ (() => {
+ const copy = new Uint8Array(bytes.byteLength);
+ copy.set(bytes);
+ return copy.buffer;
+ })();
+
+const convertImageBytesToPng = async (imageBytes: Uint8Array) => {
+ if (typeof document === 'undefined') {
+ throw new Error('Image conversion requires a browser environment.');
+ }
+
+ const objectUrl = URL.createObjectURL(new Blob([toArrayBuffer(imageBytes)]));
+
+ try {
+ const image = await loadImageElement(objectUrl);
+ const canvas = document.createElement('canvas');
+ canvas.width = image.naturalWidth || image.width;
+ canvas.height = image.naturalHeight || image.height;
+
+ const context = canvas.getContext('2d');
+
+ if (!context) {
+ throw new Error('Could not create a canvas context for image conversion.');
+ }
+
+ context.drawImage(image, 0, 0);
+
+ const pngBlob = await new Promise((resolve, reject) => {
+ canvas.toBlob((blob) => {
+ if (blob) {
+ resolve(blob);
+ return;
+ }
+
+ reject(new Error('Could not encode image asset as PNG.'));
+ }, 'image/png');
+ });
+
+ return new Uint8Array(await pngBlob.arrayBuffer());
+ } finally {
+ URL.revokeObjectURL(objectUrl);
+ }
+};
+
+const embedAttachmentImage = async (pdfDocument: PDFDocument, attachment: ZipAttachment) => {
+ const extension = getExtension(attachment.path);
+ const imageData = attachment.data;
+
+ if (extension === '.jpg' || extension === '.jpeg') {
+ return pdfDocument.embedJpg(imageData);
+ }
+
+ if (extension === '.png') {
+ return pdfDocument.embedPng(imageData);
+ }
+
+ const pngBytes = await convertImageBytesToPng(imageData);
+
+ return pdfDocument.embedPng(pngBytes);
+};
+
+const mergeAttachmentIntoPdf = async (mergedPdf: PDFDocument, attachment: ZipAttachment) => {
+ if (attachment.kind === 'pdf') {
+ const sourcePdf = await PDFDocument.load(attachment.data, { ignoreEncryption: true });
+ const copiedPages = await mergedPdf.copyPages(sourcePdf, sourcePdf.getPageIndices());
+
+ for (const page of copiedPages) {
+ mergedPdf.addPage(page);
+ }
+
+ return;
+ }
+
+ try {
+ const embeddedImage = await embedAttachmentImage(mergedPdf, attachment);
+ const page = mergedPdf.addPage([embeddedImage.width, embeddedImage.height]);
+
+ page.drawImage(embeddedImage, {
+ x: 0,
+ y: 0,
+ width: page.getWidth(),
+ height: page.getHeight()
+ });
+ } catch (error) {
+ throw error;
+ }
+};
+
+export const mergeAttachments = async (attachments: ZipAttachment[]): Promise => {
+ if (attachments.length === 0) {
+ throw new Error('Cannot create a PDF from an empty attachment list.');
+ }
+
+ const mergedPdf = await PDFDocument.create();
+
+ for (const attachment of attachments) {
+ await mergeAttachmentIntoPdf(mergedPdf, attachment);
+ }
+
+ return mergedPdf.save();
+};
+
+export const mergeProcessedZipArchive = async (archive: ProcessedZipArchive) => {
+ if (archive.attachments.length === 0 && archive.subDocuments.length === 0) {
+ throw new Error('Cannot create a PDF from an empty archive.');
+ }
+
+ return mergeAttachments(flattenArchiveForMerge(archive));
+};
+
+/**
+ * Flatten the archive into a single ordered attachment list, preserving
+ * sub-document order first and appending loose attachments at the end.
+ */
+export const flattenArchiveForMerge = (archive: ProcessedZipArchive): ZipAttachment[] => {
+ const ordered: ZipAttachment[] = [];
+
+ for (const subDocument of archive.subDocuments) {
+ ordered.push(...subDocument.attachments);
+ }
+
+ ordered.push(...archive.attachments);
+
+ return ordered;
+};
+
+/**
+ * Create a new sub-document with a stable id from a list of attachments.
+ */
+export const createSubDocument = (name: string, attachments: ZipAttachment[]): SubDocument => ({
+ id: crypto.randomUUID(),
+ name,
+ attachments: attachments.map((attachment) => ({ ...attachment }))
+});
+
+/**
+ * Reorder sub-documents inside an archive. Matches the semantics of a single
+ * `splice(fromIndex, 1)` -> `splice(toIndex, 0, moved)` move.
+ */
+export const moveSubDocument = (
+ archive: ProcessedZipArchive,
+ fromIndex: number,
+ toIndex: number
+): ProcessedZipArchive => {
+ if (
+ fromIndex === toIndex ||
+ fromIndex < 0 ||
+ toIndex < 0 ||
+ fromIndex >= archive.subDocuments.length ||
+ toIndex >= archive.subDocuments.length
+ ) {
+ return archive;
+ }
+
+ const nextSubDocuments = [...archive.subDocuments];
+ const [movedSubDocument] = nextSubDocuments.splice(fromIndex, 1);
+
+ nextSubDocuments.splice(toIndex, 0, movedSubDocument);
+
+ return { ...archive, subDocuments: nextSubDocuments };
+};
+
+const removeAt = (list: T[], index: number): T | null => {
+ if (index < 0 || index >= list.length) {
+ return null;
+ }
+
+ const [item] = list.splice(index, 1);
+
+ return item ?? null;
+};
+
+const insertAt = (list: T[], index: number, item: T) => {
+ const clampedIndex = Math.max(0, Math.min(index, list.length));
+ list.splice(clampedIndex, 0, item);
+};
+
+/**
+ * Reorder an attachment within its current location (loose list or a single
+ * sub-document's attachment list). Used by the per-list drag handlers.
+ */
+export const moveAttachmentInPlace = (
+ archive: ProcessedZipArchive,
+ location: AttachmentLocation,
+ toIndex: number
+): ProcessedZipArchive => {
+ if (location.kind === 'loose') {
+ const nextAttachments = [...archive.attachments];
+ const moved = removeAt(nextAttachments, location.index);
+
+ if (!moved) {
+ return archive;
+ }
+
+ insertAt(nextAttachments, toIndex, moved);
+
+ return { ...archive, attachments: nextAttachments };
+ }
+
+ let changed = false;
+
+ const nextSubDocuments = archive.subDocuments.map((subDocument) => {
+ if (subDocument.id !== location.id) {
+ return subDocument;
+ }
+
+ const nextAttachments = [...subDocument.attachments];
+ const moved = removeAt(nextAttachments, location.index);
+
+ if (!moved) {
+ return subDocument;
+ }
+
+ insertAt(nextAttachments, toIndex, moved);
+ changed = true;
+
+ return { ...subDocument, attachments: nextAttachments };
+ });
+
+ return changed ? { ...archive, subDocuments: nextSubDocuments } : archive;
+};
+
+/**
+ * Move an attachment from a source location to a target location. Either side
+ * may be the loose list or any sub-document. The attachment moves (not copies),
+ * so the total attachment count is invariant. When source and target point to
+ * the same list, this degenerates to an in-place reorder (explicitly delegated
+ * to `moveAttachmentInPlace` so the indices are normalized correctly).
+ */
+export const moveAttachmentIntoSubDocument = (
+ archive: ProcessedZipArchive,
+ source: AttachmentLocation,
+ target: AttachmentLocation
+): ProcessedZipArchive => {
+ const sameList =
+ source.kind === 'loose' && target.kind === 'loose'
+ ? true
+ : source.kind === 'subDocument' && target.kind === 'subDocument'
+ ? source.id === target.id
+ : false;
+
+ if (sameList) {
+ return moveAttachmentInPlace(archive, source, target.index);
+ }
+
+ const nextSubDocuments = archive.subDocuments.map((subDocument) => ({
+ ...subDocument,
+ attachments: [...subDocument.attachments]
+ }));
+ const looseAttachments = [...archive.attachments];
+
+ const removeFromList = (location: AttachmentLocation): ZipAttachment | null => {
+ if (location.kind === 'loose') {
+ return removeAt(looseAttachments, location.index);
+ }
+
+ const target_ = nextSubDocuments.find((item) => item.id === location.id);
+
+ return target_ ? removeAt(target_.attachments, location.index) : null;
+ };
+
+ const insertIntoList = (attachment: ZipAttachment, location: AttachmentLocation) => {
+ if (location.kind === 'loose') {
+ insertAt(looseAttachments, location.index, attachment);
+ return;
+ }
+
+ const target_ = nextSubDocuments.find((item) => item.id === location.id);
+
+ if (!target_) {
+ // fall back to loose list end if the referenced sub-document vanished
+ looseAttachments.push(attachment);
+ return;
+ }
+
+ insertAt(target_.attachments, location.index, attachment);
+ };
+
+ const movedAttachment = removeFromList(source);
+
+ if (!movedAttachment) {
+ return archive;
+ }
+
+ insertIntoList(movedAttachment, target);
+
+ return {
+ ...archive,
+ attachments: looseAttachments,
+ subDocuments: nextSubDocuments
+ };
+};
+
+/**
+ * Remove a single attachment from a sub-document and return it to the end of
+ * the loose list. Useful as a targeted "move back to loose" action.
+ */
+export const removeAttachmentFromSubDocument = (
+ archive: ProcessedZipArchive,
+ subDocumentId: string,
+ attachmentIndex: number
+): ProcessedZipArchive => {
+ const nextSubDocuments = archive.subDocuments.map((subDocument) => ({
+ ...subDocument,
+ attachments: [...subDocument.attachments]
+ }));
+ const nextLooseAttachments = [...archive.attachments];
+
+ const target_ = nextSubDocuments.find((item) => item.id === subDocumentId);
+
+ if (!target_) {
+ return archive;
+ }
+
+ const moved = removeAt(target_.attachments, attachmentIndex);
+
+ if (!moved) {
+ return archive;
+ }
+
+ nextLooseAttachments.push(moved);
+
+ return {
+ ...archive,
+ attachments: nextLooseAttachments,
+ subDocuments: nextSubDocuments
+ };
+};
+
+/**
+ * Remove an entire sub-document and return its attachments to the end of the
+ * loose list. The sub-document ids of the remaining sub-documents are
+ * preserved.
+ */
+export const dissolveSubDocument = (
+ archive: ProcessedZipArchive,
+ subDocumentId: string
+): ProcessedZipArchive => {
+ const dissolved = archive.subDocuments.find((item) => item.id === subDocumentId);
+
+ if (!dissolved) {
+ return archive;
+ }
+
+ return {
+ ...archive,
+ attachments: [...archive.attachments, ...dissolved.attachments],
+ subDocuments: archive.subDocuments.filter((item) => item.id !== subDocumentId)
+ };
+};
+
+const stripPdfExtension = (name: string) =>
+ name.toLowerCase().endsWith('.pdf') ? name.slice(0, -'.pdf'.length) : name;
+
+/**
+ * Build one or more PDF export units from the archive.
+ *
+ * - `mode: 'single'` mirrors today's behaviour: one merged PDF covering
+ * sub-documents first, then loose attachments, named after the archive.
+ * - `mode: 'separate'` produces one PDF per sub-document (named
+ * `{archiveName} - {subDocumentName}.pdf`) plus a single merged PDF for any
+ * loose attachments (named after the archive). Empty groups are skipped.
+ */
+export const buildArchiveExport = async (
+ archive: ProcessedZipArchive,
+ mode: ExportMode
+): Promise => {
+ if (mode === 'single') {
+ const attachments = flattenArchiveForMerge(archive);
+
+ if (attachments.length === 0) {
+ throw new Error('Cannot create a PDF from an empty archive.');
+ }
+
+ return [
+ {
+ name: stripPdfExtension(archive.name),
+ bytes: await mergeAttachments(attachments)
+ }
+ ];
+ }
+
+ const separateUnits: ExportUnit[] = [];
+
+ for (const subDocument of archive.subDocuments) {
+ if (subDocument.attachments.length === 0) {
+ continue;
+ }
+
+ separateUnits.push({
+ name: `${stripPdfExtension(archive.name)} - ${stripPdfExtension(subDocument.name)}`,
+ bytes: await mergeAttachments(subDocument.attachments)
+ });
+ }
+
+ if (archive.attachments.length > 0) {
+ separateUnits.push({
+ name: stripPdfExtension(archive.name),
+ bytes: await mergeAttachments(archive.attachments)
+ });
+ }
+
+ if (separateUnits.length === 0) {
+ throw new Error('Cannot create a PDF from an empty archive.');
+ }
+
+ return separateUnits;
+};
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 8db6d11..52e8ac8 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,35 +1,211 @@
{#snippet content()}
{#if selectedZipFiles.length === 0}
-
+
+
+
+
+
{:else}
-
-
-
ZIP-Dateien geladen
-
+
+
+ Settings
+ ⚙️
+
-
- {#each selectedZipFiles as file}
- -
- {file.name}
-
- {/each}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if pendingZipCount > 0}
+
+ Noch {pendingZipCount} ZIP-Datei{pendingZipCount === 1 ? '' : 'en'} in Bearbeitung.
+
+ {/if}
+
+ {#if processedZipFiles.length > 0}
+
+ {#each processedZipFiles as file, index}
+
updateProcessedZipFile(index, updatedArchive)}
+ />
+ {/each}
+
+ {/if}
+
{/if}
{/snippet}
- beA-Edit
-
+
+
beA-Edit
+
+ {@render content()}
diff --git a/src/routes/layout.css b/src/routes/layout.css
index 8c267aa..e2394e6 100644
--- a/src/routes/layout.css
+++ b/src/routes/layout.css
@@ -1,16 +1,161 @@
@import 'tailwindcss';
-@import '@skeletonlabs/skeleton/themes/cerberus';
-@import '@skeletonlabs/skeleton';
-@import '@skeletonlabs/skeleton-svelte';
-@import '../lib/nom-theme.css';
+/*@import '../globals.css';*/
+@import "tw-animate-css";
+@import "shadcn-svelte/tailwind.css";
+@import "@fontsource-variable/geist";
+
+@custom-variant dark (&:is(.dark *));
@plugin '@tailwindcss/forms';
@plugin '@tailwindcss/typography';
+@font-face {
+ font-family: 'Nunito';
+ font-style: normal;
+ font-weight: 100 900;
+ src: url('$lib/assets/Nunito-VariableFont_wght.ttf') format('truetype');
+}
-@font-face{
- font-family: 'Nunito';
- font-style: normal;
- font-weight: 100 900;
- src: url('$lib/assets/Nunito-VariableFont_wght.ttf') format("truetype");
-}
\ No newline at end of file
+:root {
+ --background: #EEF4F6;
+ --foreground: #122F62;
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0.145 0 0);
+ --popover: oklch(1 0 0);
+ --popover-foreground: oklch(0.145 0 0);
+ --primary: #122f62;
+ --primary-foreground: oklch(0.985 0 0);
+ --secondary: #EA544B;
+ --secondary-end: #FF6F6D;
+ --secondary-foreground: oklch(0.205 0 0);
+ --muted: oklch(0.97 0 0);
+ --muted-foreground: oklch(0.556 0 0);
+ --accent: #d6dce5;
+ --accent-foreground: oklch(0.205 0 0);
+ --destructive: #ff0027;
+ --border: oklch(0.922 0 0);
+ --input: oklch(0.922 0 0);
+ --ring: oklch(0.708 0 0);
+ --chart-1: oklch(0.87 0 0);
+ --chart-2: oklch(0.556 0 0);
+ --chart-3: oklch(0.439 0 0);
+ --chart-4: oklch(0.371 0 0);
+ --chart-5: oklch(0.269 0 0);
+ --radius: 16px;
+ --sidebar: oklch(0.985 0 0);
+ --sidebar-foreground: oklch(0.145 0 0);
+ --sidebar-primary: oklch(0.205 0 0);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.97 0 0);
+ --sidebar-accent-foreground: oklch(0.205 0 0);
+ --sidebar-border: oklch(0.922 0 0);
+ --sidebar-ring: oklch(0.708 0 0);
+}
+
+.dark {
+ --background: #212121;
+ --foreground: #FFFFFF;
+ --card: oklch(0.205 0 0);
+ --card-foreground: oklch(0.985 0 0);
+ --popover: oklch(0.205 0 0);
+ --popover-foreground: oklch(0.985 0 0);
+ --primary: #92b2eb;
+ --primary-foreground: oklch(0.205 0 0);
+ --secondary: linear-gradient(90deg, #EA544B 0%, #FF6F6D 100%);
+ --secondary-foreground: oklch(0.985 0 0);
+ --muted: oklch(0.269 0 0);
+ --muted-foreground: oklch(0.708 0 0);
+ --accent: oklch(0.269 0 0);
+ --accent-foreground: oklch(0.985 0 0);
+ --destructive: #ff0027;
+ --border: oklch(1 0 0 / 10%);
+ --input: oklch(1 0 0 / 15%);
+ --ring: oklch(0.556 0 0);
+ --chart-1: oklch(0.87 0 0);
+ --chart-2: oklch(0.556 0 0);
+ --chart-3: oklch(0.439 0 0);
+ --chart-4: oklch(0.371 0 0);
+ --chart-5: oklch(0.269 0 0);
+ --sidebar: oklch(0.205 0 0);
+ --sidebar-foreground: oklch(0.985 0 0);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.269 0 0);
+ --sidebar-accent-foreground: oklch(0.985 0 0);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.556 0 0);
+}
+
+@theme inline {
+ --font-sans: 'Nunito', sans-serif;
+ --color-sidebar-ring: var(--sidebar-ring);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar: var(--sidebar);
+ --color-chart-5: var(--chart-5);
+ --color-chart-4: var(--chart-4);
+ --color-chart-3: var(--chart-3);
+ --color-chart-2: var(--chart-2);
+ --color-chart-1: var(--chart-1);
+ --color-ring: var(--ring);
+ --color-input: var(--input);
+ --color-border: var(--border);
+ --color-destructive: var(--destructive);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-accent: var(--accent);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-muted: var(--muted);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-secondary: var(--secondary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-primary: var(--primary);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-popover: var(--popover);
+ --color-card-foreground: var(--card-foreground);
+ --color-card: var(--card);
+ --color-foreground: var(--foreground);
+ --color-background: var(--background);
+ --radius-sm: calc(var(--radius) * 0.6);
+ --radius-md: calc(var(--radius) * 0.8);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) * 1.4);
+ --radius-2xl: calc(var(--radius) * 1.8);
+ --radius-3xl: calc(var(--radius) * 2.2);
+ --radius-4xl: calc(var(--radius) * 2.6);
+}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+ html {
+ @apply font-sans;
+ }
+}
+
+
+/* ripple */
+
+@keyframes ripple {
+ from {
+ transform: scale(0);
+ opacity: 0.8;
+ }
+
+ to {
+ transform: scale(4);
+ opacity: 0;
+ }
+}
+
+.animate-ripple {
+ animation: ripple 600ms ease-out;
+}
+
\ No newline at end of file
diff --git a/uat.yml b/uat.yml
new file mode 100644
index 0000000..fac4fb8
--- /dev/null
+++ b/uat.yml
@@ -0,0 +1,37 @@
+name: Build and Push Docker Image
+
+on:
+ push:
+ branches:
+ - develop
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Docker login to Gitea Registry
+ run: |
+ echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "${{ vars.REGISTRY_URL }}" \
+ -u "${{ secrets.REGISTRY_USER }}" \
+ --password-stdin
+
+ - name: Build Docker image
+ run: |
+ docker build \
+ -t "${{ vars.REGISTRY_URL }}/${{ vars.IMAGE_NAME }}:dev" \
+ -t "${{ vars.REGISTRY_URL }}/${{ vars.IMAGE_NAME }}:${{ gitea.sha }}" \
+ .
+
+ - name: Push Docker image
+ run: |
+ docker push "${{ vars.REGISTRY_URL }}/${{ vars.IMAGE_NAME }}:dev"
+ docker push "${{ vars.REGISTRY_URL }}/${{ vars.IMAGE_NAME }}:${{ gitea.sha }}"
+
+ - name: Deploy
+ run: |
+ curl https://dokploy.robosoft-solutions.de/api/deploy/compose/Miw8GJXF_v4Ebavr3mJwa
diff --git a/vite.config.ts b/vite.config.ts
index 5765ebc..5d92263 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,5 +1,5 @@
import tailwindcss from '@tailwindcss/vite';
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-node';
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
@@ -13,9 +13,6 @@ export default defineConfig({
filename.split(/[/\\]/).includes('node_modules') ? undefined : true
},
- // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
- // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
- // See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
})
]