diff --git a/frontend/.prettierrc b/frontend/.prettierrc index 819fa57..13f9f03 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -1,16 +1,17 @@ { - "useTabs": true, - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100, - "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], - "overrides": [ - { - "files": "*.svelte", - "options": { - "parser": "svelte" - } - } - ], - "tailwindStylesheet": "./src/routes/layout.css" + "useTabs": false, + "tabWidth": 4, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ], + "tailwindStylesheet": "./src/routes/layout.css" } diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index 0014edd..8e77353 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -11,34 +11,34 @@ import svelteConfig from './svelte.config.js'; const gitignorePath = path.resolve(import.meta.dirname, '.gitignore'); export default defineConfig( - includeIgnoreFile(gitignorePath), - js.configs.recommended, - ts.configs.recommended, - svelte.configs.recommended, - prettier, - svelte.configs.prettier, - { - languageOptions: { globals: { ...globals.browser, ...globals.node } }, - rules: { - // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects. - // see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors - 'no-undef': 'off' - } - }, - { - files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'], - languageOptions: { - parserOptions: { - projectService: true, - extraFileExtensions: ['.svelte'], - parser: ts.parser, - svelteConfig - } - } - }, - { - // Override or add rule settings here, such as: - // 'svelte/button-has-type': 'error' - rules: {} - } + includeIgnoreFile(gitignorePath), + js.configs.recommended, + ts.configs.recommended, + svelte.configs.recommended, + prettier, + svelte.configs.prettier, + { + languageOptions: { globals: { ...globals.browser, ...globals.node } }, + rules: { + // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects. + // see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors + 'no-undef': 'off' + } + }, + { + files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'], + languageOptions: { + parserOptions: { + projectService: true, + extraFileExtensions: ['.svelte'], + parser: ts.parser, + svelteConfig + } + } + }, + { + // Override or add rule settings here, such as: + // 'svelte/button-has-type': 'error' + rules: {} + } ); diff --git a/frontend/package.json b/frontend/package.json index cb47397..f9bf09b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,50 +1,50 @@ { - "name": "frontend", - "private": true, - "version": "0.0.1", - "type": "module", - "scripts": { - "dev": "vite dev", - "build": "vite build", - "preview": "vite preview", - "prepare": "svelte-kit sync || echo ''", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "prettier --check . && eslint .", - "format": "prettier --write .", - "test:e2e": "playwright test", - "test": "npm run test:unit -- --run && npm run test:e2e", - "test:unit": "vitest" - }, - "devDependencies": { - "@eslint/compat": "^2.0.3", - "@eslint/js": "^10.0.1", - "@fontsource/fira-mono": "^5.2.7", - "@neoconfetti/svelte": "^2.2.2", - "@playwright/test": "^1.58.2", - "@sveltejs/adapter-auto": "^7.0.0", - "@sveltejs/kit": "^2.50.2", - "@sveltejs/vite-plugin-svelte": "^6.2.4", - "@tailwindcss/forms": "^0.5.11", - "@tailwindcss/typography": "^0.5.19", - "@tailwindcss/vite": "^4.1.18", - "@types/node": "^24", - "@vitest/browser-playwright": "^4.1.0", - "eslint": "^10.0.3", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-svelte": "^3.15.2", - "globals": "^17.4.0", - "playwright": "^1.58.2", - "prettier": "^3.8.1", - "prettier-plugin-svelte": "^3.4.1", - "prettier-plugin-tailwindcss": "^0.7.2", - "svelte": "^5.54.0", - "svelte-check": "^4.4.2", - "tailwindcss": "^4.1.18", - "typescript": "^5.9.3", - "typescript-eslint": "^8.57.0", - "vite": "^7.3.1", - "vitest": "^4.1.0", - "vitest-browser-svelte": "^2.0.2" - } + "name": "frontend", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "prepare": "svelte-kit sync || echo ''", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check . && eslint .", + "format": "prettier --write .", + "test:e2e": "playwright test", + "test": "npm run test:unit -- --run && npm run test:e2e", + "test:unit": "vitest" + }, + "devDependencies": { + "@eslint/compat": "^2.0.3", + "@eslint/js": "^10.0.1", + "@fontsource/fira-mono": "^5.2.7", + "@neoconfetti/svelte": "^2.2.2", + "@playwright/test": "^1.58.2", + "@sveltejs/adapter-auto": "^7.0.0", + "@sveltejs/kit": "^2.50.2", + "@sveltejs/vite-plugin-svelte": "^6.2.4", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/typography": "^0.5.19", + "@tailwindcss/vite": "^4.1.18", + "@types/node": "^24", + "@vitest/browser-playwright": "^4.1.0", + "eslint": "^10.0.3", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-svelte": "^3.15.2", + "globals": "^17.4.0", + "playwright": "^1.58.2", + "prettier": "^3.8.1", + "prettier-plugin-svelte": "^3.4.1", + "prettier-plugin-tailwindcss": "^0.7.2", + "svelte": "^5.54.0", + "svelte-check": "^4.4.2", + "tailwindcss": "^4.1.18", + "typescript": "^5.9.3", + "typescript-eslint": "^8.57.0", + "vite": "^7.3.1", + "vitest": "^4.1.0", + "vitest-browser-svelte": "^2.0.2" + } } diff --git a/frontend/pnpm-workspace.yaml b/frontend/pnpm-workspace.yaml index efc037a..7cb5b88 100644 --- a/frontend/pnpm-workspace.yaml +++ b/frontend/pnpm-workspace.yaml @@ -1,2 +1,2 @@ onlyBuiltDependencies: - - esbuild + - esbuild diff --git a/frontend/src/app.d.ts b/frontend/src/app.d.ts index da08e6d..d76242a 100644 --- a/frontend/src/app.d.ts +++ b/frontend/src/app.d.ts @@ -1,13 +1,13 @@ // See https://svelte.dev/docs/kit/types#app.d.ts // for information about these interfaces declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface PageState {} - // interface Platform {} - } + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } } export {}; diff --git a/frontend/src/app.html b/frontend/src/app.html index dc49ff8..bffaaa1 100644 --- a/frontend/src/app.html +++ b/frontend/src/app.html @@ -1,14 +1,17 @@ - - - - - - - %sveltekit.head% - - -
%sveltekit.body%
- + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 9efac37..3cc8529 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -1,10 +1,10 @@ -import type { FileRecord } from "$lib/types"; +import type { FileRecord } from '$lib/types'; export async function loadFiles(): Promise { const res = await fetch('/api/files', { credentials: 'include' }); - + if (res.status === 401) { window.location.href = '/auth'; return []; @@ -14,10 +14,9 @@ export async function loadFiles(): Promise { throw new Error(`Failed to load files: ${res.status}`); } - return await res.json() + return await res.json(); } - export async function uploadFile(file: File): Promise { const formData = new FormData(); formData.append('file', file); @@ -28,10 +27,10 @@ export async function uploadFile(file: File): Promise { }); if (!res.ok) { - throw new Error(`Upload failed: ${res.status}`) + throw new Error(`Upload failed: ${res.status}`); } - return await res.json() + return await res.json(); } export async function downloadFile(fileId: number): Promise { @@ -39,10 +38,10 @@ export async function downloadFile(fileId: number): Promise { credentials: 'include' }); if (!res.ok) { - throw new Error(`Download failed: ${res.status}`) + throw new Error(`Download failed: ${res.status}`); } - return await res.blob() + return await res.blob(); } export async function deleteFile(fileId: number): Promise { diff --git a/frontend/src/lib/components/FilePreview.svelte b/frontend/src/lib/components/FilePreview.svelte index a471d03..ad771ff 100644 --- a/frontend/src/lib/components/FilePreview.svelte +++ b/frontend/src/lib/components/FilePreview.svelte @@ -1,33 +1,50 @@ - { if (e.key === 'Escape') onclose(); }} /> + { + if (e.key === 'Escape') onclose(); + }} +/>
e.stopPropagation()} > -
- {file.name} -
-
+
preview coming soon
diff --git a/frontend/src/lib/components/FileRow.svelte b/frontend/src/lib/components/FileRow.svelte index 955ec49..7f6fba1 100644 --- a/frontend/src/lib/components/FileRow.svelte +++ b/frontend/src/lib/components/FileRow.svelte @@ -8,7 +8,7 @@ onselect, onpreview, ondownload, - ondelete, + ondelete }: { file: FileRecord; selected: boolean; @@ -28,59 +28,135 @@ if (e.key === 'Enter') { onpreview(); } else if (e.key === ' ') { - e.preventDefault(); onselect(); + e.preventDefault(); + onselect(); } - } - } + }} onclick={onselect} ondblclick={onpreview} - class="flex items-stretch border-l hover:bg-white/2 transition-all {selected ? 'border-sky-400/50 bg-white/2 ring-1 ring-inset ring-sky-400/50' : 'border-sky-200/20 border-l-transparent hover:border-l-sky-400/50'}" + class="flex items-stretch border-l transition-all hover:bg-white/2 {selected + ? 'border-sky-400/50 bg-white/2 ring-1 ring-sky-400/50 ring-inset' + : 'border-sky-200/20 border-l-transparent hover:border-l-sky-400/50'}" > - {formatName(file.name)} - {formatSize(file.size)} - {new Date(file.uploadedAt).toLocaleString()} -
-
+ {formatName(file.name)} + {formatSize(file.size)} + {new Date(file.uploadedAt).toLocaleString()} +
+
- -
diff --git a/frontend/src/lib/format.ts b/frontend/src/lib/format.ts index 5a048f7..5190246 100644 --- a/frontend/src/lib/format.ts +++ b/frontend/src/lib/format.ts @@ -1,13 +1,13 @@ export function formatName(name: string): string { - if (name.length > 65) { - name = name.slice(0, 65).concat("..."); - } - return name; - } + if (name.length > 65) { + name = name.slice(0, 65).concat('...'); + } + return name; +} export function formatSize(bytes: number): string { if (bytes < 1000) return bytes + 'B'; if (bytes < 1000 * 1000) return (bytes / 1000).toFixed(1) + 'KB'; if (bytes < 1000 * 1000 * 1000) return (bytes / 1000 / 1000).toFixed(1) + 'MB'; return (bytes / 1000 / 1000 / 1000).toFixed(1) + 'GB'; -} \ No newline at end of file +} diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index 931bc8e..d3cd303 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -3,4 +3,4 @@ export type FileRecord = { name: string; size: number; uploadedAt: string; -}; \ No newline at end of file +}; diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index ba65b9f..30af30b 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -1,45 +1,44 @@
-
{@render children()}
+
{@render children()}
-
-
+
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 5ea6f7a..6f5edb0 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,26 +1,26 @@

loft

-
-
+
-
@@ -91,23 +104,23 @@
- Name - Size - Uploaded at -
- Actions + Name + Size + Uploaded at +
+ Actions
{#each filteredFileRecords as fileRecord (fileRecord.id)}
- selectedFileId = fileRecord.id} - onpreview={() => previewFile = fileRecord} - ondownload={() => handleDownload(fileRecord.id, fileRecord.name)} - ondelete={() => handleDelete(fileRecord.id)} - /> + (selectedFileId = fileRecord.id)} + onpreview={() => (previewFile = fileRecord)} + ondownload={() => handleDownload(fileRecord.id, fileRecord.name)} + ondelete={() => handleDelete(fileRecord.id)} + />
{:else} {#if !loading}

No files yet.

{/if} @@ -116,5 +129,5 @@
{#if previewFile} - previewFile = null} /> + (previewFile = null)} /> {/if} diff --git a/frontend/src/routes/auth/+page.svelte b/frontend/src/routes/auth/+page.svelte index d4257fe..244ada0 100644 --- a/frontend/src/routes/auth/+page.svelte +++ b/frontend/src/routes/auth/+page.svelte @@ -1,5 +1,5 @@ -
+
-

loft

+

loft

-
+
@@ -37,29 +42,30 @@
- +
- +
- {#if error}

{error}

{/if} -
diff --git a/frontend/src/routes/layout.css b/frontend/src/routes/layout.css index cfc49f8..cabddfe 100644 --- a/frontend/src/routes/layout.css +++ b/frontend/src/routes/layout.css @@ -4,110 +4,110 @@ @import '@fontsource/fira-mono'; :root { - --font-body: - Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, - 'Open Sans', 'Helvetica Neue', sans-serif; - --font-mono: 'Fira Mono', monospace; - --color-text: rgba(255, 255, 255, 0.87); - --column-width: 42rem; - --column-margin-top: 4rem; - font-family: var(--font-body); - color: var(--color-text); + --font-body: + Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, + 'Open Sans', 'Helvetica Neue', sans-serif; + --font-mono: 'Fira Mono', monospace; + --color-text: rgba(255, 255, 255, 0.87); + --column-width: 42rem; + --column-margin-top: 4rem; + font-family: var(--font-body); + color: var(--color-text); } body { - min-height: 100vh; - margin: 0; - background-color: #0f1117; + min-height: 100vh; + margin: 0; + background-color: #0f1117; } h1, h2, p { - font-weight: 400; + font-weight: 400; } p { - line-height: 1.5; + line-height: 1.5; } a { - color: var(--color-theme-1); - text-decoration: none; + color: var(--color-theme-1); + text-decoration: none; } a:hover { - text-decoration: underline; + text-decoration: underline; } h1 { - font-size: 2rem; - text-align: center; + font-size: 2rem; + text-align: center; } h2 { - font-size: 1rem; + font-size: 1rem; } pre { - font-size: 16px; - font-family: var(--font-mono); - background-color: rgba(255, 255, 255, 0.45); - border-radius: 3px; - box-shadow: 2px 2px 6px rgb(255 255 255 / 25%); - padding: 0.5em; - overflow-x: auto; - color: var(--color-text); + font-size: 16px; + font-family: var(--font-mono); + background-color: rgba(255, 255, 255, 0.45); + border-radius: 3px; + box-shadow: 2px 2px 6px rgb(255 255 255 / 25%); + padding: 0.5em; + overflow-x: auto; + color: var(--color-text); } .text-column { - display: flex; - max-width: 48rem; - flex: 0.6; - flex-direction: column; - justify-content: center; - margin: 0 auto; + display: flex; + max-width: 48rem; + flex: 0.6; + flex-direction: column; + justify-content: center; + margin: 0 auto; } input, button { - font-size: inherit; - font-family: inherit; + font-size: inherit; + font-family: inherit; } input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, input:-webkit-autofill:active { - -webkit-box-shadow: 0 0 0 1000px #0f1117 inset !important; - -webkit-text-fill-color: #ffffffcc !important; - font-size: 16px !important; + -webkit-box-shadow: 0 0 0 1000px #0f1117 inset !important; + -webkit-text-fill-color: #ffffffcc !important; + font-size: 16px !important; } input:-moz-autofill { - background-color: #0f1117 !important; - color: #ffffffcc !important; - filter: none !important; + background-color: #0f1117 !important; + color: #ffffffcc !important; + filter: none !important; } button:focus:not(:focus-visible) { - outline: none; + outline: none; } @media (min-width: 720px) { - h1 { - font-size: 2.4rem; - } + h1 { + font-size: 2.4rem; + } } .visually-hidden { - border: 0; - clip: rect(0 0 0 0); - height: auto; - margin: 0; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - white-space: nowrap; + border: 0; + clip: rect(0 0 0 0); + height: auto; + margin: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + white-space: nowrap; } diff --git a/frontend/svelte.config.js b/frontend/svelte.config.js index 10c4eeb..d24e4c6 100644 --- a/frontend/svelte.config.js +++ b/frontend/svelte.config.js @@ -2,12 +2,12 @@ import adapter from '@sveltejs/adapter-auto'; /** @type {import('@sveltejs/kit').Config} */ const config = { - kit: { - // 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() - } + kit: { + // 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() + } }; export default config; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 2c2ed3c..f371425 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,20 +1,20 @@ { - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "rewriteRelativeImportExtensions": true, - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "moduleResolution": "bundler" - } - // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias - // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files - // - // To make changes to top-level options such as include and exclude, we recommend extending - // the generated config; see https://svelte.dev/docs/kit/configuration#typescript + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "rewriteRelativeImportExtensions": true, + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } + // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias + // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files + // + // To make changes to top-level options such as include and exclude, we recommend extending + // the generated config; see https://svelte.dev/docs/kit/configuration#typescript } diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 23d2f96..8ffafee 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -4,38 +4,38 @@ import tailwindcss from '@tailwindcss/vite'; import { sveltekit } from '@sveltejs/kit/vite'; export default defineConfig({ - plugins: [tailwindcss(), sveltekit()], - server: { - proxy: { - '/api': 'http://localhost:3000' - } + plugins: [tailwindcss(), sveltekit()], + server: { + proxy: { + '/api': 'http://localhost:3000' + } }, - test: { - expect: { requireAssertions: true }, - projects: [ - { - extends: './vite.config.ts', - test: { - name: 'client', - browser: { - enabled: true, - provider: playwright(), - instances: [{ browser: 'chromium', headless: true }] - }, - include: ['src/**/*.svelte.{test,spec}.{js,ts}'], - exclude: ['src/lib/server/**'] - } - }, + test: { + expect: { requireAssertions: true }, + projects: [ + { + extends: './vite.config.ts', + test: { + name: 'client', + browser: { + enabled: true, + provider: playwright(), + instances: [{ browser: 'chromium', headless: true }] + }, + include: ['src/**/*.svelte.{test,spec}.{js,ts}'], + exclude: ['src/lib/server/**'] + } + }, - { - extends: './vite.config.ts', - test: { - name: 'server', - environment: 'node', - include: ['src/**/*.{test,spec}.{js,ts}'], - exclude: ['src/**/*.svelte.{test,spec}.{js,ts}'] - } - } - ] - } + { + extends: './vite.config.ts', + test: { + name: 'server', + environment: 'node', + include: ['src/**/*.{test,spec}.{js,ts}'], + exclude: ['src/**/*.svelte.{test,spec}.{js,ts}'] + } + } + ] + } }); diff --git a/package.json b/package.json new file mode 100644 index 0000000..b0b22eb --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "devDependencies": { + "prettier": "^3.8.3", + "prettier-plugin-svelte": "^4.1.0", + "prettier-plugin-tailwindcss": "^0.8.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..9ccb3ec --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,253 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + prettier: + specifier: ^3.8.3 + version: 3.8.3 + prettier-plugin-svelte: + specifier: ^4.1.0 + version: 4.1.0(prettier@3.8.3)(svelte@5.56.0) + prettier-plugin-tailwindcss: + specifier: ^0.8.0 + version: 0.8.0(prettier-plugin-svelte@4.1.0(prettier@3.8.3)(svelte@5.56.0))(prettier@3.8.3) + +packages: + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@sveltejs/acorn-typescript@1.0.10': + resolution: {integrity: sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==} + peerDependencies: + acorn: ^8.9.0 + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + aria-query@5.3.1: + resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} + engines: {node: '>= 0.4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + devalue@5.8.1: + resolution: {integrity: sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==} + + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + + esrap@2.2.9: + resolution: {integrity: sha512-4KijP+NxCWthMCUC3qHbE6n4vCjqgJS1uAYKhuT/GWfFTf1Qyive2TgOjep+gzbSzRfnNyaN/UU9YmdOt8Eg0A==} + peerDependencies: + '@typescript-eslint/types': ^8.2.0 + peerDependenciesMeta: + '@typescript-eslint/types': + optional: true + + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + prettier-plugin-svelte@4.1.0: + resolution: {integrity: sha512-YZkhA2Q9oOerFFG9tq+2f98WYT7Z2JgrybJrAyrB78jpsH9i/DdgplXemehuFPgsldetFNCcR/yCcYlDjPy94Q==} + engines: {node: '>=20'} + peerDependencies: + prettier: ^3.0.0 + svelte: ^5.0.0 + + prettier-plugin-tailwindcss@0.8.0: + resolution: {integrity: sha512-V8ITGH87yuBDF6JpEZTOVlUz/saAwqb8f3HRgUj8Lh+tGCcrmorhsLpYqzygwFwK0PE2Ib6Mv3M7T/uE2tZV1g==} + engines: {node: '>=20.19'} + peerDependencies: + '@ianvs/prettier-plugin-sort-imports': '*' + '@prettier/plugin-hermes': '*' + '@prettier/plugin-oxc': '*' + '@prettier/plugin-pug': '*' + '@shopify/prettier-plugin-liquid': '*' + '@trivago/prettier-plugin-sort-imports': '*' + '@zackad/prettier-plugin-twig': '*' + prettier: ^3.0 + prettier-plugin-astro: '*' + prettier-plugin-css-order: '*' + prettier-plugin-jsdoc: '*' + prettier-plugin-marko: '*' + prettier-plugin-multiline-arrays: '*' + prettier-plugin-organize-attributes: '*' + prettier-plugin-organize-imports: '*' + prettier-plugin-sort-imports: '*' + prettier-plugin-svelte: '*' + peerDependenciesMeta: + '@ianvs/prettier-plugin-sort-imports': + optional: true + '@prettier/plugin-hermes': + optional: true + '@prettier/plugin-oxc': + optional: true + '@prettier/plugin-pug': + optional: true + '@shopify/prettier-plugin-liquid': + optional: true + '@trivago/prettier-plugin-sort-imports': + optional: true + '@zackad/prettier-plugin-twig': + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-marko: + optional: true + prettier-plugin-multiline-arrays: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-sort-imports: + optional: true + prettier-plugin-svelte: + optional: true + + prettier@3.8.3: + resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} + engines: {node: '>=14'} + hasBin: true + + svelte@5.56.0: + resolution: {integrity: sha512-kTXr26t1bchFp28ROrb957LtbujpBmBDibmqMGziVpUs7awBi96TGgX6SovrA8BNoEUDVRK2Fb9FkeYlGspoVg==} + engines: {node: '>=18'} + + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + +snapshots: + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@sveltejs/acorn-typescript@1.0.10(acorn@8.16.0)': + dependencies: + acorn: 8.16.0 + + '@types/estree@1.0.9': {} + + '@types/trusted-types@2.0.7': {} + + acorn@8.16.0: {} + + aria-query@5.3.1: {} + + axobject-query@4.1.0: {} + + clsx@2.1.1: {} + + devalue@5.8.1: {} + + esm-env@1.2.2: {} + + esrap@2.2.9: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + locate-character@3.0.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + prettier-plugin-svelte@4.1.0(prettier@3.8.3)(svelte@5.56.0): + dependencies: + prettier: 3.8.3 + svelte: 5.56.0 + + prettier-plugin-tailwindcss@0.8.0(prettier-plugin-svelte@4.1.0(prettier@3.8.3)(svelte@5.56.0))(prettier@3.8.3): + dependencies: + prettier: 3.8.3 + optionalDependencies: + prettier-plugin-svelte: 4.1.0(prettier@3.8.3)(svelte@5.56.0) + + prettier@3.8.3: {} + + svelte@5.56.0: + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.10(acorn@8.16.0) + '@types/estree': 1.0.9 + '@types/trusted-types': 2.0.7 + acorn: 8.16.0 + aria-query: 5.3.1 + axobject-query: 4.1.0 + clsx: 2.1.1 + devalue: 5.8.1 + esm-env: 1.2.2 + esrap: 2.2.9 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + zimmerframe: 1.1.4 + transitivePeerDependencies: + - '@typescript-eslint/types' + + zimmerframe@1.1.4: {}