diff --git a/.github/actions/build-package/action.yaml b/.github/actions/build-package/action.yaml index 506ef7f9..5059e31d 100644 --- a/.github/actions/build-package/action.yaml +++ b/.github/actions/build-package/action.yaml @@ -4,26 +4,6 @@ description: Build python package with bundled frontend runs: using: composite steps: - - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 - with: - node-version: 22 - cache: npm - cache-dependency-path: frontend/app/package-lock.json - - - name: Build SvelteKit frontend - shell: bash - working-directory: frontend/app - run: | - npm ci - npm run build - - name: Build and inspect Python package id: baipp - uses: hynek/build-and-inspect-python-package@ebd3b6c6d32b78607276633a23bdd4481bd23ca8 # v2.18.0 - - - name: Verify frontend bundled in wheel - shell: bash - run: | - unzip -l "${{ steps.baipp.outputs.dist }}"/pypsa_app-*.whl | grep -q "static/app/index.html" \ - || { echo "wheel missing built frontend (static/app/index.html)"; exit 1; } + uses: hynek/build-and-inspect-python-package@ebd3b6c6d32b78607276633a23bdd4481bd23ca8 # v2.18.0 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1c9b193a..452af01d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -23,18 +23,6 @@ updates: patterns: ["*"] update-types: ["minor", "patch"] -- package-ecosystem: "npm" - directory: "/frontend/app" - schedule: - interval: "weekly" - cooldown: - default-days: 7 - semver-major-days: 14 - groups: - npm: - patterns: ["*"] - update-types: ["minor", "patch"] - - package-ecosystem: "docker" directory: "/" schedule: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b9c8b529..cf2d013d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -16,8 +16,8 @@ on: branches: ["main"] pull_request: branches: ["main"] - schedule: - - cron: '24 21 * * 5' + schedule: #Re-scan regularly in case the set of codeql rules changes + - cron: "24 21 * * 5" jobs: analyze: @@ -45,8 +45,6 @@ jobs: include: - language: actions build-mode: none - - language: javascript-typescript - build-mode: none - language: python build-mode: none # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' @@ -59,33 +57,33 @@ jobs: # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages steps: - name: Checkout repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - # Add any setup steps before running the `github/codeql-action/init` action. - # This includes steps like installing compilers or runtimes (`actions/setup-node` - # or others). This is typically only required for manual builds. - # - name: Setup runtime (example) - # uses: actions/setup-example@v1 + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 - # Initializes the CodeQL tools for scanning. + # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - name: Run manual build steps if: matrix.build-mode == 'manual' shell: bash @@ -98,6 +96,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: category: "/language:${{matrix.language}}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7d6b8f76..fb4e7933 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,6 @@ ci: autoupdate_schedule: quarterly autofix_prs: false - skip: [svelte-check] repos: - repo: https://github.com/pre-commit/pre-commit-hooks @@ -18,49 +17,38 @@ repos: - id: check-case-conflict - id: mixed-line-ending - # Python - Ruff + # Python - Ruff - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.15.9 hooks: # Run the linter - id: ruff args: [--fix] - # Run the formatter + # Run the formatter - id: ruff-format - # Find common spelling mistakes in comments and docstrings + # Find common spelling mistakes in comments and docstrings - repo: https://github.com/codespell-project/codespell rev: v2.4.2 hooks: - id: codespell - args: ['--ignore-regex=(\b[A-Z]+\b)', '--ignore-words-list=fom'] + args: ['--ignore-regex=(\b[A-Z]+\b)', "--ignore-words-list=fom"] types_or: [python, rst, markdown] - # Do YAML formatting + # Do YAML formatting - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks rev: v2.16.0 hooks: - id: pretty-format-yaml - args: [--autofix, --indent, '2', --preserve-quotes] + args: [--autofix, --indent, "2", --preserve-quotes] - # Detect secrets + # Detect secrets - repo: https://github.com/gitleaks/gitleaks rev: v8.30.0 hooks: - id: gitleaks - # Svelte/TypeScript - check types and Svelte warnings -- repo: local - hooks: - - id: svelte-check - name: svelte-check - entry: bash -c 'cd frontend/app && npm run check' - language: system - files: ^frontend/app/src/ - types_or: [svelte, ts, javascript] - pass_filenames: false - - # Lint Github Actions + # Lint Github Actions - repo: https://github.com/rhysd/actionlint rev: v1.7.12 hooks: diff --git a/README.md b/README.md index 0f2bb132..d0adbaab 100644 --- a/README.md +++ b/README.md @@ -45,15 +45,7 @@ API docs available at [`http://localhost:8000/docs`](http://localhost:8000/docs) ### Frontend -Applies to both modes. Requires Node.js 22.x. - -```bash -cd frontend/app -npm install -npm run dev -``` - -App available at [`http://localhost:5173`](http://localhost:5173). +Currently non-existent. ## Running Tests diff --git a/frontend/app/.npmrc b/frontend/app/.npmrc deleted file mode 100644 index 32e60127..00000000 --- a/frontend/app/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -engine-strict=true -ignore-scripts=true diff --git a/frontend/app/components.json b/frontend/app/components.json deleted file mode 100644 index 9f8c985f..00000000 --- a/frontend/app/components.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "tailwind": { - "css": "src/app.css", - "baseColor": "neutral" - }, - "aliases": { - "components": "$lib/components", - "utils": "$lib/utils", - "ui": "$lib/components/ui", - "hooks": "$lib/hooks", - "lib": "$lib" - }, - "typescript": true, - "registry": "https://shadcn-svelte.com/registry" -} diff --git a/frontend/app/package-lock.json b/frontend/app/package-lock.json deleted file mode 100644 index 218e2b83..00000000 --- a/frontend/app/package-lock.json +++ /dev/null @@ -1,3573 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.1", - "dependencies": { - "@deck.gl/core": "9.3.3", - "@deck.gl/layers": "9.3.3", - "@tailwindcss/typography": "0.5.19", - "@tanstack/svelte-table": "9.0.0-alpha.10", - "dompurify": "3.4.7", - "elkjs": "0.11.1", - "gridstack": "12.6.0", - "js-yaml": "4.2.0", - "maplibre-gl": "5.24.0", - "marked": "18.0.4", - "mode-watcher": "1.1.0", - "plotly.js-dist": "3.6.0", - "svelte-sonner": "1.1.1" - }, - "devDependencies": { - "@internationalized/date": "3.12.2", - "@lucide/svelte": "0.561.0", - "@sveltejs/adapter-static": "3.0.10", - "@sveltejs/kit": "2.62.0", - "@sveltejs/vite-plugin-svelte": "6.2.4", - "@tailwindcss/vite": "4.3.0", - "@tanstack/table-core": "8.21.3", - "@types/js-yaml": "4.0.9", - "@types/node": "25.9.1", - "bits-ui": "2.18.1", - "clsx": "2.1.1", - "svelte": "5.56.1", - "svelte-check": "4.5.0", - "tailwind-merge": "3.6.0", - "tailwind-variants": "3.2.2", - "tailwindcss": "4.3.0", - "tw-animate-css": "1.4.0", - "typescript": "5.9.3", - "vite": "7.3.3" - }, - "engines": { - "node": "22.x", - "npm": ">=10" - } - }, - "node_modules/@deck.gl/core": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-9.3.3.tgz", - "integrity": "sha512-P8IPB0VJyyKBGEUC6wT2sfqNYY/IClzYIqi0iyHBunKTUKQNwiKhPasQLCEfb157KNoCdeZxjnohkyRYqbas+A==", - "license": "MIT", - "dependencies": { - "@loaders.gl/core": "^4.4.1", - "@loaders.gl/images": "^4.4.1", - "@luma.gl/core": "^9.3.3", - "@luma.gl/engine": "^9.3.3", - "@luma.gl/shadertools": "^9.3.3", - "@luma.gl/webgl": "^9.3.3", - "@math.gl/core": "^4.1.0", - "@math.gl/sun": "^4.1.0", - "@math.gl/types": "^4.1.0", - "@math.gl/web-mercator": "^4.1.0", - "@probe.gl/env": "^4.1.1", - "@probe.gl/log": "^4.1.1", - "@probe.gl/stats": "^4.1.1", - "@types/offscreencanvas": "^2019.6.4", - "gl-matrix": "^3.0.0", - "mjolnir.js": "^3.0.0" - } - }, - "node_modules/@deck.gl/layers": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-9.3.3.tgz", - "integrity": "sha512-sp7rvAe/SM/Ja8sVKF0r5ZFj+W5y1h9HpmFZUGv+knkBhrwWLfxa6p3sycimdLMd22tCguw7ps4klKgZjgYTtw==", - "license": "MIT", - "dependencies": { - "@loaders.gl/images": "^4.4.1", - "@loaders.gl/schema": "^4.4.1", - "@luma.gl/shadertools": "^9.3.3", - "@mapbox/tiny-sdf": "^2.0.5", - "@math.gl/core": "^4.1.0", - "@math.gl/polygon": "^4.1.0", - "@math.gl/web-mercator": "^4.1.0", - "earcut": "^2.2.4" - }, - "peerDependencies": { - "@deck.gl/core": "~9.3.0", - "@loaders.gl/core": "^4.4.1", - "@luma.gl/core": "~9.3.3", - "@luma.gl/engine": "~9.3.3" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", - "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.11" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", - "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.5", - "@floating-ui/utils": "^0.2.11" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", - "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@internationalized/date": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.2.tgz", - "integrity": "sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@loaders.gl/core": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@loaders.gl/core/-/core-4.4.1.tgz", - "integrity": "sha512-/s4IuvCCQUepvhjLnmePwQppGko2d1pxRS+sp7lyExU0uiqo5dVsAKaCZ2VnddBkFWgDVb/wvcZUBmv/dWcj0Q==", - "license": "MIT", - "dependencies": { - "@loaders.gl/loader-utils": "4.4.1", - "@loaders.gl/schema": "4.4.1", - "@loaders.gl/schema-utils": "4.4.1", - "@loaders.gl/worker-utils": "4.4.1", - "@probe.gl/log": "^4.1.1" - } - }, - "node_modules/@loaders.gl/images": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@loaders.gl/images/-/images-4.4.1.tgz", - "integrity": "sha512-v9A4BliEKGxhLuEbh0Ke8ElUlp04KxpKIknUtXXWoEaszAMTSrHI3YhaL/JdRlHraC1VUF/sjzbSBFkKh7nxJg==", - "license": "MIT", - "dependencies": { - "@loaders.gl/loader-utils": "4.4.1" - }, - "peerDependencies": { - "@loaders.gl/core": "~4.4.0" - } - }, - "node_modules/@loaders.gl/loader-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@loaders.gl/loader-utils/-/loader-utils-4.4.1.tgz", - "integrity": "sha512-waosL7VtVRfXsNOXtAM3rOjZyNQD0lQBlhuB5/oY+E+lNzYNFlzgiGXiDOwBpcs7dK7kW2Vv8+KcxyIGIyXOtg==", - "license": "MIT", - "dependencies": { - "@loaders.gl/schema": "4.4.1", - "@loaders.gl/worker-utils": "4.4.1", - "@probe.gl/log": "^4.1.1", - "@probe.gl/stats": "^4.1.1" - } - }, - "node_modules/@loaders.gl/schema": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-4.4.1.tgz", - "integrity": "sha512-s7NjEnyK6jZvJJSWj/mHq+S9mHRHVzIYtFP+C7sMf1gVCQbdkt6OSAMUWRzwPr9+whQNVWjZ9pbLsI/IPW3zvw==", - "license": "MIT", - "dependencies": { - "@types/geojson": "^7946.0.7", - "apache-arrow": ">= 17.0.0" - } - }, - "node_modules/@loaders.gl/schema-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@loaders.gl/schema-utils/-/schema-utils-4.4.1.tgz", - "integrity": "sha512-4upip2O6MFaWzk68/lnna7P2uRj9NQ8MIk/ff3CLbciP5/9lKl1qyuzObz5JrJRYzfGB6I81vpOn6FSVQ6m6KQ==", - "license": "MIT", - "dependencies": { - "@loaders.gl/schema": "4.4.1", - "@types/geojson": "^7946.0.7", - "apache-arrow": ">= 17.0.0" - }, - "peerDependencies": { - "@loaders.gl/core": "~4.4.0" - } - }, - "node_modules/@loaders.gl/worker-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@loaders.gl/worker-utils/-/worker-utils-4.4.1.tgz", - "integrity": "sha512-ovMyIyj9dlChuHuD64Bel7Mir2UYlmLqlZ9MMzVxzTTLvaudJoNAXi6Disp0ooxwF62ZqjNXXutaSbS6UDeuIg==", - "license": "MIT", - "peerDependencies": { - "@loaders.gl/core": "~4.4.0" - } - }, - "node_modules/@lucide/svelte": { - "version": "0.561.0", - "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-0.561.0.tgz", - "integrity": "sha512-vofKV2UFVrKE6I4ewKJ3dfCXSV6iP6nWVmiM83MLjsU91EeJcEg7LoWUABLp/aOTxj1HQNbJD1f3g3L0JQgH9A==", - "dev": true, - "license": "ISC", - "peerDependencies": { - "svelte": "^5" - } - }, - "node_modules/@luma.gl/core": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/@luma.gl/core/-/core-9.3.3.tgz", - "integrity": "sha512-jCFm2htvrVpcXIy85TBTF1ROgMfknKnfw2OH+Vydr41hiCFd6nqr79gM3f2uhaNkal0BghFNqF3qDioKiUWtew==", - "license": "MIT", - "dependencies": { - "@math.gl/types": "^4.1.0", - "@probe.gl/env": "^4.1.1", - "@probe.gl/log": "^4.1.1", - "@probe.gl/stats": "^4.1.1", - "@types/offscreencanvas": "^2019.7.3" - } - }, - "node_modules/@luma.gl/engine": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/@luma.gl/engine/-/engine-9.3.3.tgz", - "integrity": "sha512-StmMTzUcUlpKMU3wvWU48A6OQyphptD9zVGBsSkK6iHIBdtBKlOcmqRkyfvRouo8JHtlrnoJDHLVKhxorwhGAg==", - "license": "MIT", - "dependencies": { - "@math.gl/core": "^4.1.0", - "@math.gl/types": "^4.1.0", - "@probe.gl/log": "^4.1.1", - "@probe.gl/stats": "^4.1.1" - }, - "peerDependencies": { - "@luma.gl/core": "~9.3.0", - "@luma.gl/shadertools": "~9.3.0" - } - }, - "node_modules/@luma.gl/shadertools": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/@luma.gl/shadertools/-/shadertools-9.3.3.tgz", - "integrity": "sha512-4ZfG4/Utix951vqyiG/JIx+Eg+GMNwOxgr/07/i0gf7bK1gJZIEQ5BxVcDw4MCQfdoVlGPGzl0cQKbdqBvaCAQ==", - "license": "MIT", - "dependencies": { - "@math.gl/core": "^4.1.0", - "@math.gl/types": "^4.1.0" - }, - "peerDependencies": { - "@luma.gl/core": "~9.3.0" - } - }, - "node_modules/@luma.gl/webgl": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/@luma.gl/webgl/-/webgl-9.3.3.tgz", - "integrity": "sha512-X+aavdP5o6VFHSA0es9gKZTT145jfcFbhKJt/gwJrptnKNoIW4+Y37ZEpCo1AzAnr+FQCxjgcM2kOCpoWMfSVA==", - "license": "MIT", - "dependencies": { - "@math.gl/types": "^4.1.0", - "@probe.gl/env": "^4.1.1" - }, - "peerDependencies": { - "@luma.gl/core": "~9.3.0" - } - }, - "node_modules/@mapbox/jsonlint-lines-primitives": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", - "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mapbox/tiny-sdf": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz", - "integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==", - "license": "BSD-2-Clause" - }, - "node_modules/@mapbox/unitbezier": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", - "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==", - "license": "BSD-2-Clause" - }, - "node_modules/@mapbox/whoots-js": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz", - "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==", - "license": "ISC", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@maplibre/geojson-vt": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.1.0.tgz", - "integrity": "sha512-2eIY4gZxeKIVOZVNkAMb+5NgXhgsMQpOveTQAvnp53LYqHGJZDidk7Ew0Tged9PThidpbS+NFTh0g4zivhPDzQ==", - "license": "ISC", - "dependencies": { - "kdbush": "^4.0.2" - } - }, - "node_modules/@maplibre/maplibre-gl-style-spec": { - "version": "24.8.5", - "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-24.8.5.tgz", - "integrity": "sha512-EzEJmMt6thioRH7GI9LWS7ahXTcAhAPGWCe6oTP2Ps4YnsXOOAfeqx854lZaiDnwURfHmcCKV1mr6oo0i23x6w==", - "license": "ISC", - "dependencies": { - "@mapbox/jsonlint-lines-primitives": "~2.0.2", - "@mapbox/unitbezier": "^0.0.1", - "json-stringify-pretty-compact": "^4.0.0", - "minimist": "^1.2.8", - "quickselect": "^3.0.0", - "tinyqueue": "^3.0.0" - }, - "bin": { - "gl-style-format": "dist/gl-style-format.mjs", - "gl-style-migrate": "dist/gl-style-migrate.mjs", - "gl-style-validate": "dist/gl-style-validate.mjs" - } - }, - "node_modules/@maplibre/mlt": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.9.tgz", - "integrity": "sha512-g/tD8EYJB97udq33ipuJ9a4Q7fcbZnTEnUrgnEc/tLMmEL+zaCbR+X5fkDBO2dgpaAMsLH179qE3UXg2N0Nc/g==", - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "@mapbox/point-geometry": "^1.1.0" - } - }, - "node_modules/@maplibre/mlt/node_modules/@mapbox/point-geometry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", - "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", - "license": "ISC" - }, - "node_modules/@maplibre/vt-pbf": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@maplibre/vt-pbf/-/vt-pbf-4.3.0.tgz", - "integrity": "sha512-jIvp8F5hQCcreqOOpEt42TJMUlsrEcpf/kI1T2v85YrQRV6PPXUcEXUg5karKtH6oh47XJZ4kHu56pUkOuqA7w==", - "license": "MIT", - "dependencies": { - "@mapbox/point-geometry": "^1.1.0", - "@mapbox/vector-tile": "^2.0.4", - "@maplibre/geojson-vt": "^5.0.4", - "@types/geojson": "^7946.0.16", - "@types/supercluster": "^7.1.3", - "pbf": "^4.0.1", - "supercluster": "^8.0.1" - } - }, - "node_modules/@maplibre/vt-pbf/node_modules/@mapbox/point-geometry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", - "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", - "license": "ISC" - }, - "node_modules/@maplibre/vt-pbf/node_modules/@mapbox/vector-tile": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-2.0.4.tgz", - "integrity": "sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg==", - "license": "BSD-3-Clause", - "dependencies": { - "@mapbox/point-geometry": "~1.1.0", - "@types/geojson": "^7946.0.16", - "pbf": "^4.0.1" - } - }, - "node_modules/@maplibre/vt-pbf/node_modules/@maplibre/geojson-vt": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-5.0.4.tgz", - "integrity": "sha512-KGg9sma45S+stfH9vPCJk1J0lSDLWZgCT9Y8u8qWZJyjFlP8MNP1WGTxIMYJZjDvVT3PDn05kN1C95Sut1HpgQ==", - "license": "ISC" - }, - "node_modules/@maplibre/vt-pbf/node_modules/pbf": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz", - "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", - "license": "BSD-3-Clause", - "dependencies": { - "resolve-protobuf-schema": "^2.1.0" - }, - "bin": { - "pbf": "bin/pbf" - } - }, - "node_modules/@math.gl/core": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@math.gl/core/-/core-4.1.0.tgz", - "integrity": "sha512-FrdHBCVG3QdrworwrUSzXIaK+/9OCRLscxI2OUy6sLOHyHgBMyfnEGs99/m3KNvs+95BsnQLWklVfpKfQzfwKA==", - "license": "MIT", - "dependencies": { - "@math.gl/types": "4.1.0" - } - }, - "node_modules/@math.gl/polygon": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@math.gl/polygon/-/polygon-4.1.0.tgz", - "integrity": "sha512-YA/9PzaCRHbIP5/0E9uTYrqe+jsYTQoqoDWhf6/b0Ixz8bPZBaGDEafLg3z7ffBomZLacUty9U3TlPjqMtzPjA==", - "license": "MIT", - "dependencies": { - "@math.gl/core": "4.1.0" - } - }, - "node_modules/@math.gl/sun": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@math.gl/sun/-/sun-4.1.0.tgz", - "integrity": "sha512-i3q6OCBLSZ5wgZVhXg+X7gsjY/TUtuFW/2KBiq/U1ypLso3S4sEykoU/MGjxUv1xiiGtr+v8TeMbO1OBIh/HmA==", - "license": "MIT" - }, - "node_modules/@math.gl/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@math.gl/types/-/types-4.1.0.tgz", - "integrity": "sha512-clYZdHcmRvMzVK5fjeDkQlHUzXQSNdZ7s4xOqC3nJPgz4C/TZkUecTo9YS4PruZqtDda/ag4erndP0MIn40dGA==", - "license": "MIT" - }, - "node_modules/@math.gl/web-mercator": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@math.gl/web-mercator/-/web-mercator-4.1.0.tgz", - "integrity": "sha512-HZo3vO5GCMkXJThxRJ5/QYUYRr3XumfT8CzNNCwoJfinxy5NtKUd7dusNTXn7yJ40UoB8FMIwkVwNlqaiRZZAw==", - "license": "MIT", - "dependencies": { - "@math.gl/core": "4.1.0" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", - "dev": true, - "license": "MIT" - }, - "node_modules/@probe.gl/env": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-4.1.1.tgz", - "integrity": "sha512-+68seNDMVsEegRB47pFA/Ws1Fjy8agcFYXxzorKToyPcD6zd+gZ5uhwoLd7TzsSw6Ydns//2KEszWn+EnNHTbA==", - "license": "MIT" - }, - "node_modules/@probe.gl/log": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-4.1.1.tgz", - "integrity": "sha512-kcZs9BT44pL7hS1OkRGKYRXI/SN9KejUlPD+BY40DguRLzdC5tLG/28WGMyfKdn/51GT4a0p+0P8xvDn1Ez+Kg==", - "license": "MIT", - "dependencies": { - "@probe.gl/env": "4.1.1" - } - }, - "node_modules/@probe.gl/stats": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-4.1.1.tgz", - "integrity": "sha512-4VpAyMHOqydSvPlEyHwXaE+AkIdR03nX+Qhlxsk2D/IW4OVmDZgIsvJB1cDzyEEtcfKcnaEbfXeiPgejBceT6g==", - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz", - "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz", - "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz", - "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz", - "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz", - "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz", - "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz", - "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz", - "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz", - "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz", - "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz", - "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz", - "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz", - "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz", - "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz", - "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz", - "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz", - "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz", - "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz", - "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz", - "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz", - "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz", - "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz", - "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz", - "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz", - "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sveltejs/acorn-typescript": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.10.tgz", - "integrity": "sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==", - "license": "MIT", - "peerDependencies": { - "acorn": "^8.9.0" - } - }, - "node_modules/@sveltejs/adapter-static": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.10.tgz", - "integrity": "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@sveltejs/kit": "^2.0.0" - } - }, - "node_modules/@sveltejs/kit": { - "version": "2.62.0", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.62.0.tgz", - "integrity": "sha512-4JlkXGRJ3kW15dL4LCHV3Mu5aSTTtmH8EBNE4QjJl+KLY77dClgAsZg8aebpwFcDXemNP1z9az8EatD2UNWAcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@sveltejs/acorn-typescript": "^1.0.9", - "@types/cookie": "^0.6.0", - "acorn": "^8.16.0", - "cookie": "^0.6.0", - "devalue": "^5.8.1", - "esm-env": "^1.2.2", - "kleur": "^4.1.5", - "magic-string": "^0.30.5", - "mrmime": "^2.0.0", - "set-cookie-parser": "^3.0.0", - "sirv": "^3.0.0" - }, - "bin": { - "svelte-kit": "svelte-kit.js" - }, - "engines": { - "node": ">=18.13" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0", - "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", - "svelte": "^4.0.0 || ^5.0.0-next.0", - "typescript": "^5.3.3 || ^6.0.0", - "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.4.tgz", - "integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", - "deepmerge": "^4.3.1", - "magic-string": "^0.30.21", - "obug": "^2.1.0", - "vitefu": "^1.1.1" - }, - "engines": { - "node": "^20.19 || ^22.12 || >=24" - }, - "peerDependencies": { - "svelte": "^5.0.0", - "vite": "^6.3.0 || ^7.0.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.2.tgz", - "integrity": "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "obug": "^2.1.0" - }, - "engines": { - "node": "^20.19 || ^22.12 || >=24" - }, - "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", - "svelte": "^5.0.0", - "vite": "^6.3.0 || ^7.0.0" - } - }, - "node_modules/@swc/helpers": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.21.tgz", - "integrity": "sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@tailwindcss/node": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", - "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.21.0", - "jiti": "^2.6.1", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.3.0" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz", - "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.0", - "@tailwindcss/oxide-darwin-arm64": "4.3.0", - "@tailwindcss/oxide-darwin-x64": "4.3.0", - "@tailwindcss/oxide-freebsd-x64": "4.3.0", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", - "@tailwindcss/oxide-linux-x64-musl": "4.3.0", - "@tailwindcss/oxide-wasm32-wasi": "4.3.0", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz", - "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz", - "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz", - "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz", - "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz", - "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz", - "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz", - "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz", - "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz", - "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz", - "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.10.0", - "@emnapi/runtime": "^1.10.0", - "@emnapi/wasi-threads": "^1.2.1", - "@napi-rs/wasm-runtime": "^1.1.4", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.10.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.10.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.1", - "dev": true, - "inBundle": true, - "license": "0BSD", - "optional": true - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz", - "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz", - "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/typography": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz", - "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==", - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "6.0.10" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" - } - }, - "node_modules/@tailwindcss/vite": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.0.tgz", - "integrity": "sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tailwindcss/node": "4.3.0", - "@tailwindcss/oxide": "4.3.0", - "tailwindcss": "4.3.0" - }, - "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7 || ^8" - } - }, - "node_modules/@tanstack/svelte-table": { - "version": "9.0.0-alpha.10", - "resolved": "https://registry.npmjs.org/@tanstack/svelte-table/-/svelte-table-9.0.0-alpha.10.tgz", - "integrity": "sha512-H0eAQlpXgK9JYYrgc0cWXVqEJywxkhuYODnVobUZGskFg6J+5PP+7UCjzrY9ftMge6s1hwb2Ipq3u4wPYJz7HA==", - "license": "MIT", - "dependencies": { - "@tanstack/table-core": "9.0.0-alpha.10" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "svelte": "^5.0.0-next" - } - }, - "node_modules/@tanstack/svelte-table/node_modules/@tanstack/table-core": { - "version": "9.0.0-alpha.10", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-9.0.0-alpha.10.tgz", - "integrity": "sha512-f2kEGGL+d+I7evkhU926cID2MyH7nPI8acAPcwpaAR1DrgTNStAMp3NS+tgMDyrYtc8zd+RyTxC8m+NBhHhFmA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/table-core": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", - "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@types/command-line-args": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.3.tgz", - "integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==", - "license": "MIT" - }, - "node_modules/@types/command-line-usage": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.4.tgz", - "integrity": "sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==", - "license": "MIT" - }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", - "license": "MIT" - }, - "node_modules/@types/geojson": { - "version": "7946.0.16", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", - "license": "MIT" - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "25.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", - "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": ">=7.24.0 <7.24.7" - } - }, - "node_modules/@types/offscreencanvas": { - "version": "2019.7.3", - "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz", - "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==", - "license": "MIT" - }, - "node_modules/@types/supercluster": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz", - "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", - "license": "MIT", - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT" - }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/apache-arrow": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-21.1.0.tgz", - "integrity": "sha512-kQrYLxhC+NTVVZ4CCzGF6L/uPVOzJmD1T3XgbiUnP7oTeVFOFgEUu6IKNwCDkpFoBVqDKQivlX4RUFqqnWFlEA==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.11", - "@types/command-line-args": "^5.2.3", - "@types/command-line-usage": "^5.0.4", - "@types/node": "^24.0.3", - "command-line-args": "^6.0.1", - "command-line-usage": "^7.0.1", - "flatbuffers": "^25.1.24", - "json-bignum": "^0.0.3", - "tslib": "^2.6.2" - }, - "bin": { - "arrow2csv": "bin/arrow2csv.js" - } - }, - "node_modules/apache-arrow/node_modules/@types/node": { - "version": "24.12.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.4.tgz", - "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/apache-arrow/node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", - "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-back": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.3.tgz", - "integrity": "sha512-SGDvmg6QTYiTxCBkYVmThcoa67uLl35pyzRHdpCGBOcqFy6BtwnphoFPk7LhJshD+Yk1Kt35WGWeZPTgwR4Fhw==", - "license": "MIT", - "engines": { - "node": ">=12.17" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/bits-ui": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-2.18.1.tgz", - "integrity": "sha512-KkemzKFH4T3gt3H+P86JcnAWExjByv/6vlwjm/BoCwTPHu03yiCdxbghdJLvFReQTe0acCAiRcKfmixxD6XvlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.1", - "@floating-ui/dom": "^1.7.1", - "esm-env": "^1.1.2", - "runed": "^0.35.1", - "svelte-toolbelt": "^0.10.6", - "tabbable": "^6.2.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/huntabyte" - }, - "peerDependencies": { - "@internationalized/date": "^3.8.1", - "svelte": "^5.33.0" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/command-line-args": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.2.tgz", - "integrity": "sha512-AIjYVxrV9X752LmPDLbVYv8aMCuHPSLZJXEo2qo/xJfv+NYhaZ4sMSF01rM+gHPaMgvPM0l5D/F+Qx+i2WfSmQ==", - "license": "MIT", - "dependencies": { - "array-back": "^6.2.3", - "find-replace": "^5.0.2", - "lodash.camelcase": "^4.3.0", - "typical": "^7.3.0" - }, - "engines": { - "node": ">=12.20" - }, - "peerDependencies": { - "@75lb/nature": "latest" - }, - "peerDependenciesMeta": { - "@75lb/nature": { - "optional": true - } - } - }, - "node_modules/command-line-usage": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.4.tgz", - "integrity": "sha512-85UdvzTNx/+s5CkSgBm/0hzP80RFHAa7PsfeADE5ezZF3uHz3/Tqj9gIKGT9PTtpycc3Ua64T0oVulGfKxzfqg==", - "license": "MIT", - "dependencies": { - "array-back": "^6.2.2", - "chalk-template": "^0.4.0", - "table-layout": "^4.1.1", - "typical": "^7.3.0" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/devalue": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.1.tgz", - "integrity": "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==", - "license": "MIT" - }, - "node_modules/dompurify": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.7.tgz", - "integrity": "sha512-2jBxDJY4RR06tQNy4w5FlFH7kfxsQZlufd0sbv+chfHCxeJwrFw2baUDsSwvBISD4K4RDbd0PTfy3uNXsR6siA==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, - "node_modules/earcut": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", - "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", - "license": "ISC" - }, - "node_modules/elkjs": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.11.1.tgz", - "integrity": "sha512-zxxR9k+rx5ktMwT/FwyLdPCrq7xN6e4VGGHH8hA01vVYKjTFik7nHOxBnAYtrgYUB1RpAiLvA1/U2YraWxyKKg==", - "license": "EPL-2.0" - }, - "node_modules/enhanced-resolve": { - "version": "5.21.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz", - "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" - } - }, - "node_modules/esm-env": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", - "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", - "license": "MIT" - }, - "node_modules/esrap": { - "version": "2.2.11", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.11.tgz", - "integrity": "sha512-gPdx+I+BjYEinNMQaBXFjbaJVyoPMU4ZODg5mE+M4DqVG9VusAVHHjcBX+zqyITlI0DIARwDMMzZwAWj36dRoQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "peerDependencies": { - "@typescript-eslint/types": "^8.2.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/types": { - "optional": true - } - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/find-replace": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz", - "integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==", - "license": "MIT", - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@75lb/nature": "latest" - }, - "peerDependenciesMeta": { - "@75lb/nature": { - "optional": true - } - } - }, - "node_modules/flatbuffers": { - "version": "25.9.23", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", - "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", - "license": "Apache-2.0" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gl-matrix": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", - "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", - "license": "MIT" - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/gridstack": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/gridstack/-/gridstack-12.6.0.tgz", - "integrity": "sha512-dUrqsormSybFn/2P4Dz8AgprftKD5e/IiV7UmC0XLQU+G+/WtkAeFiCSNLoAGhPDXoJ/O61Xtj3gljY/Ds83yQ==", - "funding": [ - { - "type": "paypal", - "url": "https://www.paypal.me/alaind831" - }, - { - "type": "venmo", - "url": "https://www.venmo.com/adumesny" - } - ], - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/inline-style-parser": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", - "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", - "license": "MIT" - }, - "node_modules/is-reference": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", - "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.6" - } - }, - "node_modules/jiti": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-bignum": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz", - "integrity": "sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/json-stringify-pretty-compact": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", - "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==", - "license": "MIT" - }, - "node_modules/kdbush": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", - "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==", - "license": "ISC" - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/locate-character": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", - "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", - "license": "MIT" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "license": "MIT" - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true, - "license": "MIT", - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/maplibre-gl": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.24.0.tgz", - "integrity": "sha512-ALyFxgtd5R+65UqZ/++lOqwWcC0SNho9c27fYSyLmG7AfnAul2o46F05aDJGPbFU57wos9dgcIySHs0Xe6ia3A==", - "license": "BSD-3-Clause", - "dependencies": { - "@mapbox/jsonlint-lines-primitives": "^2.0.2", - "@mapbox/point-geometry": "^1.1.0", - "@mapbox/tiny-sdf": "^2.1.0", - "@mapbox/unitbezier": "^0.0.1", - "@mapbox/vector-tile": "^2.0.4", - "@mapbox/whoots-js": "^3.1.0", - "@maplibre/geojson-vt": "^6.1.0", - "@maplibre/maplibre-gl-style-spec": "^24.8.1", - "@maplibre/mlt": "^1.1.8", - "@maplibre/vt-pbf": "^4.3.0", - "@types/geojson": "^7946.0.16", - "earcut": "^3.0.2", - "gl-matrix": "^3.4.4", - "kdbush": "^4.0.2", - "murmurhash-js": "^1.0.0", - "pbf": "^4.0.1", - "potpack": "^2.1.0", - "quickselect": "^3.0.0", - "tinyqueue": "^3.0.0" - }, - "engines": { - "node": ">=16.14.0", - "npm": ">=8.1.0" - }, - "funding": { - "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" - } - }, - "node_modules/maplibre-gl/node_modules/@mapbox/point-geometry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", - "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", - "license": "ISC" - }, - "node_modules/maplibre-gl/node_modules/@mapbox/vector-tile": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-2.0.4.tgz", - "integrity": "sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg==", - "license": "BSD-3-Clause", - "dependencies": { - "@mapbox/point-geometry": "~1.1.0", - "@types/geojson": "^7946.0.16", - "pbf": "^4.0.1" - } - }, - "node_modules/maplibre-gl/node_modules/earcut": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", - "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==", - "license": "ISC" - }, - "node_modules/maplibre-gl/node_modules/pbf": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz", - "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", - "license": "BSD-3-Clause", - "dependencies": { - "resolve-protobuf-schema": "^2.1.0" - }, - "bin": { - "pbf": "bin/pbf" - } - }, - "node_modules/marked": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.4.tgz", - "integrity": "sha512-c/BTaKzg0G6ezQx97DAkYU7k0HM6ys0FqYeKBL6hlBByZwy+ycA1+f0vDdjMHKKeEjdgkx0GOv9Il6D+85cOqA==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mjolnir.js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mjolnir.js/-/mjolnir.js-3.0.0.tgz", - "integrity": "sha512-siX3YCG7N2HnmN1xMH3cK4JkUZJhbkhRFJL+G5N1vH0mh1t5088rJknIoqDFWDIU6NPGvRRgLnYW3ZHjSMEBLA==", - "license": "MIT" - }, - "node_modules/mode-watcher": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-1.1.0.tgz", - "integrity": "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g==", - "license": "MIT", - "dependencies": { - "runed": "^0.25.0", - "svelte-toolbelt": "^0.7.1" - }, - "peerDependencies": { - "svelte": "^5.27.0" - } - }, - "node_modules/mode-watcher/node_modules/runed": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.25.0.tgz", - "integrity": "sha512-7+ma4AG9FT2sWQEA0Egf6mb7PBT2vHyuHail1ie8ropfSjvZGtEAx8YTmUjv/APCsdRRxEVvArNjALk9zFSOrg==", - "funding": [ - "https://github.com/sponsors/huntabyte", - "https://github.com/sponsors/tglide" - ], - "dependencies": { - "esm-env": "^1.0.0" - }, - "peerDependencies": { - "svelte": "^5.7.0" - } - }, - "node_modules/mode-watcher/node_modules/svelte-toolbelt": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.7.1.tgz", - "integrity": "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ==", - "funding": [ - "https://github.com/sponsors/huntabyte" - ], - "dependencies": { - "clsx": "^2.1.1", - "runed": "^0.23.2", - "style-to-object": "^1.0.8" - }, - "engines": { - "node": ">=18", - "pnpm": ">=8.7.0" - }, - "peerDependencies": { - "svelte": "^5.0.0" - } - }, - "node_modules/mode-watcher/node_modules/svelte-toolbelt/node_modules/runed": { - "version": "0.23.4", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.23.4.tgz", - "integrity": "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA==", - "funding": [ - "https://github.com/sponsors/huntabyte", - "https://github.com/sponsors/tglide" - ], - "dependencies": { - "esm-env": "^1.0.0" - }, - "peerDependencies": { - "svelte": "^5.7.0" - } - }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/murmurhash-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", - "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/plotly.js-dist": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/plotly.js-dist/-/plotly.js-dist-3.6.0.tgz", - "integrity": "sha512-2h4MMbY6wBx6qfF7b5sX4S/6lnu/YAi2nHA0SB/OPO/I1jVmC6LfTGXiQcOmuYZTha4CLmtZAh5Iv9ApWMFEBQ==", - "license": "MIT" - }, - "node_modules/postcss": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/potpack": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.1.0.tgz", - "integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==", - "license": "ISC" - }, - "node_modules/protocol-buffers-schema": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz", - "integrity": "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==", - "license": "MIT" - }, - "node_modules/quickselect": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", - "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", - "license": "ISC" - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/resolve-protobuf-schema": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", - "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", - "license": "MIT", - "dependencies": { - "protocol-buffers-schema": "^3.3.1" - } - }, - "node_modules/rollup": { - "version": "4.60.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz", - "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.3", - "@rollup/rollup-android-arm64": "4.60.3", - "@rollup/rollup-darwin-arm64": "4.60.3", - "@rollup/rollup-darwin-x64": "4.60.3", - "@rollup/rollup-freebsd-arm64": "4.60.3", - "@rollup/rollup-freebsd-x64": "4.60.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.3", - "@rollup/rollup-linux-arm-musleabihf": "4.60.3", - "@rollup/rollup-linux-arm64-gnu": "4.60.3", - "@rollup/rollup-linux-arm64-musl": "4.60.3", - "@rollup/rollup-linux-loong64-gnu": "4.60.3", - "@rollup/rollup-linux-loong64-musl": "4.60.3", - "@rollup/rollup-linux-ppc64-gnu": "4.60.3", - "@rollup/rollup-linux-ppc64-musl": "4.60.3", - "@rollup/rollup-linux-riscv64-gnu": "4.60.3", - "@rollup/rollup-linux-riscv64-musl": "4.60.3", - "@rollup/rollup-linux-s390x-gnu": "4.60.3", - "@rollup/rollup-linux-x64-gnu": "4.60.3", - "@rollup/rollup-linux-x64-musl": "4.60.3", - "@rollup/rollup-openbsd-x64": "4.60.3", - "@rollup/rollup-openharmony-arm64": "4.60.3", - "@rollup/rollup-win32-arm64-msvc": "4.60.3", - "@rollup/rollup-win32-ia32-msvc": "4.60.3", - "@rollup/rollup-win32-x64-gnu": "4.60.3", - "@rollup/rollup-win32-x64-msvc": "4.60.3", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/runed": { - "version": "0.35.1", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.35.1.tgz", - "integrity": "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==", - "dev": true, - "funding": [ - "https://github.com/sponsors/huntabyte", - "https://github.com/sponsors/tglide" - ], - "license": "MIT", - "dependencies": { - "dequal": "^2.0.3", - "esm-env": "^1.0.0", - "lz-string": "^1.5.0" - }, - "peerDependencies": { - "@sveltejs/kit": "^2.21.0", - "svelte": "^5.7.0" - }, - "peerDependenciesMeta": { - "@sveltejs/kit": { - "optional": true - } - } - }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/set-cookie-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.0.tgz", - "integrity": "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/sirv": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", - "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/style-to-object": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", - "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.7" - } - }, - "node_modules/supercluster": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", - "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", - "license": "ISC", - "dependencies": { - "kdbush": "^4.0.2" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/svelte": { - "version": "5.56.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.56.1.tgz", - "integrity": "sha512-eArsJmvl3xZVuTYD852PzIEdg2wgDdIZ1NEsIPbzAukHwi284B18No4nK2rCO9AwsWUDza4Cjvmoa4HaojTl5g==", - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "@jridgewell/sourcemap-codec": "^1.5.0", - "@sveltejs/acorn-typescript": "^1.0.10", - "@types/estree": "^1.0.5", - "@types/trusted-types": "^2.0.7", - "acorn": "^8.12.1", - "aria-query": "5.3.1", - "axobject-query": "^4.1.0", - "clsx": "^2.1.1", - "devalue": "^5.8.1", - "esm-env": "^1.2.1", - "esrap": "^2.2.9", - "is-reference": "^3.0.3", - "locate-character": "^3.0.0", - "magic-string": "^0.30.11", - "zimmerframe": "^1.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/svelte-check": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.5.0.tgz", - "integrity": "sha512-9lNwPxCLWniFvQIcEv1LFqjIxcFtO3smb5+5BKbRJ3ttL4o2lXCej5rLF4DAnfLPI66oaA81vAxw6ILdIWI7kA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "chokidar": "^4.0.1", - "fdir": "^6.2.0", - "picocolors": "^1.0.0", - "sade": "^1.7.4" - }, - "bin": { - "svelte-check": "bin/svelte-check" - }, - "engines": { - "node": ">= 18.0.0" - }, - "peerDependencies": { - "svelte": "^4.0.0 || ^5.0.0-next.0", - "typescript": ">=5.0.0" - } - }, - "node_modules/svelte-sonner": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/svelte-sonner/-/svelte-sonner-1.1.1.tgz", - "integrity": "sha512-5cd3p7wa4cq0NsqslMwdlPb7x1JglEZ/GKrLePWNr5bCxR1nagAVrY01FRFrXfUGs41miLt3C327+8XJo5BzZw==", - "license": "MIT", - "dependencies": { - "runed": "^0.28.0" - }, - "peerDependencies": { - "svelte": "^5.0.0" - } - }, - "node_modules/svelte-sonner/node_modules/runed": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.28.0.tgz", - "integrity": "sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ==", - "funding": [ - "https://github.com/sponsors/huntabyte", - "https://github.com/sponsors/tglide" - ], - "license": "MIT", - "dependencies": { - "esm-env": "^1.0.0" - }, - "peerDependencies": { - "svelte": "^5.7.0" - } - }, - "node_modules/svelte-toolbelt": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.10.6.tgz", - "integrity": "sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/huntabyte" - ], - "dependencies": { - "clsx": "^2.1.1", - "runed": "^0.35.1", - "style-to-object": "^1.0.8" - }, - "engines": { - "node": ">=18", - "pnpm": ">=8.7.0" - }, - "peerDependencies": { - "svelte": "^5.30.2" - } - }, - "node_modules/tabbable": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", - "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", - "dev": true, - "license": "MIT" - }, - "node_modules/table-layout": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz", - "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==", - "license": "MIT", - "dependencies": { - "array-back": "^6.2.2", - "wordwrapjs": "^5.1.0" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/tailwind-merge": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", - "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/dcastil" - } - }, - "node_modules/tailwind-variants": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-3.2.2.tgz", - "integrity": "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.x", - "pnpm": ">=7.x" - }, - "peerDependencies": { - "tailwind-merge": ">=3.0.0", - "tailwindcss": "*" - }, - "peerDependenciesMeta": { - "tailwind-merge": { - "optional": true - } - } - }, - "node_modules/tailwindcss": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", - "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyqueue": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", - "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==", - "license": "ISC" - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tw-animate-css": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", - "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Wombosvideo" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typical": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz", - "integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==", - "license": "MIT", - "engines": { - "node": ">=12.17" - } - }, - "node_modules/undici-types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", - "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", - "dev": true, - "license": "MIT" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/vite": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", - "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vitefu": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", - "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", - "dev": true, - "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*", - "tests/projects/workspace/packages/*" - ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "node_modules/wordwrapjs": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.1.tgz", - "integrity": "sha512-0yweIbkINJodk27gX9LBGMzyQdBDan3s/dEAiwBOj+Mf0PPyWL6/rikalkv8EeD0E8jm4o5RXEOrFTP3NXbhJg==", - "license": "MIT", - "engines": { - "node": ">=12.17" - } - }, - "node_modules/zimmerframe": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", - "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", - "license": "MIT" - } - } -} diff --git a/frontend/app/package.json b/frontend/app/package.json deleted file mode 100644 index 558cca2e..00000000 --- a/frontend/app/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.1", - "type": "module", - "engines": { - "node": "22.x", - "npm": ">=10" - }, - "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" - }, - "devDependencies": { - "@internationalized/date": "3.12.2", - "@lucide/svelte": "0.561.0", - "@sveltejs/adapter-static": "3.0.10", - "@sveltejs/kit": "2.62.0", - "@sveltejs/vite-plugin-svelte": "6.2.4", - "@tailwindcss/vite": "4.3.0", - "@tanstack/table-core": "8.21.3", - "@types/js-yaml": "4.0.9", - "@types/node": "25.9.1", - "bits-ui": "2.18.1", - "clsx": "2.1.1", - "svelte": "5.56.1", - "svelte-check": "4.5.0", - "tailwind-merge": "3.6.0", - "tailwind-variants": "3.2.2", - "tailwindcss": "4.3.0", - "tw-animate-css": "1.4.0", - "typescript": "5.9.3", - "vite": "7.3.3" - }, - "dependencies": { - "@deck.gl/core": "9.3.3", - "@deck.gl/layers": "9.3.3", - "@tailwindcss/typography": "0.5.19", - "@tanstack/svelte-table": "9.0.0-alpha.10", - "dompurify": "3.4.7", - "elkjs": "0.11.1", - "gridstack": "12.6.0", - "js-yaml": "4.2.0", - "maplibre-gl": "5.24.0", - "marked": "18.0.4", - "mode-watcher": "1.1.0", - "plotly.js-dist": "3.6.0", - "svelte-sonner": "1.1.1" - } -} diff --git a/frontend/app/src/app.css b/frontend/app/src/app.css deleted file mode 100644 index 12a8b11b..00000000 --- a/frontend/app/src/app.css +++ /dev/null @@ -1,165 +0,0 @@ -@import "tailwindcss" source(none); -@plugin "@tailwindcss/typography"; - -@source "./routes"; -@source "./lib"; - -@import "tw-animate-css"; - - -@custom-variant dark (&:is(.dark *)); - -:root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --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: #098754; - --primary-foreground: oklch(1 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.85 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --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); - --hover-light: #e4e4e7; - --hover-dark: #3f3f46; -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --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: #098754; - --primary-foreground: oklch(1 0 0); - --secondary: oklch(0.269 0 0); - --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: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --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.439 0 0); - --hover-light: #e4e4e7; - --hover-dark: #3f3f46; -} - -@theme inline { - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --color-hover-light: var(--hover-light); - --color-hover-dark: var(--hover-dark); - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } -} - -/* Tag color classes */ -.tag-model { - background-color: #D10A49; - color: white; -} -.tag-model:hover { - background-color: #B00940; -} - -.tag-version { - background-color: #504078; - color: white; -} -.tag-version:hover { - background-color: #423462; -} - -.tag-config { - background-color: #2993B5; - color: white; -} -.tag-config:hover { - background-color: #237A9A; -} - -.tag-default { - background-color: var(--primary); - color: white; -} -.tag-default:hover { - opacity: 0.9; -} diff --git a/frontend/app/src/app.d.ts b/frontend/app/src/app.d.ts deleted file mode 100644 index da08e6da..00000000 --- a/frontend/app/src/app.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -// 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 {} - } -} - -export {}; diff --git a/frontend/app/src/app.html b/frontend/app/src/app.html deleted file mode 100644 index 1a64aa6c..00000000 --- a/frontend/app/src/app.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - %sveltekit.head% - - -
%sveltekit.body%
- - diff --git a/frontend/app/src/hooks.server.ts b/frontend/app/src/hooks.server.ts deleted file mode 100644 index 83fc3775..00000000 --- a/frontend/app/src/hooks.server.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { Handle } from '@sveltejs/kit'; -import { env } from '$env/dynamic/private'; - -const API_BASE_URL = env.BACKEND_URL || 'http://localhost:8000'; - -export const handle: Handle = async ({ event, resolve }) => { - // Proxy /api requests to the backend - if (event.url.pathname.startsWith('/api')) { - const targetUrl = `${API_BASE_URL}${event.url.pathname}${event.url.search}`; - - try { - const response = await fetch(targetUrl, { - method: event.request.method, - headers: event.request.headers, - body: event.request.method !== 'GET' && event.request.method !== 'HEAD' - ? await event.request.text() - : undefined - }); - - // Create a new response with the proxied content - const responseBody = await response.text(); - - const headers: Record = { - 'content-type': response.headers.get('content-type') || 'application/json', - 'cache-control': response.headers.get('cache-control') || 'no-cache', - }; - const setCookie = response.headers.get('set-cookie'); - if (setCookie) headers['set-cookie'] = setCookie; - - return new Response(responseBody, { - status: response.status, - statusText: response.statusText, - headers - }); - } catch (error) { - console.error('API proxy error:', error); - return new Response( - JSON.stringify({ - detail: `Failed to connect to backend: ${(error as Error).message}` - }), - { - status: 502, - headers: { 'content-type': 'application/json' } - } - ); - } - } - - // For non-API requests, proceed as normal - return resolve(event); -}; diff --git a/frontend/app/src/lib/api/client.ts b/frontend/app/src/lib/api/client.ts deleted file mode 100644 index f43d23cc..00000000 --- a/frontend/app/src/lib/api/client.ts +++ /dev/null @@ -1,629 +0,0 @@ -import type { - User, - Network, - Run, - RunSummary, - Backend, - BackendPublic, - TaskStatus, - PlotResponse, - PlotData, - VersionInfo, - HealthStatus, - ApiError, - ApiKey, - NetworkUpdate, - NetworkListMeta, - RunListMeta, - OutputFile, - Visibility, - PaginatedResponse, - Workflow, - PublicRunResponse, - ComponentDataResponse, - UserStatsResponse, -} from "$lib/types.js"; -import type { ReportState } from "$lib/stores/reportStore.svelte.js"; - -const API_BASE = '/api/v1'; - -// Track active requests to enable cancellation -const activeControllers = new Map(); - -async function request(endpoint: string, options: RequestInit = {}, cancellationKey: string | null = null): Promise { - const url = `${API_BASE}${endpoint}`; - - // Handle request cancellation - const controller = new AbortController(); - if (cancellationKey) { - // Cancel any previous request with the same key - if (activeControllers.has(cancellationKey)) { - activeControllers.get(cancellationKey)!.abort(); - } - activeControllers.set(cancellationKey, controller); - } - - const { headers: optHeaders, ...restOptions } = options; - const headers: Record = options.body instanceof FormData - ? { 'Accept': 'application/json', ...(optHeaders as Record) } - : { 'Accept': 'application/json', 'Content-Type': 'application/json', ...(optHeaders as Record) }; - - const config: RequestInit = { - ...restOptions, - headers, - credentials: 'include', - signal: controller.signal, - }; - - try { - const response = await fetch(url, config); - - if (!response.ok) { - const error = await response.json().catch(() => ({ detail: response.statusText })); - const detail = error.detail; - let message: string; - if (typeof detail === 'string') { - message = detail; - } else if (Array.isArray(detail)) { - message = detail - .map((d) => (typeof d === 'string' ? d : d?.msg ? `${(d.loc ?? []).join('.')}: ${d.msg}` : JSON.stringify(d))) - .join('; '); - } else if (detail) { - message = JSON.stringify(detail); - } else { - message = `HTTP ${response.status}: ${response.statusText}`; - } - const err: ApiError = new Error(message); - err.status = response.status; - - // 401 = auth required, redirect to login (skip for auth endpoints themselves) - if (response.status === 401 && !endpoint.includes('/auth/')) { - if (typeof window !== 'undefined' && !window.location.pathname.startsWith('/login')) { - window.location.href = '/login'; - } - } - - throw err; - } - - if (response.status === 204) { - return undefined as T; - } - return await response.json(); - } catch (error) { - if (error instanceof Error && error.name === 'AbortError') { - const cancelError: ApiError = new Error('Request cancelled'); - cancelError.cancelled = true; - throw cancelError; - } - console.error('API request failed:', error); - throw error; - } finally { - // Clean up the controller - if (cancellationKey && activeControllers.get(cancellationKey) === controller) { - activeControllers.delete(cancellationKey); - } - } -} - -// Auth API -export interface AuthProviderInfo { - id: string; - name: string; - type: string; - login_url?: string; - icon?: string; -} - -export const auth = { - async me(): Promise { - return request('/auth/me'); - }, - async providers(): Promise<{ providers: AuthProviderInfo[] }> { - return request<{ providers: AuthProviderInfo[] }>('/auth/providers'); - }, - async passwordLogin(email: string, password: string): Promise { - return request('/auth/login/password', { - method: 'POST', - body: JSON.stringify({ email, password }), - }); - }, - logout(): void { - window.location.href = '/api/v1/auth/logout'; - } -}; - -// Networks API -export const networks = { - async list( - skip = 0, - limit = 100, - options: { sort_by?: string; sort_dir?: string; filter_q?: string } = {} - ): Promise> { - const params = new URLSearchParams({ offset: String(skip), limit: String(limit) }); - if (options.sort_by) params.set('sort_by', options.sort_by); - if (options.sort_dir) params.set('sort_dir', options.sort_dir); - if (options.filter_q) params.set('filter_q', options.filter_q); - return request>(`/networks/?${params}`); - }, - async get(id: string): Promise { - return request(`/networks/${id}`, {}, `network-${id}`); - }, - async getSummary(id: string): Promise> { - return request>(`/networks/${id}/summary`, {}, `network-summary-${id}`); - }, - async upload(file: File): Promise<{ task_id: string }> { - const formData = new FormData(); - formData.append('file', file); - return request<{ task_id: string }>('/networks/', { method: 'POST', body: formData }); - }, - async fromUrl(url: string): Promise<{ task_id: string }> { - return request<{ task_id: string }>('/networks/from-url', { - method: 'POST', - body: JSON.stringify({ url }), - }); - }, - async registerPath(absolutePath: string): Promise { - return request('/networks/register-path', { - method: 'POST', - body: JSON.stringify({ absolute_path: absolutePath }), - }); - }, - async pollImport(taskId: string, timeoutMs = 15 * 60_000): Promise<{ network_id: string; filename?: string; size?: number }> { - const start = Date.now(); - let delay = 200; - while (Date.now() - start < timeoutMs) { - await new Promise(r => setTimeout(r, delay)); - const status = await request(`/tasks/status/${taskId}`); - if (status.state === 'SUCCESS' && status.result) { - if (status.result.status === 'error') { - throw new Error(status.result.error || 'Network import failed'); - } - return status.result.data as unknown as { network_id: string; filename?: string; size?: number }; - } - if (status.state === 'FAILURE') { - throw new Error(status.error || 'Network import failed'); - } - delay = Math.min(delay * 1.5, 2000); - } - throw new Error('Network import timed out'); - }, - async reset(): Promise { - return request('/networks/reset', { method: 'DELETE' }); - }, - async delete(id: string, removeFile = false): Promise { - const qs = removeFile ? '?remove_file=true' : ''; - return request(`/networks/${id}${qs}`, { method: 'DELETE' }); - }, - async updateVisibility(id: string, visibility: Visibility): Promise { - return request(`/networks/${id}`, { - method: 'PATCH', - body: JSON.stringify({ visibility }) - }); - }, - async getReports(networkId: string): Promise { - return request(`/networks/${networkId}/reports`); - }, - async saveReports(networkId: string, state: ReportState): Promise { - await request(`/networks/${networkId}/reports`, { - method: 'PUT', - body: JSON.stringify(state), - }); - }, - async getComponentData( - networkId: string, - component: string, - options: { offset?: number; limit?: number; sort_by?: string; sort_dir?: string; search?: string } = {} - ): Promise { - const params = new URLSearchParams(); - if (options.offset !== undefined) params.set('offset', String(options.offset)); - if (options.limit !== undefined) params.set('limit', String(options.limit)); - if (options.sort_by) params.set('sort_by', options.sort_by); - if (options.sort_dir) params.set('sort_dir', options.sort_dir); - if (options.search) params.set('search', options.search); - const qs = params.toString(); - return request( - `/networks/${networkId}/components/${encodeURIComponent(component)}${qs ? `?${qs}` : ''}`, - {}, - `component-data-${networkId}-${component}` - ); - } -}; - -// Statistics API -export const statistics = { - async get(networkIds: string | string[], statistic: string, parameters: Record = {}): Promise> { - // Ensure networkIds is always an array - const idsArray = Array.isArray(networkIds) ? networkIds : [networkIds]; - const cacheKey = idsArray.length === 1 ? idsArray[0] : idsArray.sort().join(','); - - return request>('/statistics/', { - method: 'POST', - body: JSON.stringify({ - network_ids: idsArray, - statistic, - parameters - }) - }, `statistics-${cacheKey}-${statistic}`); - } -}; - -// Plots API -export const plots = { - async generate(networkIds: string | string[], statistic: string, plotType: string, parameters: Record = {}): Promise { - // Ensure networkIds is always an array - const idsArray = Array.isArray(networkIds) ? networkIds : [networkIds]; - const cacheKey = idsArray.length === 1 ? idsArray[0] : idsArray.sort().join(','); - - // Include parameters in cancellation key to ensure unique requests are properly cancelled - const paramsKey = JSON.stringify(parameters); - - const response = await request<{ task_id?: string; plot_data?: PlotData; cached?: boolean; generated_at?: string; statistic?: string; plot_type?: string }>('/plots/generate', { - method: 'POST', - body: JSON.stringify({ - network_ids: idsArray, - statistic, - plot_type: plotType, - parameters - }) - }, `plot-${cacheKey}-${statistic}-${plotType}-${paramsKey}`); - - // Check if response is cached (synchronous) or async (task-based) - if (response.task_id) { - // Async response - poll for results - return await this.pollTaskStatus(response.task_id); - } else { - // Cached response - return immediately - return response as PlotResponse; - } - }, - - async getStatus(taskId: string): Promise { - return request(`/tasks/status/${taskId}`); - }, - - async generateExplore( - networkId: string, - options: { - bus_carrier?: string[]; - query?: string; - branch_components?: string[]; - geometry?: boolean; - } = {} - ): Promise> { - const paramsKey = JSON.stringify(options); - - const response = await request<{ task_id?: string; data?: Record }>('/plots/explore', { - method: 'POST', - body: JSON.stringify({ - network_id: networkId, - ...options, - }) - }, `explore-${networkId}-${paramsKey}`); - - if (response.task_id) { - const result = await this.pollTaskStatus(response.task_id); - return result.plot_data as unknown as Record; - } - return response.data ?? response as unknown as Record; - }, - - async pollTaskStatus(taskId: string, maxAttempts = 30, timeoutMs = 120_000): Promise { - let attempts = 0; - let delay = 200; // Start with 200ms - const deadline = Date.now() + timeoutMs; - - while (attempts < maxAttempts && Date.now() < deadline) { - const status = await this.getStatus(taskId); - - if (status.state === 'SUCCESS' && status.result) { - // Check if the result contains an error (task succeeded but operation failed) - if (status.result.status === 'error') { - // Create detailed error message - let errorMessage = status.result.error || 'Plot generation failed'; - - // Include error details if available (stack trace + parameters) - if (status.result.error_details) { - const details = status.result.error_details; - errorMessage += '\n\nParameters:\n' + JSON.stringify(details.parameters, null, 2); - - if (details.stack_trace) { - errorMessage += '\n\nStack Trace:\n' + details.stack_trace; - } - } - - throw new Error(errorMessage); - } - - return { - plot_data: status.result.data!, - cached: false, - generated_at: status.result.generated_at, - statistic: status.result.request?.statistic, - plot_type: status.result.request?.plot_type - }; - } else if (status.state === 'FAILURE') { - throw new Error(status.error || 'Plot generation failed'); - } - - await new Promise(resolve => setTimeout(resolve, delay)); - // Exponential backoff with max 2 seconds - delay = Math.min(delay * 1.5, 2000); - attempts++; - } - - throw new Error('Plot generation timed out'); - } - -}; - -// Runs API -export const runs = { - async list( - skip = 0, - limit = 100, - options: { sort_by?: string; sort_dir?: string; filter_q?: string } = {} - ): Promise> { - const params = new URLSearchParams({ offset: String(skip), limit: String(limit) }); - if (options.sort_by) params.set('sort_by', options.sort_by); - if (options.sort_dir) params.set('sort_dir', options.sort_dir); - if (options.filter_q) params.set('filter_q', options.filter_q); - return request>(`/runs/?${params}`); - }, - async get(id: string): Promise { - return request(`/runs/${id}`, {}, `run-${id}`); - }, - async cancel(id: string): Promise { - return request(`/runs/${id}/cancel`, { method: 'POST' }); - }, - async backends(): Promise { - return request('/runs/backends'); - }, - async create(body: { - workflow: string; - git_ref?: string; - configfile?: string; - snakemake_args?: string[]; - extra_files?: Record; - cache?: { key: string; dirs: string[] }; - import_networks?: string[]; - backend_id?: string; - visibility?: Visibility; - callback_url?: string; - }): Promise { - return request('/runs/', { method: 'POST', body: JSON.stringify(body) }); - }, - async rerun(run: Run): Promise { - return this.create({ - workflow: run.workflow, - configfile: run.configfile ?? undefined, - snakemake_args: run.snakemake_args ?? undefined, - extra_files: run.extra_files ?? undefined, - cache: run.cache ?? undefined, - import_networks: run.import_networks ?? undefined, - backend_id: run.backend.id - }); - }, - async remove(id: string): Promise { - return request(`/runs/${id}`, { method: 'DELETE' }); - }, - async updateVisibility(id: string, visibility: Visibility): Promise { - return request(`/runs/${id}`, { - method: 'PATCH', - body: JSON.stringify({ visibility }) - }); - }, - logsUrl(id: string): string { - return `${API_BASE}/runs/${id}/logs`; - }, - async listOutputs(id: string): Promise { - return request(`/runs/${id}/outputs`); - }, - outputDownloadUrl(id: string, path: string): string { - const encoded = path.split('/').map(encodeURIComponent).join('/'); - return `${API_BASE}/runs/${id}/outputs/${encoded}`; - }, - async workflow(id: string): Promise { - return request(`/runs/${id}/workflow`, {}, `run-workflow-${id}`); - } -}; - -// Cache API -export const cache = { - async clearNetwork(networkId: string): Promise { - return request(`/cache/${networkId}`, { method: 'DELETE' }); - }, - async clearAll(): Promise { - return request('/cache/', { method: 'DELETE' }); - } -}; - -// Version API -export const version = { - async get(): Promise { - return request('/version/'); - } -}; - -// Health check -export const health = { - async check(): Promise { - // Health endpoint is outside /api/v1 - const url = '/health'; - const response = await fetch(url); - if (!response.ok) { - throw new Error(`HTTP ${response.status}: ${response.statusText}`); - } - return await response.json(); - } -}; - -// Admin API -export const admin = { - async listUsers( - skip = 0, - limit = 100, - options: { sort_by?: string; sort_dir?: string; filter_q?: string } = {} - ): Promise> { - const params = new URLSearchParams({ offset: String(skip), limit: String(limit) }); - if (options.sort_by) params.set('sort_by', options.sort_by); - if (options.sort_dir) params.set('sort_dir', options.sort_dir); - if (options.filter_q) params.set('filter_q', options.filter_q); - return request>(`/admin/users?${params}`); - }, - - async approveUser(userId: string): Promise { - return request(`/admin/users/${userId}/approve`, { method: 'POST' }); - }, - - async updateUserRole(userId: string, role: string): Promise { - return request(`/admin/users/${userId}/role`, { - method: 'PATCH', - body: JSON.stringify({ role }) - }); - }, - - async createUser(username: string, role: string = 'bot', avatarUrl?: string): Promise { - return request('/admin/users', { - method: 'POST', - body: JSON.stringify({ username, role, avatar_url: avatarUrl || null }) - }); - }, - - async deleteUser(userId: string): Promise { - return request(`/admin/users/${userId}`, { method: 'DELETE' }); - }, - - async listNetworks( - skip = 0, - limit = 100, - options: { sort_by?: string; sort_dir?: string; filter_q?: string } = {} - ): Promise> { - const params = new URLSearchParams({ offset: String(skip), limit: String(limit) }); - if (options.sort_by) params.set('sort_by', options.sort_by); - if (options.sort_dir) params.set('sort_dir', options.sort_dir); - if (options.filter_q) params.set('filter_q', options.filter_q); - return request>(`/admin/networks?${params}`); - }, - - async updateNetwork(networkId: string, updates: NetworkUpdate): Promise { - return request(`/admin/networks/${networkId}`, { - method: 'PATCH', - body: JSON.stringify(updates) - }); - }, - - async deleteNetwork(networkId: string, removeFile = false): Promise { - const qs = removeFile ? '?remove_file=true' : ''; - return request(`/admin/networks/${networkId}${qs}`, { method: 'DELETE' }); - }, - - async listRuns( - skip = 0, - limit = 100, - options: { sort_by?: string; sort_dir?: string; filter_q?: string } = {} - ): Promise> { - const params = new URLSearchParams({ offset: String(skip), limit: String(limit) }); - if (options.sort_by) params.set('sort_by', options.sort_by); - if (options.sort_dir) params.set('sort_dir', options.sort_dir); - if (options.filter_q) params.set('filter_q', options.filter_q); - return request>(`/admin/runs?${params}`); - }, - - async updateRun(runId: string, updates: { visibility?: Visibility; user_id?: string }): Promise { - return request(`/admin/runs/${runId}`, { - method: 'PATCH', - body: JSON.stringify(updates) - }); - }, - - async deleteRun(runId: string): Promise { - return request(`/admin/runs/${runId}`, { method: 'DELETE' }); - }, - - async getPermissions(): Promise> { - return request>('/admin/permissions'); - }, - - async listBackends(): Promise { - return request('/admin/backends'); - }, - - async getBackend(backendId: string): Promise { - return request(`/admin/backends/${backendId}`); - }, - - async listBackendUsers(backendId: string): Promise { - return request(`/admin/backends/${backendId}/users`); - }, - - async assignUserToBackend(backendId: string, userId: string): Promise { - return request(`/admin/backends/${backendId}/users`, { - method: 'POST', - body: JSON.stringify({ user_id: userId }) - }); - }, - - async unassignUserFromBackend(backendId: string, userId: string): Promise { - return request(`/admin/backends/${backendId}/users/${userId}`, { method: 'DELETE' }); - }, - - async getUser(userId: string): Promise { - return request(`/admin/users/${userId}`); - }, - - async listUserBackends(userId: string): Promise { - return request(`/admin/users/${userId}/backends`); - }, - - async assignBackendToUser(userId: string, backendId: string): Promise { - return request(`/admin/users/${userId}/backends`, { - method: 'POST', - body: JSON.stringify({ backend_id: backendId }) - }); - }, - - async unassignBackendFromUser(userId: string, backendId: string): Promise { - return request(`/admin/users/${userId}/backends/${backendId}`, { method: 'DELETE' }); - }, - - async listUserApiKeys(userId: string): Promise { - return request(`/admin/users/${userId}/api-keys`); - }, - - async getUserStats(userId: string): Promise { - return request(`/admin/users/${userId}/stats`); - } -}; - -// Public API (no credentials, no 401 redirect) -export const publicApi = { - async getRun(id: string): Promise { - const resp = await fetch(`${API_BASE}/public/runs/${id}`); - if (!resp.ok) { - const error = await resp.json().catch(() => ({ detail: resp.statusText })); - const err: ApiError = new Error(error.detail || `HTTP ${resp.status}`); - err.status = resp.status; - throw err; - } - return resp.json(); - } -}; - -// API Keys -export const apiKeys = { - async list(): Promise { - return request('/auth/api-keys/'); - }, - - async create(name: string, expiresInDays: number, userId: string): Promise { - return request('/auth/api-keys/', { - method: 'POST', - body: JSON.stringify({ name, expires_in_days: expiresInDays, user_id: userId }) - }); - }, - - async delete(keyId: string): Promise { - return request(`/auth/api-keys/${keyId}`, { method: 'DELETE' }); - } -}; diff --git a/frontend/app/src/lib/api/schema.ts b/frontend/app/src/lib/api/schema.ts deleted file mode 100644 index 7982b961..00000000 --- a/frontend/app/src/lib/api/schema.ts +++ /dev/null @@ -1,71 +0,0 @@ -// Lazy access to the backend OpenAPI spec for surfacing field descriptions. -// Fetched once per page load and memoised. - -interface OpenAPISpec { - components?: { - schemas?: Record; - }; -} - -interface SchemaObject { - properties?: Record; - description?: string; - $ref?: string; - anyOf?: Array<{ $ref?: string; type?: string }>; -} - -interface PropertyObject extends SchemaObject {} - -let cache: Promise | null = null; - -function load(): Promise { - if (!cache) { - cache = fetch('/api/v1/openapi.json', { credentials: 'include' }) - .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`openapi ${r.status}`)))) - .catch((err) => { - cache = null; - throw err; - }); - } - return cache; -} - -function resolveRef(spec: OpenAPISpec, ref: string): SchemaObject | undefined { - const name = ref.split('/').pop(); - return name ? spec.components?.schemas?.[name] : undefined; -} - -function descend(spec: OpenAPISpec, current: SchemaObject, part: string): SchemaObject | undefined { - const prop = current.properties?.[part]; - if (!prop) return undefined; - if (prop.$ref) return resolveRef(spec, prop.$ref); - const ref = prop.anyOf?.find((x) => x.$ref)?.$ref; - if (ref) return resolveRef(spec, ref); - return prop; -} - -export async function fieldDescriptions( - schema: string, - fields: string[] -): Promise> { - let spec: OpenAPISpec; - try { - spec = await load(); - } catch { - return {}; - } - const root = spec.components?.schemas?.[schema]; - if (!root) return {}; - const out: Record = {}; - for (const field of fields) { - const parts = field.split('.'); - let current: SchemaObject | undefined = root; - for (let i = 0; i < parts.length - 1 && current; i++) { - current = descend(spec, current, parts[i]); - } - const last = parts[parts.length - 1]; - const prop = current?.properties?.[last]; - if (prop?.description) out[field] = prop.description; - } - return out; -} diff --git a/frontend/app/src/lib/assets/favicon.svg b/frontend/app/src/lib/assets/favicon.svg deleted file mode 100644 index fc8ed39d..00000000 --- a/frontend/app/src/lib/assets/favicon.svg +++ /dev/null @@ -1 +0,0 @@ -svelte-logo diff --git a/frontend/app/src/lib/assets/pypsa-logo.svg b/frontend/app/src/lib/assets/pypsa-logo.svg deleted file mode 100644 index 5c92eec6..00000000 --- a/frontend/app/src/lib/assets/pypsa-logo.svg +++ /dev/null @@ -1,25 +0,0 @@ - - diff --git a/frontend/app/src/lib/components/AppSidebar.svelte b/frontend/app/src/lib/components/AppSidebar.svelte deleted file mode 100644 index 21ebd1c3..00000000 --- a/frontend/app/src/lib/components/AppSidebar.svelte +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - {#snippet child({ props }: { props: Record })} - - PyPSA Logo -
- PyPSA App - {#if versionData?.app} - - - - v{formatVersion(versionData.app)} - - - -
- PyPSA App - {versionData.app} - PyPSA - {versionData.pypsa} -
-
-
- {/if} -
-
- {/snippet} -
-
-
-
- - - - - - - {#if features.demoMode} -
-
- - Demo instance -
-

- This is a public demo instance. Data shown is synthetic and may not be coherent. Uploads - to this instance are disabled. You can host your own instance or run the app in local - mode. - - Learn more - . -

-
- {/if} - - {#if !authStore.loading && authStore.isAuthenticated} - - - - {/if} - - -
diff --git a/frontend/app/src/lib/components/DarkModeToggle.svelte b/frontend/app/src/lib/components/DarkModeToggle.svelte deleted file mode 100644 index d761aec9..00000000 --- a/frontend/app/src/lib/components/DarkModeToggle.svelte +++ /dev/null @@ -1,13 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/DataTable.svelte b/frontend/app/src/lib/components/DataTable.svelte deleted file mode 100644 index d34d0db2..00000000 --- a/frontend/app/src/lib/components/DataTable.svelte +++ /dev/null @@ -1,333 +0,0 @@ - - -{#if showToolbar} -
- {#if showFilters} -
- -
- {/if} - -
- - {#if showColumnVisibility && visibleColumns.length > 0} - - - {#snippet child({ props }: { props: Record })} - - {/snippet} - - - Toggle Columns - - {#each visibleColumns as column} - {#if (column.accessorKey || column.id) && column.header} - {@const columnId = (column.id || column.accessorKey) as string} - {@const isVisible = columnVisibility[columnId] !== false} - toggleColumn(columnId, checked)} - closeOnSelect={false} - > - {column.header} - - {/if} - {/each} - - - {/if} -
-{/if} - -
-
- - - {#each table.getHeaderGroups() as headerGroup} - - {#each headerGroup.headers as header} - - {#if !header.isPlaceholder} - {#if header.column.getCanSort()} - - {:else} - - - {/if} - {/if} - - {/each} - - {/each} - - - {#each table.getRowModel().rows as row} - onRowClick?.(row.original)} - > - {#each row.getVisibleCells() as cell} - - - - - {/each} - - {/each} - - -
-
- -{#if showPagination} -
-
- {#if effectiveTotalItems === 0} - No items - {:else} - Showing {startItem}-{endItem} of {effectiveTotalItems.toLocaleString()} - {/if} -
- -
- goToPage(page)}> - {#snippet children({ pages })} - - - goToPage(effectivePage - 1)} disabled={isFirstPage} /> - - - {#each pages as page} - {#if page.type === 'ellipsis'} - - - - {:else} - - goToPage(page.value)}> - {page.value} - - - {/if} - {/each} - - - goToPage(effectivePage + 1)} disabled={isLastPage} /> - - - {/snippet} - - -
- Per page: - - - {effectivePageSize} - - - {#each pageSizeOptions as size} - - {size} - - {/each} - - -
-
-
-{/if} diff --git a/frontend/app/src/lib/components/DateTime.svelte b/frontend/app/src/lib/components/DateTime.svelte deleted file mode 100644 index 4f1d4499..00000000 --- a/frontend/app/src/lib/components/DateTime.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -{#if !value} - — -{:else} - - - - - -

{detailedRelative}

-

{absolute}

-
-
-{/if} diff --git a/frontend/app/src/lib/components/EmptyState.svelte b/frontend/app/src/lib/components/EmptyState.svelte deleted file mode 100644 index 6aa6d5d7..00000000 --- a/frontend/app/src/lib/components/EmptyState.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - {title} - {description} - - diff --git a/frontend/app/src/lib/components/LockedContentPreview.svelte b/frontend/app/src/lib/components/LockedContentPreview.svelte deleted file mode 100644 index 76588934..00000000 --- a/frontend/app/src/lib/components/LockedContentPreview.svelte +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - -

Sign in to see details.

-

PyPSA App is open source.

-

Deploy your own instance or use the local app.

diff --git a/frontend/app/src/lib/components/NotFound.svelte b/frontend/app/src/lib/components/NotFound.svelte deleted file mode 100644 index 88c6fbda..00000000 --- a/frontend/app/src/lib/components/NotFound.svelte +++ /dev/null @@ -1,11 +0,0 @@ -
-

404

-

It seems like no feasible solution can be found.

-

You may not have permission to view this resource.

- -
diff --git a/frontend/app/src/lib/components/admin/ApiKeyReveal.svelte b/frontend/app/src/lib/components/admin/ApiKeyReveal.svelte deleted file mode 100644 index a8a1de19..00000000 --- a/frontend/app/src/lib/components/admin/ApiKeyReveal.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - -
-
-

API key created!

-

Copy now. You won't see it again.

-
- {token} - -
-
-
- -
-
diff --git a/frontend/app/src/lib/components/admin/AssignmentList.svelte b/frontend/app/src/lib/components/admin/AssignmentList.svelte deleted file mode 100644 index 8b3da389..00000000 --- a/frontend/app/src/lib/components/admin/AssignmentList.svelte +++ /dev/null @@ -1,83 +0,0 @@ - - -
- {#if items.length === 0} -

{emptyText}

- {:else} -
- {#each items as item (item.id)} -
- {#if rowSnippet} - {@render rowSnippet(item)} - {:else} - {labelOf(item)} - {/if} - -
- {/each} -
- {/if} - - {#if candidates.length === 0} -

No candidates available.

- {:else if options.length > 0} - - {#snippet trigger({ props })} - - {/snippet} - - {/if} -
diff --git a/frontend/app/src/lib/components/cells/ActionsCell.svelte b/frontend/app/src/lib/components/cells/ActionsCell.svelte deleted file mode 100644 index e0aec081..00000000 --- a/frontend/app/src/lib/components/cells/ActionsCell.svelte +++ /dev/null @@ -1,60 +0,0 @@ - - -{#if actions.length > 0} -
e.stopPropagation()} onkeydown={(e) => e.key === 'Enter' && e.stopPropagation()} role="button" tabindex="-1"> - - - {#snippet child({ props }: { props: Record })} - - {/snippet} - - - {#each actions as action, i} - {#if i > 0 && action.variant === 'destructive'} - - {/if} - - {#if action.loading} - - {action.loadingLabel || 'Loading...'} - {:else} - - {action.label} - {/if} - - {/each} - - -
-{/if} diff --git a/frontend/app/src/lib/components/cells/BadgeCell.svelte b/frontend/app/src/lib/components/cells/BadgeCell.svelte deleted file mode 100644 index 6dbbb634..00000000 --- a/frontend/app/src/lib/components/cells/BadgeCell.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - - {#if icon} - {@const Icon = icon} - - {/if} - {label} - diff --git a/frontend/app/src/lib/components/cells/OwnerCell.svelte b/frontend/app/src/lib/components/cells/OwnerCell.svelte deleted file mode 100644 index 4c970e77..00000000 --- a/frontend/app/src/lib/components/cells/OwnerCell.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - -{#if owner} - - - - {#if owner.avatar_url} - - {/if} - - {owner.username.substring(0, 2).toUpperCase()} - - - - -

{owner.username}

-
-
-{/if} diff --git a/frontend/app/src/lib/components/cells/UserCell.svelte b/frontend/app/src/lib/components/cells/UserCell.svelte deleted file mode 100644 index 02dff861..00000000 --- a/frontend/app/src/lib/components/cells/UserCell.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - -
- - {#if user.avatar_url} - - {/if} - - {user.username.substring(0, 2).toUpperCase()} - - - {user.username} -
diff --git a/frontend/app/src/lib/components/cells/VisibilityCell.svelte b/frontend/app/src/lib/components/cells/VisibilityCell.svelte deleted file mode 100644 index bd3aafec..00000000 --- a/frontend/app/src/lib/components/cells/VisibilityCell.svelte +++ /dev/null @@ -1,49 +0,0 @@ - - -{#if isSystem} -
-{:else} -
e.stopPropagation()} onkeydown={(e) => e.key === 'Enter' && e.stopPropagation()} role="button" tabindex="-1"> - - - {#snippet child({ props }: { props: Record })} - {#if canEdit} - - {:else} -
- -
- {/if} - {/snippet} -
- - {isPublic ? 'Visible to all users' : 'Only visible to the owner'} - -
-
-{/if} diff --git a/frontend/app/src/lib/components/sidebar/NavAdmin.svelte b/frontend/app/src/lib/components/sidebar/NavAdmin.svelte deleted file mode 100644 index a4704116..00000000 --- a/frontend/app/src/lib/components/sidebar/NavAdmin.svelte +++ /dev/null @@ -1,70 +0,0 @@ - - -{#if authStore.isAdmin} - - - - - - {#snippet child({ props })} - - - Administration - - - {/snippet} - - - - {#each navItems as item} - - - {#snippet child({ props }: { props: Record })} - - - {item.title} - - {/snippet} - - - {/each} - - - - - - -{/if} diff --git a/frontend/app/src/lib/components/sidebar/NavMain.svelte b/frontend/app/src/lib/components/sidebar/NavMain.svelte deleted file mode 100644 index 50705207..00000000 --- a/frontend/app/src/lib/components/sidebar/NavMain.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - - - Navigation - - - {#each navItems as item} - - - {#snippet child({ props }: { props: Record })} - - - {item.title} - - {/snippet} - - - {/each} - - - diff --git a/frontend/app/src/lib/components/sidebar/NavUser.svelte b/frontend/app/src/lib/components/sidebar/NavUser.svelte deleted file mode 100644 index 818cd120..00000000 --- a/frontend/app/src/lib/components/sidebar/NavUser.svelte +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - {#snippet child({ props }: { props: Record })} - {#if authStore.isAuthenticated} - - - - - {getInitials(authStore.displayName)} - - -
- {authStore.displayName} - {authStore.user?.email || ''} -
- -
- {:else} - - - Sign in - - {/if} - {/snippet} -
- - -
- {#if authStore.isAuthenticated} - - - - {getInitials(authStore.displayName)} - - -
- {authStore.displayName} - {authStore.user?.email || ''} -
- {/if} -
-
- - - - - Profile - - - - - - Log out - -
-
-
-
diff --git a/frontend/app/src/lib/components/skeletons/NetworksListSkeleton.svelte b/frontend/app/src/lib/components/skeletons/NetworksListSkeleton.svelte deleted file mode 100644 index 709c79f4..00000000 --- a/frontend/app/src/lib/components/skeletons/NetworksListSkeleton.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - -
- {#each Array(count) as _, i} -
- - -
- {/each} -
diff --git a/frontend/app/src/lib/components/skeletons/PageSkeleton.svelte b/frontend/app/src/lib/components/skeletons/PageSkeleton.svelte deleted file mode 100644 index 154c1f03..00000000 --- a/frontend/app/src/lib/components/skeletons/PageSkeleton.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - -
- - - -
diff --git a/frontend/app/src/lib/components/skeletons/PlotSkeleton.svelte b/frontend/app/src/lib/components/skeletons/PlotSkeleton.svelte deleted file mode 100644 index e7c4cc1a..00000000 --- a/frontend/app/src/lib/components/skeletons/PlotSkeleton.svelte +++ /dev/null @@ -1,84 +0,0 @@ - - -
- {#if title} -

{title}

- {/if} -
-
- - - -
-
- {#each leftBars as barHeight, i} -
- -
- {/each} - - {#each rightBars as barHeight, i} -
- -
- {/each} -
- - - -
-
- - - - - -
-
-
-
-
-
- {#if message} - {message} - {/if} -
-
-
-
diff --git a/frontend/app/src/lib/components/skeletons/RunDetailSkeleton.svelte b/frontend/app/src/lib/components/skeletons/RunDetailSkeleton.svelte deleted file mode 100644 index 7651cb2d..00000000 --- a/frontend/app/src/lib/components/skeletons/RunDetailSkeleton.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
-
- - -
-
- - - - -
-
-{#if showContentArea} - -{/if} diff --git a/frontend/app/src/lib/components/skeletons/TableSkeleton.svelte b/frontend/app/src/lib/components/skeletons/TableSkeleton.svelte deleted file mode 100644 index c9ef42d7..00000000 --- a/frontend/app/src/lib/components/skeletons/TableSkeleton.svelte +++ /dev/null @@ -1,32 +0,0 @@ - - -
-
- - - - {#each Array(columns) as _} - - {/each} - - - - {#each Array(rows) as _, i} - - {#each Array(columns) as _} - - {/each} - - {/each} - -
- -
- -
-
-
diff --git a/frontend/app/src/lib/components/skeletons/index.ts b/frontend/app/src/lib/components/skeletons/index.ts deleted file mode 100644 index 2268d023..00000000 --- a/frontend/app/src/lib/components/skeletons/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as TableSkeleton } from './TableSkeleton.svelte'; -export { default as PlotSkeleton } from './PlotSkeleton.svelte'; -export { default as PageSkeleton } from './PageSkeleton.svelte'; -export { default as NetworksListSkeleton } from './NetworksListSkeleton.svelte'; -export { default as RunDetailSkeleton } from './RunDetailSkeleton.svelte'; diff --git a/frontend/app/src/lib/components/ui/alert/alert-description.svelte b/frontend/app/src/lib/components/ui/alert/alert-description.svelte deleted file mode 100644 index 8b56aed2..00000000 --- a/frontend/app/src/lib/components/ui/alert/alert-description.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
- {@render children?.()} -
diff --git a/frontend/app/src/lib/components/ui/alert/alert-title.svelte b/frontend/app/src/lib/components/ui/alert/alert-title.svelte deleted file mode 100644 index 77e45ad5..00000000 --- a/frontend/app/src/lib/components/ui/alert/alert-title.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
- {@render children?.()} -
diff --git a/frontend/app/src/lib/components/ui/alert/alert.svelte b/frontend/app/src/lib/components/ui/alert/alert.svelte deleted file mode 100644 index 80f7858b..00000000 --- a/frontend/app/src/lib/components/ui/alert/alert.svelte +++ /dev/null @@ -1,44 +0,0 @@ - - - - - diff --git a/frontend/app/src/lib/components/ui/alert/index.ts b/frontend/app/src/lib/components/ui/alert/index.ts deleted file mode 100644 index 97e21b4e..00000000 --- a/frontend/app/src/lib/components/ui/alert/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import Root from "./alert.svelte"; -import Description from "./alert-description.svelte"; -import Title from "./alert-title.svelte"; -export { alertVariants, type AlertVariant } from "./alert.svelte"; - -export { - Root, - Description, - Title, - // - Root as Alert, - Description as AlertDescription, - Title as AlertTitle, -}; diff --git a/frontend/app/src/lib/components/ui/avatar/avatar-fallback.svelte b/frontend/app/src/lib/components/ui/avatar/avatar-fallback.svelte deleted file mode 100644 index 249d4a4a..00000000 --- a/frontend/app/src/lib/components/ui/avatar/avatar-fallback.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/avatar/avatar-image.svelte b/frontend/app/src/lib/components/ui/avatar/avatar-image.svelte deleted file mode 100644 index 2bb9db4d..00000000 --- a/frontend/app/src/lib/components/ui/avatar/avatar-image.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/avatar/avatar.svelte b/frontend/app/src/lib/components/ui/avatar/avatar.svelte deleted file mode 100644 index e37214d5..00000000 --- a/frontend/app/src/lib/components/ui/avatar/avatar.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/avatar/index.ts b/frontend/app/src/lib/components/ui/avatar/index.ts deleted file mode 100644 index d06457be..00000000 --- a/frontend/app/src/lib/components/ui/avatar/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Root from "./avatar.svelte"; -import Image from "./avatar-image.svelte"; -import Fallback from "./avatar-fallback.svelte"; - -export { - Root, - Image, - Fallback, - // - Root as Avatar, - Image as AvatarImage, - Fallback as AvatarFallback, -}; diff --git a/frontend/app/src/lib/components/ui/badge/badge.svelte b/frontend/app/src/lib/components/ui/badge/badge.svelte deleted file mode 100644 index e3164ba7..00000000 --- a/frontend/app/src/lib/components/ui/badge/badge.svelte +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/badge/index.ts b/frontend/app/src/lib/components/ui/badge/index.ts deleted file mode 100644 index 64e0aa9b..00000000 --- a/frontend/app/src/lib/components/ui/badge/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Badge } from "./badge.svelte"; -export { badgeVariants, type BadgeVariant } from "./badge.svelte"; diff --git a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte b/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte deleted file mode 100644 index a178cf55..00000000 --- a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte b/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte deleted file mode 100644 index 1a84c4c4..00000000 --- a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
  • - {@render children?.()} -
  • diff --git a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte b/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte deleted file mode 100644 index e6bc17d3..00000000 --- a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - -{#if child} - {@render child({ props: attrs })} -{:else} - - {@render children?.()} - -{/if} diff --git a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte b/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte deleted file mode 100644 index 1272a374..00000000 --- a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
      - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte b/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte deleted file mode 100644 index 5fb69794..00000000 --- a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte b/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte deleted file mode 100644 index 84106a1c..00000000 --- a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb.svelte b/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb.svelte deleted file mode 100644 index 8f8a3e64..00000000 --- a/frontend/app/src/lib/components/ui/breadcrumb/breadcrumb.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/breadcrumb/index.ts b/frontend/app/src/lib/components/ui/breadcrumb/index.ts deleted file mode 100644 index dc914ec3..00000000 --- a/frontend/app/src/lib/components/ui/breadcrumb/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import Root from "./breadcrumb.svelte"; -import Ellipsis from "./breadcrumb-ellipsis.svelte"; -import Item from "./breadcrumb-item.svelte"; -import Separator from "./breadcrumb-separator.svelte"; -import Link from "./breadcrumb-link.svelte"; -import List from "./breadcrumb-list.svelte"; -import Page from "./breadcrumb-page.svelte"; - -export { - Root, - Ellipsis, - Item, - Separator, - Link, - List, - Page, - // - Root as Breadcrumb, - Ellipsis as BreadcrumbEllipsis, - Item as BreadcrumbItem, - Separator as BreadcrumbSeparator, - Link as BreadcrumbLink, - List as BreadcrumbList, - Page as BreadcrumbPage, -}; diff --git a/frontend/app/src/lib/components/ui/button/button.svelte b/frontend/app/src/lib/components/ui/button/button.svelte deleted file mode 100644 index a8296aed..00000000 --- a/frontend/app/src/lib/components/ui/button/button.svelte +++ /dev/null @@ -1,82 +0,0 @@ - - - - -{#if href} - - {@render children?.()} - -{:else} - -{/if} diff --git a/frontend/app/src/lib/components/ui/button/index.ts b/frontend/app/src/lib/components/ui/button/index.ts deleted file mode 100644 index fb585d76..00000000 --- a/frontend/app/src/lib/components/ui/button/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Root, { - type ButtonProps, - type ButtonSize, - type ButtonVariant, - buttonVariants, -} from "./button.svelte"; - -export { - Root, - type ButtonProps as Props, - // - Root as Button, - buttonVariants, - type ButtonProps, - type ButtonSize, - type ButtonVariant, -}; diff --git a/frontend/app/src/lib/components/ui/checkbox/checkbox.svelte b/frontend/app/src/lib/components/ui/checkbox/checkbox.svelte deleted file mode 100644 index 0a2b0101..00000000 --- a/frontend/app/src/lib/components/ui/checkbox/checkbox.svelte +++ /dev/null @@ -1,36 +0,0 @@ - - - - {#snippet children({ checked, indeterminate })} -
    - {#if checked} - - {:else if indeterminate} - - {/if} -
    - {/snippet} -
    diff --git a/frontend/app/src/lib/components/ui/checkbox/index.ts b/frontend/app/src/lib/components/ui/checkbox/index.ts deleted file mode 100644 index 6d92d945..00000000 --- a/frontend/app/src/lib/components/ui/checkbox/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import Root from "./checkbox.svelte"; -export { - Root, - // - Root as Checkbox, -}; diff --git a/frontend/app/src/lib/components/ui/data-table/data-table.svelte.ts b/frontend/app/src/lib/components/ui/data-table/data-table.svelte.ts deleted file mode 100644 index 5b7985e7..00000000 --- a/frontend/app/src/lib/components/ui/data-table/data-table.svelte.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { - type RowData, - type TableOptions, - type TableOptionsResolved, - type TableState, - createTable, -} from "@tanstack/table-core"; - -/** - * Creates a reactive TanStack table object for Svelte. - * @param options Table options to create the table with. - * @returns A reactive table object. - * @example - * ```svelte - * - * - * - * - * {#each table.getHeaderGroups() as headerGroup} - * - * {#each headerGroup.headers as header} - * - * {/each} - * - * {/each} - * - * - *
    - * - *
    - * ``` - */ -export function createSvelteTable(options: TableOptions) { - const resolvedOptions: TableOptionsResolved = mergeObjects( - { - state: {}, - onStateChange() {}, - renderFallbackValue: null, - mergeOptions: ( - defaultOptions: TableOptions, - options: Partial> - ) => { - return mergeObjects(defaultOptions, options); - }, - }, - options - ); - - const table = createTable(resolvedOptions); - let state = $state>(table.initialState); - - function updateOptions() { - table.setOptions((prev) => { - return mergeObjects(prev, options, { - state: mergeObjects(state, options.state || {}), - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onStateChange: (updater: any) => { - if (updater instanceof Function) state = updater(state); - else state = mergeObjects(state, updater); - - options.onStateChange?.(updater); - }, - }); - }); - } - - updateOptions(); - - $effect.pre(() => { - updateOptions(); - }); - - return table; -} - -type MaybeThunk = T | (() => T | null | undefined); -type Intersection = (T extends [infer H, ...infer R] - ? H & Intersection - : unknown) & {}; - -/** - * Lazily merges several objects (or thunks) while preserving - * getter semantics from every source. - * - * Proxy-based to avoid known WebKit recursion issue. - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function mergeObjects[]>( - ...sources: Sources -): Intersection<{ [K in keyof Sources]: Sources[K] }> { - const resolve = (src: MaybeThunk): T | undefined => - typeof src === "function" ? (src() ?? undefined) : src; - - const findSourceWithKey = (key: PropertyKey) => { - for (let i = sources.length - 1; i >= 0; i--) { - const obj = resolve(sources[i]); - if (obj && key in obj) return obj; - } - return undefined; - }; - - return new Proxy(Object.create(null), { - get(_, key) { - const src = findSourceWithKey(key); - - return src?.[key as never]; - }, - - has(_, key) { - return !!findSourceWithKey(key); - }, - - ownKeys(): (string | symbol)[] { - // eslint-disable-next-line svelte/prefer-svelte-reactivity - const all = new Set(); - for (const s of sources) { - const obj = resolve(s); - if (obj) { - for (const k of Reflect.ownKeys(obj) as (string | symbol)[]) { - all.add(k); - } - } - } - return [...all]; - }, - - getOwnPropertyDescriptor(_, key) { - const src = findSourceWithKey(key); - if (!src) return undefined; - return { - configurable: true, - enumerable: true, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - value: (src as any)[key], - writable: true, - }; - }, - }) as Intersection<{ [K in keyof Sources]: Sources[K] }>; -} diff --git a/frontend/app/src/lib/components/ui/data-table/flex-render.svelte b/frontend/app/src/lib/components/ui/data-table/flex-render.svelte deleted file mode 100644 index ac82a581..00000000 --- a/frontend/app/src/lib/components/ui/data-table/flex-render.svelte +++ /dev/null @@ -1,40 +0,0 @@ - - -{#if typeof content === "string"} - {content} -{:else if content instanceof Function} - - - {@const result = content(context as any)} - {#if result instanceof RenderComponentConfig} - {@const { component: Component, props } = result} - - {:else if result instanceof RenderSnippetConfig} - {@const { snippet, params } = result} - {@render snippet({ ...params, attach })} - {:else} - {result} - {/if} -{/if} diff --git a/frontend/app/src/lib/components/ui/data-table/render-helpers.ts b/frontend/app/src/lib/components/ui/data-table/render-helpers.ts deleted file mode 100644 index fa036d62..00000000 --- a/frontend/app/src/lib/components/ui/data-table/render-helpers.ts +++ /dev/null @@ -1,111 +0,0 @@ -import type { Component, ComponentProps, Snippet } from "svelte"; - -/** - * A helper class to make it easy to identify Svelte components in - * `columnDef.cell` and `columnDef.header` properties. - * - * > NOTE: This class should only be used internally by the adapter. If you're - * reading this and you don't know what this is for, you probably don't need it. - * - * @example - * ```svelte - * {@const result = content(context as any)} - * {#if result instanceof RenderComponentConfig} - * {@const { component: Component, props } = result} - * - * {/if} - * ``` - */ -export class RenderComponentConfig { - component: TComponent; - props: ComponentProps | Record; - constructor( - component: TComponent, - props: ComponentProps | Record = {} - ) { - this.component = component; - this.props = props; - } -} - -/** - * A helper class to make it easy to identify Svelte Snippets in `columnDef.cell` and `columnDef.header` properties. - * - * > NOTE: This class should only be used internally by the adapter. If you're - * reading this and you don't know what this is for, you probably don't need it. - * - * @example - * ```svelte - * {@const result = content(context as any)} - * {#if result instanceof RenderSnippetConfig} - * {@const { snippet, params } = result} - * {@render snippet(params)} - * {/if} - * ``` - */ -export class RenderSnippetConfig { - snippet: Snippet<[TProps]>; - params: TProps; - constructor(snippet: Snippet<[TProps]>, params: TProps) { - this.snippet = snippet; - this.params = params; - } -} - -/** - * A helper function to help create cells from Svelte components through ColumnDef's `cell` and `header` properties. - * - * This is only to be used with Svelte Components - use `renderSnippet` for Svelte Snippets. - * - * @param component A Svelte component - * @param props The props to pass to `component` - * @returns A `RenderComponentConfig` object that helps svelte-table know how to render the header/cell component. - * @example - * ```ts - * // +page.svelte - * const defaultColumns = [ - * columnHelper.accessor('name', { - * header: header => renderComponent(SortHeader, { label: 'Name', header }), - * }), - * columnHelper.accessor('state', { - * header: header => renderComponent(SortHeader, { label: 'State', header }), - * }), - * ] - * ``` - * @see {@link https://tanstack.com/table/latest/docs/guide/column-defs} - */ -export function renderComponent< - // eslint-disable-next-line @typescript-eslint/no-explicit-any - T extends Component, - Props extends ComponentProps, ->(component: T, props: Props = {} as Props) { - return new RenderComponentConfig(component, props); -} - -/** - * A helper function to help create cells from Svelte Snippets through ColumnDef's `cell` and `header` properties. - * - * The snippet must only take one parameter. - * - * This is only to be used with Snippets - use `renderComponent` for Svelte Components. - * - * @param snippet - * @param params - * @returns - A `RenderSnippetConfig` object that helps svelte-table know how to render the header/cell snippet. - * @example - * ```ts - * // +page.svelte - * const defaultColumns = [ - * columnHelper.accessor('name', { - * cell: cell => renderSnippet(nameSnippet, { name: cell.row.name }), - * }), - * columnHelper.accessor('state', { - * cell: cell => renderSnippet(stateSnippet, { state: cell.row.state }), - * }), - * ] - * ``` - * @see {@link https://tanstack.com/table/latest/docs/guide/column-defs} - */ -export function renderSnippet(snippet: Snippet<[TProps]>, params: TProps = {} as TProps) { - return new RenderSnippetConfig(snippet, params); -} diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-close.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-close.svelte deleted file mode 100644 index 840b2f68..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-close.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-content.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-content.svelte deleted file mode 100644 index 5c6ee6db..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-content.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - {@render children?.()} - {#if showCloseButton} - - - Close - - {/if} - - diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-description.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-description.svelte deleted file mode 100644 index 38450239..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-description.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-footer.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-footer.svelte deleted file mode 100644 index e7ff4468..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-footer.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-header.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-header.svelte deleted file mode 100644 index 4e5c4473..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-header.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-overlay.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-overlay.svelte deleted file mode 100644 index f81ad833..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-overlay.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-portal.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-portal.svelte deleted file mode 100644 index ccfa79ca..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-title.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-title.svelte deleted file mode 100644 index e4d4b344..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-title.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dialog/dialog-trigger.svelte b/frontend/app/src/lib/components/ui/dialog/dialog-trigger.svelte deleted file mode 100644 index 9d1e8011..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog-trigger.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dialog/dialog.svelte b/frontend/app/src/lib/components/ui/dialog/dialog.svelte deleted file mode 100644 index 211672c6..00000000 --- a/frontend/app/src/lib/components/ui/dialog/dialog.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dialog/index.ts b/frontend/app/src/lib/components/ui/dialog/index.ts deleted file mode 100644 index 076cef52..00000000 --- a/frontend/app/src/lib/components/ui/dialog/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import Root from "./dialog.svelte"; -import Portal from "./dialog-portal.svelte"; -import Title from "./dialog-title.svelte"; -import Footer from "./dialog-footer.svelte"; -import Header from "./dialog-header.svelte"; -import Overlay from "./dialog-overlay.svelte"; -import Content from "./dialog-content.svelte"; -import Description from "./dialog-description.svelte"; -import Trigger from "./dialog-trigger.svelte"; -import Close from "./dialog-close.svelte"; - -export { - Root, - Title, - Portal, - Footer, - Header, - Trigger, - Overlay, - Content, - Description, - Close, - // - Root as Dialog, - Title as DialogTitle, - Portal as DialogPortal, - Footer as DialogFooter, - Header as DialogHeader, - Trigger as DialogTrigger, - Overlay as DialogOverlay, - Content as DialogContent, - Description as DialogDescription, - Close as DialogClose, -}; diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte deleted file mode 100644 index e0e19718..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte deleted file mode 100644 index 6d9ef855..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +++ /dev/null @@ -1,43 +0,0 @@ - - - - {#snippet children({ checked, indeterminate })} - - {#if indeterminate} - - {:else} - - {/if} - - {@render childrenProp?.()} - {/snippet} - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte deleted file mode 100644 index 1e96782e..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte deleted file mode 100644 index 433540fd..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte deleted file mode 100644 index aca1f7bd..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte deleted file mode 100644 index 04cd1103..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte deleted file mode 100644 index 9681c2bb..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte deleted file mode 100644 index 274cfef7..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte deleted file mode 100644 index 189aef40..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte deleted file mode 100644 index ce2ad094..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - - {#snippet children({ checked })} - - {#if checked} - - {/if} - - {@render childrenProp?.({ checked })} - {/snippet} - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte deleted file mode 100644 index 90f1b6f1..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte deleted file mode 100644 index 7c6e9c67..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte deleted file mode 100644 index 3f06dc49..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte deleted file mode 100644 index 5f49d01e..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - {@render children?.()} - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte deleted file mode 100644 index f0445813..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte deleted file mode 100644 index cb053444..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte b/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte deleted file mode 100644 index cb4bc621..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/dropdown-menu/index.ts b/frontend/app/src/lib/components/ui/dropdown-menu/index.ts deleted file mode 100644 index 7850c6a3..00000000 --- a/frontend/app/src/lib/components/ui/dropdown-menu/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import Root from "./dropdown-menu.svelte"; -import Sub from "./dropdown-menu-sub.svelte"; -import CheckboxGroup from "./dropdown-menu-checkbox-group.svelte"; -import CheckboxItem from "./dropdown-menu-checkbox-item.svelte"; -import Content from "./dropdown-menu-content.svelte"; -import Group from "./dropdown-menu-group.svelte"; -import Item from "./dropdown-menu-item.svelte"; -import Label from "./dropdown-menu-label.svelte"; -import RadioGroup from "./dropdown-menu-radio-group.svelte"; -import RadioItem from "./dropdown-menu-radio-item.svelte"; -import Separator from "./dropdown-menu-separator.svelte"; -import Shortcut from "./dropdown-menu-shortcut.svelte"; -import Trigger from "./dropdown-menu-trigger.svelte"; -import SubContent from "./dropdown-menu-sub-content.svelte"; -import SubTrigger from "./dropdown-menu-sub-trigger.svelte"; -import GroupHeading from "./dropdown-menu-group-heading.svelte"; -import Portal from "./dropdown-menu-portal.svelte"; - -export { - CheckboxGroup, - CheckboxItem, - Content, - Portal, - Root as DropdownMenu, - CheckboxGroup as DropdownMenuCheckboxGroup, - CheckboxItem as DropdownMenuCheckboxItem, - Content as DropdownMenuContent, - Portal as DropdownMenuPortal, - Group as DropdownMenuGroup, - Item as DropdownMenuItem, - Label as DropdownMenuLabel, - RadioGroup as DropdownMenuRadioGroup, - RadioItem as DropdownMenuRadioItem, - Separator as DropdownMenuSeparator, - Shortcut as DropdownMenuShortcut, - Sub as DropdownMenuSub, - SubContent as DropdownMenuSubContent, - SubTrigger as DropdownMenuSubTrigger, - Trigger as DropdownMenuTrigger, - GroupHeading as DropdownMenuGroupHeading, - Group, - GroupHeading, - Item, - Label, - RadioGroup, - RadioItem, - Root, - Separator, - Shortcut, - Sub, - SubContent, - SubTrigger, - Trigger, -}; diff --git a/frontend/app/src/lib/components/ui/empty/empty-content.svelte b/frontend/app/src/lib/components/ui/empty/empty-content.svelte deleted file mode 100644 index f5a9c68c..00000000 --- a/frontend/app/src/lib/components/ui/empty/empty-content.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/empty/empty-description.svelte b/frontend/app/src/lib/components/ui/empty/empty-description.svelte deleted file mode 100644 index 85a866c0..00000000 --- a/frontend/app/src/lib/components/ui/empty/empty-description.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4", - className - )} - {...restProps} -> - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/empty/empty-header.svelte b/frontend/app/src/lib/components/ui/empty/empty-header.svelte deleted file mode 100644 index 296eaf8a..00000000 --- a/frontend/app/src/lib/components/ui/empty/empty-header.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/empty/empty-media.svelte b/frontend/app/src/lib/components/ui/empty/empty-media.svelte deleted file mode 100644 index 0b4e45de..00000000 --- a/frontend/app/src/lib/components/ui/empty/empty-media.svelte +++ /dev/null @@ -1,41 +0,0 @@ - - - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/empty/empty-title.svelte b/frontend/app/src/lib/components/ui/empty/empty-title.svelte deleted file mode 100644 index 8c237aae..00000000 --- a/frontend/app/src/lib/components/ui/empty/empty-title.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/empty/empty.svelte b/frontend/app/src/lib/components/ui/empty/empty.svelte deleted file mode 100644 index 4ccf0604..00000000 --- a/frontend/app/src/lib/components/ui/empty/empty.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/empty/index.ts b/frontend/app/src/lib/components/ui/empty/index.ts deleted file mode 100644 index ae4c106e..00000000 --- a/frontend/app/src/lib/components/ui/empty/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import Root from "./empty.svelte"; -import Header from "./empty-header.svelte"; -import Media from "./empty-media.svelte"; -import Title from "./empty-title.svelte"; -import Description from "./empty-description.svelte"; -import Content from "./empty-content.svelte"; - -export { - Root, - Header, - Media, - Title, - Description, - Content, - // - Root as Empty, - Header as EmptyHeader, - Media as EmptyMedia, - Title as EmptyTitle, - Description as EmptyDescription, - Content as EmptyContent, -}; diff --git a/frontend/app/src/lib/components/ui/field/field-content.svelte b/frontend/app/src/lib/components/ui/field/field-content.svelte deleted file mode 100644 index 1b6535b4..00000000 --- a/frontend/app/src/lib/components/ui/field/field-content.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/field/field-description.svelte b/frontend/app/src/lib/components/ui/field/field-description.svelte deleted file mode 100644 index a0c9f067..00000000 --- a/frontend/app/src/lib/components/ui/field/field-description.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - -

    a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", - className - )} - {...restProps} -> - {@render children?.()} -

    diff --git a/frontend/app/src/lib/components/ui/field/field-error.svelte b/frontend/app/src/lib/components/ui/field/field-error.svelte deleted file mode 100644 index 94a46c2b..00000000 --- a/frontend/app/src/lib/components/ui/field/field-error.svelte +++ /dev/null @@ -1,58 +0,0 @@ - - -{#if hasContent} - -{/if} diff --git a/frontend/app/src/lib/components/ui/field/field-group.svelte b/frontend/app/src/lib/components/ui/field/field-group.svelte deleted file mode 100644 index e6854279..00000000 --- a/frontend/app/src/lib/components/ui/field/field-group.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    [data-slot=field-group]]:gap-4", - className - )} - {...restProps} -> - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/field/field-label.svelte b/frontend/app/src/lib/components/ui/field/field-label.svelte deleted file mode 100644 index 2ee431a7..00000000 --- a/frontend/app/src/lib/components/ui/field/field-label.svelte +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/field/field-legend.svelte b/frontend/app/src/lib/components/ui/field/field-legend.svelte deleted file mode 100644 index 3f1c50fb..00000000 --- a/frontend/app/src/lib/components/ui/field/field-legend.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/field/field-separator.svelte b/frontend/app/src/lib/components/ui/field/field-separator.svelte deleted file mode 100644 index 12bcb77e..00000000 --- a/frontend/app/src/lib/components/ui/field/field-separator.svelte +++ /dev/null @@ -1,38 +0,0 @@ - - -
    - - {#if children} - - {@render children()} - - {/if} -
    diff --git a/frontend/app/src/lib/components/ui/field/field-set.svelte b/frontend/app/src/lib/components/ui/field/field-set.svelte deleted file mode 100644 index 1d8e2339..00000000 --- a/frontend/app/src/lib/components/ui/field/field-set.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - -
    [data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", - className - )} - {...restProps} -> - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/field/field-title.svelte b/frontend/app/src/lib/components/ui/field/field-title.svelte deleted file mode 100644 index 59060445..00000000 --- a/frontend/app/src/lib/components/ui/field/field-title.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/field/field.svelte b/frontend/app/src/lib/components/ui/field/field.svelte deleted file mode 100644 index 32842030..00000000 --- a/frontend/app/src/lib/components/ui/field/field.svelte +++ /dev/null @@ -1,53 +0,0 @@ - - - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/field/index.ts b/frontend/app/src/lib/components/ui/field/index.ts deleted file mode 100644 index a644a956..00000000 --- a/frontend/app/src/lib/components/ui/field/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import Field from "./field.svelte"; -import Set from "./field-set.svelte"; -import Legend from "./field-legend.svelte"; -import Group from "./field-group.svelte"; -import Content from "./field-content.svelte"; -import Label from "./field-label.svelte"; -import Title from "./field-title.svelte"; -import Description from "./field-description.svelte"; -import Separator from "./field-separator.svelte"; -import Error from "./field-error.svelte"; - -export { - Field, - Set, - Legend, - Group, - Content, - Label, - Title, - Description, - Separator, - Error, - // - Set as FieldSet, - Legend as FieldLegend, - Group as FieldGroup, - Content as FieldContent, - Label as FieldLabel, - Title as FieldTitle, - Description as FieldDescription, - Separator as FieldSeparator, - Error as FieldError, -}; diff --git a/frontend/app/src/lib/components/ui/input/index.ts b/frontend/app/src/lib/components/ui/input/index.ts deleted file mode 100644 index f47b6d3f..00000000 --- a/frontend/app/src/lib/components/ui/input/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Root from "./input.svelte"; - -export { - Root, - // - Root as Input, -}; diff --git a/frontend/app/src/lib/components/ui/input/input.svelte b/frontend/app/src/lib/components/ui/input/input.svelte deleted file mode 100644 index ff1a4c87..00000000 --- a/frontend/app/src/lib/components/ui/input/input.svelte +++ /dev/null @@ -1,52 +0,0 @@ - - -{#if type === "file"} - -{:else} - -{/if} diff --git a/frontend/app/src/lib/components/ui/label/index.ts b/frontend/app/src/lib/components/ui/label/index.ts deleted file mode 100644 index 8bfca0b3..00000000 --- a/frontend/app/src/lib/components/ui/label/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Root from "./label.svelte"; - -export { - Root, - // - Root as Label, -}; diff --git a/frontend/app/src/lib/components/ui/label/label.svelte b/frontend/app/src/lib/components/ui/label/label.svelte deleted file mode 100644 index d71afbca..00000000 --- a/frontend/app/src/lib/components/ui/label/label.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/pagination/index.ts b/frontend/app/src/lib/components/ui/pagination/index.ts deleted file mode 100644 index a769899d..00000000 --- a/frontend/app/src/lib/components/ui/pagination/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -import Root from "./pagination.svelte"; -import Content from "./pagination-content.svelte"; -import Item from "./pagination-item.svelte"; -import Link from "./pagination-link.svelte"; -import PrevButton from "./pagination-prev-button.svelte"; -import NextButton from "./pagination-next-button.svelte"; -import Ellipsis from "./pagination-ellipsis.svelte"; -import Previous from "./pagination-previous.svelte"; -import Next from "./pagination-next.svelte"; - -export { - Root, - Content, - Item, - Link, - PrevButton, //old - NextButton, //old - Ellipsis, - Previous, - Next, - // - Root as Pagination, - Content as PaginationContent, - Item as PaginationItem, - Link as PaginationLink, - PrevButton as PaginationPrevButton, //old - NextButton as PaginationNextButton, //old - Ellipsis as PaginationEllipsis, - Previous as PaginationPrevious, - Next as PaginationNext, -}; diff --git a/frontend/app/src/lib/components/ui/pagination/pagination-content.svelte b/frontend/app/src/lib/components/ui/pagination/pagination-content.svelte deleted file mode 100644 index e1124fce..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination-content.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
      - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/pagination/pagination-ellipsis.svelte b/frontend/app/src/lib/components/ui/pagination/pagination-ellipsis.svelte deleted file mode 100644 index 3be94c9c..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination-ellipsis.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/pagination/pagination-item.svelte b/frontend/app/src/lib/components/ui/pagination/pagination-item.svelte deleted file mode 100644 index fd7ffc3a..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination-item.svelte +++ /dev/null @@ -1,14 +0,0 @@ - - -
  • - {@render children?.()} -
  • diff --git a/frontend/app/src/lib/components/ui/pagination/pagination-link.svelte b/frontend/app/src/lib/components/ui/pagination/pagination-link.svelte deleted file mode 100644 index 58b1a5ca..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination-link.svelte +++ /dev/null @@ -1,39 +0,0 @@ - - -{#snippet Fallback()} - {page.value} -{/snippet} - - diff --git a/frontend/app/src/lib/components/ui/pagination/pagination-next-button.svelte b/frontend/app/src/lib/components/ui/pagination/pagination-next-button.svelte deleted file mode 100644 index cc40ee30..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination-next-button.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - -{#snippet Fallback()} - Next - -{/snippet} - - diff --git a/frontend/app/src/lib/components/ui/pagination/pagination-next.svelte b/frontend/app/src/lib/components/ui/pagination/pagination-next.svelte deleted file mode 100644 index 5bb37f7b..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination-next.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - - diff --git a/frontend/app/src/lib/components/ui/pagination/pagination-prev-button.svelte b/frontend/app/src/lib/components/ui/pagination/pagination-prev-button.svelte deleted file mode 100644 index 28caad5e..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination-prev-button.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - -{#snippet Fallback()} - - Previous -{/snippet} - - diff --git a/frontend/app/src/lib/components/ui/pagination/pagination-previous.svelte b/frontend/app/src/lib/components/ui/pagination/pagination-previous.svelte deleted file mode 100644 index cf7c460f..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination-previous.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - - diff --git a/frontend/app/src/lib/components/ui/pagination/pagination.svelte b/frontend/app/src/lib/components/ui/pagination/pagination.svelte deleted file mode 100644 index 60e3471b..00000000 --- a/frontend/app/src/lib/components/ui/pagination/pagination.svelte +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/popover/index.ts b/frontend/app/src/lib/components/ui/popover/index.ts deleted file mode 100644 index b79d12e5..00000000 --- a/frontend/app/src/lib/components/ui/popover/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Root from "./popover.svelte"; -import Close from "./popover-close.svelte"; -import Content from "./popover-content.svelte"; -import Trigger from "./popover-trigger.svelte"; -import Portal from "./popover-portal.svelte"; - -export { - Root, - Content, - Trigger, - Close, - Portal, - // - Root as Popover, - Content as PopoverContent, - Trigger as PopoverTrigger, - Close as PopoverClose, - Portal as PopoverPortal, -}; diff --git a/frontend/app/src/lib/components/ui/popover/popover-close.svelte b/frontend/app/src/lib/components/ui/popover/popover-close.svelte deleted file mode 100644 index c360925a..00000000 --- a/frontend/app/src/lib/components/ui/popover/popover-close.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/popover/popover-content.svelte b/frontend/app/src/lib/components/ui/popover/popover-content.svelte deleted file mode 100644 index 3d79f3c6..00000000 --- a/frontend/app/src/lib/components/ui/popover/popover-content.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - - - - diff --git a/frontend/app/src/lib/components/ui/popover/popover-portal.svelte b/frontend/app/src/lib/components/ui/popover/popover-portal.svelte deleted file mode 100644 index dd8265fe..00000000 --- a/frontend/app/src/lib/components/ui/popover/popover-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/popover/popover-trigger.svelte b/frontend/app/src/lib/components/ui/popover/popover-trigger.svelte deleted file mode 100644 index 586323c7..00000000 --- a/frontend/app/src/lib/components/ui/popover/popover-trigger.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/popover/popover.svelte b/frontend/app/src/lib/components/ui/popover/popover.svelte deleted file mode 100644 index 6b1aa5f9..00000000 --- a/frontend/app/src/lib/components/ui/popover/popover.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/select/index.ts b/frontend/app/src/lib/components/ui/select/index.ts deleted file mode 100644 index 4dec358b..00000000 --- a/frontend/app/src/lib/components/ui/select/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import Root from "./select.svelte"; -import Group from "./select-group.svelte"; -import Label from "./select-label.svelte"; -import Item from "./select-item.svelte"; -import Content from "./select-content.svelte"; -import Trigger from "./select-trigger.svelte"; -import Separator from "./select-separator.svelte"; -import ScrollDownButton from "./select-scroll-down-button.svelte"; -import ScrollUpButton from "./select-scroll-up-button.svelte"; -import GroupHeading from "./select-group-heading.svelte"; -import Portal from "./select-portal.svelte"; - -export { - Root, - Group, - Label, - Item, - Content, - Trigger, - Separator, - ScrollDownButton, - ScrollUpButton, - GroupHeading, - Portal, - // - Root as Select, - Group as SelectGroup, - Label as SelectLabel, - Item as SelectItem, - Content as SelectContent, - Trigger as SelectTrigger, - Separator as SelectSeparator, - ScrollDownButton as SelectScrollDownButton, - ScrollUpButton as SelectScrollUpButton, - GroupHeading as SelectGroupHeading, - Portal as SelectPortal, -}; diff --git a/frontend/app/src/lib/components/ui/select/select-content.svelte b/frontend/app/src/lib/components/ui/select/select-content.svelte deleted file mode 100644 index 4b9ca438..00000000 --- a/frontend/app/src/lib/components/ui/select/select-content.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - {@render children?.()} - - - - diff --git a/frontend/app/src/lib/components/ui/select/select-group-heading.svelte b/frontend/app/src/lib/components/ui/select/select-group-heading.svelte deleted file mode 100644 index 1fab5f00..00000000 --- a/frontend/app/src/lib/components/ui/select/select-group-heading.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/select/select-group.svelte b/frontend/app/src/lib/components/ui/select/select-group.svelte deleted file mode 100644 index a1f43bf3..00000000 --- a/frontend/app/src/lib/components/ui/select/select-group.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/select/select-item.svelte b/frontend/app/src/lib/components/ui/select/select-item.svelte deleted file mode 100644 index b85eef69..00000000 --- a/frontend/app/src/lib/components/ui/select/select-item.svelte +++ /dev/null @@ -1,38 +0,0 @@ - - - - {#snippet children({ selected, highlighted })} - - {#if selected} - - {/if} - - {#if childrenProp} - {@render childrenProp({ selected, highlighted })} - {:else} - {label || value} - {/if} - {/snippet} - diff --git a/frontend/app/src/lib/components/ui/select/select-label.svelte b/frontend/app/src/lib/components/ui/select/select-label.svelte deleted file mode 100644 index 46960259..00000000 --- a/frontend/app/src/lib/components/ui/select/select-label.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/select/select-portal.svelte b/frontend/app/src/lib/components/ui/select/select-portal.svelte deleted file mode 100644 index 424bcddc..00000000 --- a/frontend/app/src/lib/components/ui/select/select-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/select/select-scroll-down-button.svelte b/frontend/app/src/lib/components/ui/select/select-scroll-down-button.svelte deleted file mode 100644 index 36292058..00000000 --- a/frontend/app/src/lib/components/ui/select/select-scroll-down-button.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/frontend/app/src/lib/components/ui/select/select-scroll-up-button.svelte b/frontend/app/src/lib/components/ui/select/select-scroll-up-button.svelte deleted file mode 100644 index 1aa2300c..00000000 --- a/frontend/app/src/lib/components/ui/select/select-scroll-up-button.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/frontend/app/src/lib/components/ui/select/select-separator.svelte b/frontend/app/src/lib/components/ui/select/select-separator.svelte deleted file mode 100644 index 0eac3ebc..00000000 --- a/frontend/app/src/lib/components/ui/select/select-separator.svelte +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/select/select-trigger.svelte b/frontend/app/src/lib/components/ui/select/select-trigger.svelte deleted file mode 100644 index dbb81dfa..00000000 --- a/frontend/app/src/lib/components/ui/select/select-trigger.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - {@render children?.()} - - diff --git a/frontend/app/src/lib/components/ui/select/select.svelte b/frontend/app/src/lib/components/ui/select/select.svelte deleted file mode 100644 index 05eb6634..00000000 --- a/frontend/app/src/lib/components/ui/select/select.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/separator/index.ts b/frontend/app/src/lib/components/ui/separator/index.ts deleted file mode 100644 index 82442d2c..00000000 --- a/frontend/app/src/lib/components/ui/separator/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Root from "./separator.svelte"; - -export { - Root, - // - Root as Separator, -}; diff --git a/frontend/app/src/lib/components/ui/separator/separator.svelte b/frontend/app/src/lib/components/ui/separator/separator.svelte deleted file mode 100644 index f40999fa..00000000 --- a/frontend/app/src/lib/components/ui/separator/separator.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sheet/index.ts b/frontend/app/src/lib/components/ui/sheet/index.ts deleted file mode 100644 index 28d7da1c..00000000 --- a/frontend/app/src/lib/components/ui/sheet/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import Root from "./sheet.svelte"; -import Portal from "./sheet-portal.svelte"; -import Trigger from "./sheet-trigger.svelte"; -import Close from "./sheet-close.svelte"; -import Overlay from "./sheet-overlay.svelte"; -import Content from "./sheet-content.svelte"; -import Header from "./sheet-header.svelte"; -import Footer from "./sheet-footer.svelte"; -import Title from "./sheet-title.svelte"; -import Description from "./sheet-description.svelte"; - -export { - Root, - Close, - Trigger, - Portal, - Overlay, - Content, - Header, - Footer, - Title, - Description, - // - Root as Sheet, - Close as SheetClose, - Trigger as SheetTrigger, - Portal as SheetPortal, - Overlay as SheetOverlay, - Content as SheetContent, - Header as SheetHeader, - Footer as SheetFooter, - Title as SheetTitle, - Description as SheetDescription, -}; diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-close.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-close.svelte deleted file mode 100644 index ae382c12..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-close.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-content.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-content.svelte deleted file mode 100644 index 065fe044..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-content.svelte +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - {@render children?.()} - - - Close - - - diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-description.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-description.svelte deleted file mode 100644 index 333b17a7..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-description.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-footer.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-footer.svelte deleted file mode 100644 index dd9ed84b..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-footer.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-header.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-header.svelte deleted file mode 100644 index 757a6a56..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-header.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-overlay.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-overlay.svelte deleted file mode 100644 index 345e197b..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-overlay.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-portal.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-portal.svelte deleted file mode 100644 index f3085a3c..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-title.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-title.svelte deleted file mode 100644 index 9fda327e..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-title.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sheet/sheet-trigger.svelte b/frontend/app/src/lib/components/ui/sheet/sheet-trigger.svelte deleted file mode 100644 index e266975f..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet-trigger.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sheet/sheet.svelte b/frontend/app/src/lib/components/ui/sheet/sheet.svelte deleted file mode 100644 index 5bf97839..00000000 --- a/frontend/app/src/lib/components/ui/sheet/sheet.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sidebar/constants.ts b/frontend/app/src/lib/components/ui/sidebar/constants.ts deleted file mode 100644 index 4de44351..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/constants.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const SIDEBAR_COOKIE_NAME = "sidebar:state"; -export const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; -export const SIDEBAR_WIDTH = "16rem"; -export const SIDEBAR_WIDTH_MOBILE = "18rem"; -export const SIDEBAR_WIDTH_ICON = "3rem"; -export const SIDEBAR_KEYBOARD_SHORTCUT = "b"; diff --git a/frontend/app/src/lib/components/ui/sidebar/context.svelte.ts b/frontend/app/src/lib/components/ui/sidebar/context.svelte.ts deleted file mode 100644 index 15248ada..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/context.svelte.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { IsMobile } from "$lib/hooks/is-mobile.svelte.js"; -import { getContext, setContext } from "svelte"; -import { SIDEBAR_KEYBOARD_SHORTCUT } from "./constants.js"; - -type Getter = () => T; - -export type SidebarStateProps = { - /** - * A getter function that returns the current open state of the sidebar. - * We use a getter function here to support `bind:open` on the `Sidebar.Provider` - * component. - */ - open: Getter; - - /** - * A function that sets the open state of the sidebar. To support `bind:open`, we need - * a source of truth for changing the open state to ensure it will be synced throughout - * the sub-components and any `bind:` references. - */ - setOpen: (open: boolean) => void; -}; - -class SidebarState { - readonly props: SidebarStateProps; - open = $derived.by(() => this.props.open()); - openMobile = $state(false); - setOpen: SidebarStateProps["setOpen"]; - #isMobile: IsMobile; - state = $derived.by(() => (this.open ? "expanded" : "collapsed")); - - constructor(props: SidebarStateProps) { - this.setOpen = props.setOpen; - this.#isMobile = new IsMobile(); - this.props = props; - } - - // Convenience getter for checking if the sidebar is mobile - // without this, we would need to use `sidebar.isMobile.current` everywhere - get isMobile() { - return this.#isMobile.current; - } - - // Event handler to apply to the `` - handleShortcutKeydown = (e: KeyboardEvent) => { - if (e.key === SIDEBAR_KEYBOARD_SHORTCUT && (e.metaKey || e.ctrlKey)) { - e.preventDefault(); - this.toggle(); - } - }; - - setOpenMobile = (value: boolean) => { - this.openMobile = value; - }; - - toggle = () => { - return this.#isMobile.current - ? (this.openMobile = !this.openMobile) - : this.setOpen(!this.open); - }; -} - -const SYMBOL_KEY = "scn-sidebar"; - -/** - * Instantiates a new `SidebarState` instance and sets it in the context. - * - * @param props The constructor props for the `SidebarState` class. - * @returns The `SidebarState` instance. - */ -export function setSidebar(props: SidebarStateProps): SidebarState { - return setContext(Symbol.for(SYMBOL_KEY), new SidebarState(props)); -} - -/** - * Retrieves the `SidebarState` instance from the context. This is a class instance, - * so you cannot destructure it. - * @returns The `SidebarState` instance. - */ -export function useSidebar(): SidebarState { - return getContext(Symbol.for(SYMBOL_KEY)); -} diff --git a/frontend/app/src/lib/components/ui/sidebar/index.ts b/frontend/app/src/lib/components/ui/sidebar/index.ts deleted file mode 100644 index 318a3417..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { useSidebar } from "./context.svelte.js"; -import Content from "./sidebar-content.svelte"; -import Footer from "./sidebar-footer.svelte"; -import GroupAction from "./sidebar-group-action.svelte"; -import GroupContent from "./sidebar-group-content.svelte"; -import GroupLabel from "./sidebar-group-label.svelte"; -import Group from "./sidebar-group.svelte"; -import Header from "./sidebar-header.svelte"; -import Input from "./sidebar-input.svelte"; -import Inset from "./sidebar-inset.svelte"; -import MenuAction from "./sidebar-menu-action.svelte"; -import MenuBadge from "./sidebar-menu-badge.svelte"; -import MenuButton from "./sidebar-menu-button.svelte"; -import MenuItem from "./sidebar-menu-item.svelte"; -import MenuSkeleton from "./sidebar-menu-skeleton.svelte"; -import MenuSubButton from "./sidebar-menu-sub-button.svelte"; -import MenuSubItem from "./sidebar-menu-sub-item.svelte"; -import MenuSub from "./sidebar-menu-sub.svelte"; -import Menu from "./sidebar-menu.svelte"; -import Provider from "./sidebar-provider.svelte"; -import Rail from "./sidebar-rail.svelte"; -import Separator from "./sidebar-separator.svelte"; -import Trigger from "./sidebar-trigger.svelte"; -import Root from "./sidebar.svelte"; - -export { - Content, - Footer, - Group, - GroupAction, - GroupContent, - GroupLabel, - Header, - Input, - Inset, - Menu, - MenuAction, - MenuBadge, - MenuButton, - MenuItem, - MenuSkeleton, - MenuSub, - MenuSubButton, - MenuSubItem, - Provider, - Rail, - Root, - Separator, - // - Root as Sidebar, - Content as SidebarContent, - Footer as SidebarFooter, - Group as SidebarGroup, - GroupAction as SidebarGroupAction, - GroupContent as SidebarGroupContent, - GroupLabel as SidebarGroupLabel, - Header as SidebarHeader, - Input as SidebarInput, - Inset as SidebarInset, - Menu as SidebarMenu, - MenuAction as SidebarMenuAction, - MenuBadge as SidebarMenuBadge, - MenuButton as SidebarMenuButton, - MenuItem as SidebarMenuItem, - MenuSkeleton as SidebarMenuSkeleton, - MenuSub as SidebarMenuSub, - MenuSubButton as SidebarMenuSubButton, - MenuSubItem as SidebarMenuSubItem, - Provider as SidebarProvider, - Rail as SidebarRail, - Separator as SidebarSeparator, - Trigger as SidebarTrigger, - Trigger, - useSidebar, -}; diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-content.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-content.svelte deleted file mode 100644 index f1218002..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-content.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-footer.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-footer.svelte deleted file mode 100644 index 6259cb95..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-footer.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-group-action.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-group-action.svelte deleted file mode 100644 index a76dfe17..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-group-action.svelte +++ /dev/null @@ -1,36 +0,0 @@ - - -{#if child} - {@render child({ props: mergedProps })} -{:else} - -{/if} diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-group-content.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-group-content.svelte deleted file mode 100644 index 415255f1..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-group-content.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-group-label.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-group-label.svelte deleted file mode 100644 index b2e72b67..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-group-label.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - -{#if child} - {@render child({ props: mergedProps })} -{:else} -
    - {@render children?.()} -
    -{/if} diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-group.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-group.svelte deleted file mode 100644 index ec18a697..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-group.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-header.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-header.svelte deleted file mode 100644 index a1b2db15..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-header.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-input.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-input.svelte deleted file mode 100644 index 19b36660..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-input.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-inset.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-inset.svelte deleted file mode 100644 index b67b7e41..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-inset.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-action.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-action.svelte deleted file mode 100644 index d3fe2954..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-action.svelte +++ /dev/null @@ -1,43 +0,0 @@ - - -{#if child} - {@render child({ props: mergedProps })} -{:else} - -{/if} diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte deleted file mode 100644 index e8ecdb47..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-button.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-button.svelte deleted file mode 100644 index 2ee7d7cd..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-button.svelte +++ /dev/null @@ -1,103 +0,0 @@ - - - - -{#snippet Button({ props }: { props?: Record })} - {@const mergedProps = mergeProps(buttonProps, props)} - {#if child} - {@render child({ props: mergedProps })} - {:else} - - {/if} -{/snippet} - -{#if !tooltipContent} - {@render Button({})} -{:else} - - - {#snippet child({ props })} - {@render Button({ props })} - {/snippet} - - - -{/if} diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-item.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-item.svelte deleted file mode 100644 index 4db44532..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-item.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
  • - {@render children?.()} -
  • diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte deleted file mode 100644 index 68604e24..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte +++ /dev/null @@ -1,36 +0,0 @@ - - -
    - {#if showIcon} - - {/if} - - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte deleted file mode 100644 index c8cd4ffe..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte +++ /dev/null @@ -1,43 +0,0 @@ - - -{#if child} - {@render child({ props: mergedProps })} -{:else} - - {@render children?.()} - -{/if} diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte deleted file mode 100644 index 681d0f1d..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
  • - {@render children?.()} -
  • diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte deleted file mode 100644 index 76bd1d91..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - -
      - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-menu.svelte deleted file mode 100644 index 946cccef..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-menu.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
      - {@render children?.()} -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-provider.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-provider.svelte deleted file mode 100644 index f8ef3835..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-provider.svelte +++ /dev/null @@ -1,53 +0,0 @@ - - - - - -
    - {@render children?.()} -
    -
    diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-rail.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-rail.svelte deleted file mode 100644 index 704d54f7..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-rail.svelte +++ /dev/null @@ -1,36 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-separator.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-separator.svelte deleted file mode 100644 index 5a7dedac..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-separator.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar-trigger.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar-trigger.svelte deleted file mode 100644 index 18251827..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar-trigger.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/sidebar/sidebar.svelte b/frontend/app/src/lib/components/ui/sidebar/sidebar.svelte deleted file mode 100644 index 7f0f202a..00000000 --- a/frontend/app/src/lib/components/ui/sidebar/sidebar.svelte +++ /dev/null @@ -1,105 +0,0 @@ - - -{#if collapsible === "none"} -
    - {@render children?.()} -
    -{:else if sidebar.isMobile} - sidebar.openMobile, (v) => sidebar.setOpenMobile(v)} - {...restProps} - > - - - Sidebar - Displays the mobile sidebar. - -
    - {@render children?.()} -
    -
    -
    -{:else} - -{/if} diff --git a/frontend/app/src/lib/components/ui/skeleton/index.ts b/frontend/app/src/lib/components/ui/skeleton/index.ts deleted file mode 100644 index 186db219..00000000 --- a/frontend/app/src/lib/components/ui/skeleton/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Root from "./skeleton.svelte"; - -export { - Root, - // - Root as Skeleton, -}; diff --git a/frontend/app/src/lib/components/ui/skeleton/skeleton.svelte b/frontend/app/src/lib/components/ui/skeleton/skeleton.svelte deleted file mode 100644 index c7e3d26c..00000000 --- a/frontend/app/src/lib/components/ui/skeleton/skeleton.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - -
    diff --git a/frontend/app/src/lib/components/ui/switch/switch.svelte b/frontend/app/src/lib/components/ui/switch/switch.svelte deleted file mode 100644 index 80661fd8..00000000 --- a/frontend/app/src/lib/components/ui/switch/switch.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - - diff --git a/frontend/app/src/lib/components/ui/table/index.ts b/frontend/app/src/lib/components/ui/table/index.ts deleted file mode 100644 index 14695c81..00000000 --- a/frontend/app/src/lib/components/ui/table/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import Root from "./table.svelte"; -import Body from "./table-body.svelte"; -import Caption from "./table-caption.svelte"; -import Cell from "./table-cell.svelte"; -import Footer from "./table-footer.svelte"; -import Head from "./table-head.svelte"; -import Header from "./table-header.svelte"; -import Row from "./table-row.svelte"; - -export { - Root, - Body, - Caption, - Cell, - Footer, - Head, - Header, - Row, - // - Root as Table, - Body as TableBody, - Caption as TableCaption, - Cell as TableCell, - Footer as TableFooter, - Head as TableHead, - Header as TableHeader, - Row as TableRow, -}; diff --git a/frontend/app/src/lib/components/ui/table/table-body.svelte b/frontend/app/src/lib/components/ui/table/table-body.svelte deleted file mode 100644 index 29e96875..00000000 --- a/frontend/app/src/lib/components/ui/table/table-body.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/table/table-caption.svelte b/frontend/app/src/lib/components/ui/table/table-caption.svelte deleted file mode 100644 index 4696cff5..00000000 --- a/frontend/app/src/lib/components/ui/table/table-caption.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/table/table-cell.svelte b/frontend/app/src/lib/components/ui/table/table-cell.svelte deleted file mode 100644 index 2c0c26a0..00000000 --- a/frontend/app/src/lib/components/ui/table/table-cell.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/table/table-footer.svelte b/frontend/app/src/lib/components/ui/table/table-footer.svelte deleted file mode 100644 index b9b14ebf..00000000 --- a/frontend/app/src/lib/components/ui/table/table-footer.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -tr]:last:border-b-0", className)} - {...restProps} -> - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/table/table-head.svelte b/frontend/app/src/lib/components/ui/table/table-head.svelte deleted file mode 100644 index b67a6f9b..00000000 --- a/frontend/app/src/lib/components/ui/table/table-head.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/table/table-header.svelte b/frontend/app/src/lib/components/ui/table/table-header.svelte deleted file mode 100644 index f47d2597..00000000 --- a/frontend/app/src/lib/components/ui/table/table-header.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/table/table-row.svelte b/frontend/app/src/lib/components/ui/table/table-row.svelte deleted file mode 100644 index 0df769e0..00000000 --- a/frontend/app/src/lib/components/ui/table/table-row.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -svelte-css-wrapper]:[&>th,td]:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors", - className - )} - {...restProps} -> - {@render children?.()} - diff --git a/frontend/app/src/lib/components/ui/table/table.svelte b/frontend/app/src/lib/components/ui/table/table.svelte deleted file mode 100644 index a3349563..00000000 --- a/frontend/app/src/lib/components/ui/table/table.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - -
    - - {@render children?.()} -
    -
    diff --git a/frontend/app/src/lib/components/ui/tooltip/index.ts b/frontend/app/src/lib/components/ui/tooltip/index.ts deleted file mode 100644 index 17186042..00000000 --- a/frontend/app/src/lib/components/ui/tooltip/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Root from "./tooltip.svelte"; -import Trigger from "./tooltip-trigger.svelte"; -import Content from "./tooltip-content.svelte"; -import Provider from "./tooltip-provider.svelte"; -import Portal from "./tooltip-portal.svelte"; - -export { - Root, - Trigger, - Content, - Provider, - Portal, - // - Root as Tooltip, - Content as TooltipContent, - Trigger as TooltipTrigger, - Provider as TooltipProvider, - Portal as TooltipPortal, -}; diff --git a/frontend/app/src/lib/components/ui/tooltip/tooltip-content.svelte b/frontend/app/src/lib/components/ui/tooltip/tooltip-content.svelte deleted file mode 100644 index 26625228..00000000 --- a/frontend/app/src/lib/components/ui/tooltip/tooltip-content.svelte +++ /dev/null @@ -1,52 +0,0 @@ - - - - - {@render children?.()} - - {#snippet child({ props })} -
    - {/snippet} -
    -
    -
    diff --git a/frontend/app/src/lib/components/ui/tooltip/tooltip-portal.svelte b/frontend/app/src/lib/components/ui/tooltip/tooltip-portal.svelte deleted file mode 100644 index d234f7d7..00000000 --- a/frontend/app/src/lib/components/ui/tooltip/tooltip-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/tooltip/tooltip-provider.svelte b/frontend/app/src/lib/components/ui/tooltip/tooltip-provider.svelte deleted file mode 100644 index 8150bef2..00000000 --- a/frontend/app/src/lib/components/ui/tooltip/tooltip-provider.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/tooltip/tooltip-trigger.svelte b/frontend/app/src/lib/components/ui/tooltip/tooltip-trigger.svelte deleted file mode 100644 index 1acdaa47..00000000 --- a/frontend/app/src/lib/components/ui/tooltip/tooltip-trigger.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/ui/tooltip/tooltip.svelte b/frontend/app/src/lib/components/ui/tooltip/tooltip.svelte deleted file mode 100644 index 0b0f9cef..00000000 --- a/frontend/app/src/lib/components/ui/tooltip/tooltip.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/app/src/lib/components/widgets/combobox/combobox.svelte b/frontend/app/src/lib/components/widgets/combobox/combobox.svelte deleted file mode 100644 index 0c20e807..00000000 --- a/frontend/app/src/lib/components/widgets/combobox/combobox.svelte +++ /dev/null @@ -1,147 +0,0 @@ - - - - - {#snippet child({ props }: { props: Record })} - {@render trigger({ props })} - {/snippet} - - -
    - - 0 - ? `${listboxId}-opt-${clampedIndex}` - : undefined} - /> -
    -
    - {#if filtered.length === 0} -

    {emptyText}

    - {:else} - {#each filtered as option, i (option.value)} - {@const selected = option.value === value} - - {/each} - {/if} -
    -
    -
    diff --git a/frontend/app/src/lib/components/widgets/combobox/index.ts b/frontend/app/src/lib/components/widgets/combobox/index.ts deleted file mode 100644 index bbe1925b..00000000 --- a/frontend/app/src/lib/components/widgets/combobox/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Combobox } from './combobox.svelte'; -export type { ComboboxOption } from './combobox.svelte'; diff --git a/frontend/app/src/lib/components/widgets/filter-dialog/index.ts b/frontend/app/src/lib/components/widgets/filter-dialog/index.ts deleted file mode 100644 index d8f6974c..00000000 --- a/frontend/app/src/lib/components/widgets/filter-dialog/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -export { default as TokenSearchInput } from './token-search-input.svelte'; -export type { FilterAst } from '$lib/filters/ast'; - -export interface FilterOption { - id: string; - label: string; - avatarUrl?: string; -} - -export interface FilterCategory { - key: string; - label: string; - description?: string; - options: FilterOption[]; - condition?: boolean | null; - hideChipPrefix?: boolean; -} - -export type FilterState = Record>; diff --git a/frontend/app/src/lib/components/widgets/filter-dialog/token-search-input.svelte b/frontend/app/src/lib/components/widgets/filter-dialog/token-search-input.svelte deleted file mode 100644 index 0b5be21f..00000000 --- a/frontend/app/src/lib/components/widgets/filter-dialog/token-search-input.svelte +++ /dev/null @@ -1,392 +0,0 @@ - - -{#if mounted} -
    -
    -
    - - - (focused = true)} - onblur={handleBlur} - {placeholder} - class="flex-1 bg-transparent outline-none placeholder:text-muted-foreground font-mono text-sm field-sizing-content min-w-[8rem]" - aria-invalid={hasError} - spellcheck="false" - autocomplete="off" - autocapitalize="off" - autocorrect="off" - /> - - {#if showClear} - - {/if} - - - - {#snippet child({ props })} - - {/snippet} - - -

    Filter syntax

    - -

    Operators

    -
    -
    - And - AND -
    -
    - Or - OR -
    -
    - Not - NOT / - -
    -
    - Multi-value - field:a,b -
    -
    - Grouping - ( â€Ļ ) -
    -
    - -

    Fields

    -
    - {#each visibleCategories as cat (cat.key)} -
    - {cat.label} - {cat.key}:.. -
    - {/each} -
    -
    -
    -
    - - {#if showPopover} -
    -
      - {#each popoverItems as item, i (item.kind === 'key' ? 'k:' + item.category.key : item.kind === 'operator' ? 'op:' + item.label : 'v:' + item.category.key + '/' + item.option.id)} -
    • - -
    • - {/each} -
    -
    - {/if} -
    - {#if hasError} -
    - {errors[0].message} -
    - {/if} -
    -{/if} diff --git a/frontend/app/src/lib/components/widgets/filter-dialog/tokenizer.ts b/frontend/app/src/lib/components/widgets/filter-dialog/tokenizer.ts deleted file mode 100644 index 25e6ca1f..00000000 --- a/frontend/app/src/lib/components/widgets/filter-dialog/tokenizer.ts +++ /dev/null @@ -1,65 +0,0 @@ -export type SuggestMode = - | { kind: 'none' } - | { kind: 'key'; prefix: string; tokenStart: number; tokenEnd: number } - | { - kind: 'value'; - key: string; - partial: string; - tokenStart: number; - valueStart: number; - tokenEnd: number; - }; - -const IDENT = /^[a-zA-Z_][a-zA-Z0-9_]*$/; - -export function suggestMode(draft: string, cursor: number): SuggestMode { - const before = draft.slice(0, cursor); - let tokenStart = before.length; - while (tokenStart > 0 && !/\s/.test(before[tokenStart - 1])) tokenStart--; - const fragment = before.slice(tokenStart); - - let fullTokenEnd = cursor; - while (fullTokenEnd < draft.length && !/\s/.test(draft[fullTokenEnd])) fullTokenEnd++; - if (fragment.length === 0) { - const prevEnd = tokenStart; - let prevStart = prevEnd; - while (prevStart > 0 && !/\s/.test(before[prevStart - 1])) prevStart--; - const prevToken = before.slice(prevStart, prevEnd); - const prevColon = prevToken.indexOf(':'); - if (prevColon !== -1) { - const prevKey = prevToken.slice(0, prevColon); - if (IDENT.test(prevKey) && prevToken.indexOf(':', prevColon + 1) === -1) { - const valueStart = prevStart + prevColon + 1; - return { - kind: 'value', - key: prevKey.toLowerCase(), - partial: '', - tokenStart: prevStart, - valueStart, - tokenEnd: fullTokenEnd - }; - } - } - return { kind: 'none' }; - } - - const colonIdx = fragment.indexOf(':'); - if (colonIdx === -1) { - if (!IDENT.test(fragment)) return { kind: 'none' }; - return { kind: 'key', prefix: fragment, tokenStart, tokenEnd: fullTokenEnd }; - } - const key = fragment.slice(0, colonIdx); - if (!IDENT.test(key)) return { kind: 'none' }; - const valuesPart = fragment.slice(colonIdx + 1); - const lastComma = valuesPart.lastIndexOf(','); - const partial = lastComma === -1 ? valuesPart : valuesPart.slice(lastComma + 1); - const valueStart = tokenStart + colonIdx + 1 + (lastComma === -1 ? 0 : lastComma + 1); - return { - kind: 'value', - key: key.toLowerCase(), - partial, - tokenStart, - valueStart, - tokenEnd: fullTokenEnd - }; -} diff --git a/frontend/app/src/lib/filters/ast.ts b/frontend/app/src/lib/filters/ast.ts deleted file mode 100644 index 9779c238..00000000 --- a/frontend/app/src/lib/filters/ast.ts +++ /dev/null @@ -1,110 +0,0 @@ -// Filter AST — single source of truth for table filters. -// Round-trips with the GitHub-style DSL (added in a later phase) and is -// evaluated server-side via a backend mirror of these types. - -// Source byte range in the DSL string a node was parsed from. Optional because -// ASTs built programmatically (URL re-hydration) have no source — only the -// parser sets it. Used for chip rendering and error highlighting. -export interface SourceSpan { - start: number; - end: number; -} - -export interface FilterIn { - type: 'in'; - field: string; - values: string[]; - span?: SourceSpan; -} - -export interface FilterText { - type: 'text'; - value: string; - span?: SourceSpan; -} - -export interface FilterAnd { - type: 'and'; - children: FilterAst[]; - span?: SourceSpan; -} - -export interface FilterOr { - type: 'or'; - children: FilterAst[]; - span?: SourceSpan; -} - -export interface FilterNot { - type: 'not'; - child: FilterAst; - span?: SourceSpan; -} - -export type FilterAst = FilterIn | FilterText | FilterAnd | FilterOr | FilterNot; - -export function emptyAnd(): FilterAnd { - return { type: 'and', children: [] }; -} - -export function isEmpty(ast: FilterAst): boolean { - if (ast.type === 'and' || ast.type === 'or') return ast.children.length === 0; - if (ast.type === 'in') return ast.values.length === 0; - if (ast.type === 'text') return ast.value.length === 0; - return false; -} - -// True iff the AST is representable as the per-category UI's flat shape: a -// single `in` leaf or `and(in, in, ...)`. The parser collapses singleton ANDs -// to a bare `in` so we accept both forms. Free-text leaves never qualify. -export function isFlatAndOfIn(ast: FilterAst): boolean { - if (ast.type === 'in') return true; - if (ast.type === 'and') return ast.children.every(c => c.type === 'in'); - return false; -} - -// Flatten the top of the AST into its conjuncts so callers can work on each -// piece independently. `and(a, b, c)` → `[a, b, c]`; a bare leaf → `[leaf]`; -// OR/NOT stay opaque (returned as a single child). -export function topLevelConjuncts(ast: FilterAst): FilterAst[] { - if (ast.type === 'and') return [...ast.children]; - return [ast]; -} - -// Combine top-level conjuncts back into a single AST, collapsing singletons. -export function fromConjuncts(children: FilterAst[]): FilterAst { - if (children.length === 0) return { type: 'and', children: [] }; - if (children.length === 1) return children[0]; - return { type: 'and', children }; -} - -export function walk(ast: FilterAst, fn: (node: FilterAst) => void): void { - fn(ast); - if (ast.type === 'and' || ast.type === 'or') { - for (const c of ast.children) walk(c, fn); - } else if (ast.type === 'not') { - walk(ast.child, fn); - } -} - -export function equals(a: FilterAst, b: FilterAst): boolean { - if (a.type !== b.type) return false; - if (a.type === 'in' && b.type === 'in') { - if (a.field !== b.field) return false; - if (a.values.length !== b.values.length) return false; - for (let i = 0; i < a.values.length; i++) { - if (a.values[i] !== b.values[i]) return false; - } - return true; - } - if (a.type === 'text' && b.type === 'text') return a.value === b.value; - if ((a.type === 'and' && b.type === 'and') || (a.type === 'or' && b.type === 'or')) { - if (a.children.length !== b.children.length) return false; - for (let i = 0; i < a.children.length; i++) { - if (!equals(a.children[i], b.children[i])) return false; - } - return true; - } - if (a.type === 'not' && b.type === 'not') return equals(a.child, b.child); - return false; -} diff --git a/frontend/app/src/lib/filters/dsl.ts b/frontend/app/src/lib/filters/dsl.ts deleted file mode 100644 index eda24a07..00000000 --- a/frontend/app/src/lib/filters/dsl.ts +++ /dev/null @@ -1,286 +0,0 @@ -// GitHub-style filter DSL — parse + serialize. -// Grammar (informal): -// expr := or -// or := and ('OR' and)* -// and := term (('AND')? term)* // implicit AND between adjacent terms -// term := '(' expr ')' | ('NOT' | '-') term | leaf -// leaf := IDENT ':' value (',' value)* | value // bare value = free text -// value := unquoted | '"' quoted '"' -// AND/OR/NOT are uppercase keywords; '-' is shorthand for NOT on a single leaf. -// Bare tokens (no `field:`) become free-text leaves; multiple bare tokens -// implicitly AND together. - -import type { FilterAst } from '$lib/filters/ast'; -import { emptyAnd } from '$lib/filters/ast'; - -export interface ParseError { - message: string; - range: [number, number]; -} - -export interface ParseResult { - ast: FilterAst; - errors: ParseError[]; -} - -const IDENT_HEAD = /[a-zA-Z_]/; -const IDENT_TAIL = /[a-zA-Z0-9_]/; -const VALUE_CHAR = /[^\s,()"]/; - -class Parser { - pos = 0; - errors: ParseError[] = []; - - constructor(public input: string) {} - - parse(): ParseResult { - this.skipWs(); - if (this.eof()) return { ast: emptyAnd(), errors: this.errors }; - const ast = this.parseOr(); - this.skipWs(); - if (!this.eof()) { - this.error('Invalid query', this.pos, this.input.length); - } - return { ast, errors: this.errors }; - } - - private parseOr(): FilterAst { - const start = this.pos; - let left = this.parseAnd(); - while (true) { - this.skipWs(); - if (!this.consumeKeyword('OR')) break; - const right = this.parseAnd(); - if (left.type === 'or') { - left.children.push(right); - left.span = { start, end: this.pos }; - } else { - left = { type: 'or', children: [left, right], span: { start, end: this.pos } }; - } - } - return left; - } - - private parseAnd(): FilterAst { - const start = this.pos; - const children: FilterAst[] = [this.parseTerm()]; - while (true) { - this.skipWs(); - if (this.eof()) break; - if (this.peekKeyword('OR')) break; - if (this.peek() === ')') break; - // Optional explicit AND keyword between terms. - this.consumeKeyword('AND'); - this.skipWs(); - if (this.eof()) break; - if (this.peek() === ')') break; - children.push(this.parseTerm()); - } - if (children.length === 1) return children[0]; - return { type: 'and', children, span: { start, end: this.pos } }; - } - - private parseTerm(): FilterAst { - this.skipWs(); - if (this.peek() === '(') { - const parenStart = this.pos; - this.pos++; - const inner = this.parseOr(); - this.skipWs(); - if (this.peek() === ')') this.pos++; - else this.error("Expected ')'", this.pos, this.pos + 1); - // Extend the inner node's span to swallow wrapping parens so chip - // slicing removes them too — otherwise removing `(status:done)` would - // leave dangling `()` in the draft. - inner.span = { start: parenStart, end: this.pos }; - return inner; - } - if (this.peekKeyword('NOT')) { - const notStart = this.pos; - this.consumeKeyword('NOT'); - const child = this.parseTerm(); - return { type: 'not', child, span: { start: notStart, end: this.pos } }; - } - if (this.peek() === '-') { - const notStart = this.pos; - this.pos++; - const child = this.parseLeaf(); - return { type: 'not', child, span: { start: notStart, end: this.pos } }; - } - return this.parseLeaf(); - } - - private parseLeaf(): FilterAst { - // Peek ahead: an IDENT immediately followed by ':' = field leaf. - // Otherwise we consume one value as a free-text leaf. - if (this.looksLikeFieldLeaf()) { - const spanStart = this.pos; - const field = this.parseIdent().toLowerCase(); - this.pos++; // consume ':' (looksLikeFieldLeaf already verified it) - const values = this.parseValueList(); - return { type: 'in', field, values, span: { start: spanStart, end: this.pos } }; - } - // Reserved keywords appearing where a term is expected = syntax error. - // (NOT is intercepted earlier in parseTerm; AND/OR landing here means - // the user wrote a dangling operator.) - for (const kw of ['AND', 'OR', 'NOT']) { - if (this.peekKeyword(kw)) { - this.error(`Unexpected keyword '${kw}'`, this.pos, this.pos + kw.length); - const start = this.pos; - this.pos += kw.length; - return { type: 'text', value: '', span: { start, end: this.pos } }; - } - } - const start = this.pos; - const value = this.parseValue(); - if (value === null) { - this.error('Expected value', start, this.pos + 1); - return { type: 'text', value: '', span: { start, end: this.pos } }; - } - return { type: 'text', value, span: { start, end: this.pos } }; - } - - private looksLikeFieldLeaf(): boolean { - // Can't be a field leaf if it starts with a quote — that's free text. - if (this.peek() === '"') return false; - const save = this.pos; - const ident = this.parseIdent(); - const isField = ident.length > 0 && this.peek() === ':'; - this.pos = save; - return isField; - } - - private parseValueList(): string[] { - const values: string[] = []; - const first = this.parseValue(); - if (first === null) { - this.error('Expected value', this.pos, this.pos + 1); - } else { - values.push(first); - } - while (this.peek() === ',') { - this.pos++; - const next = this.parseValue(); - if (next === null) { - this.error('Expected value after comma', this.pos, this.pos + 1); - break; - } - values.push(next); - } - return values; - } - - private parseValue(): string | null { - if (this.peek() === '"') return this.parseQuoted(); - const start = this.pos; - while (!this.eof() && VALUE_CHAR.test(this.peek())) this.pos++; - if (this.pos === start) return null; - return this.input.slice(start, this.pos); - } - - private parseQuoted(): string { - const start = this.pos; - this.pos++; // opening quote - let out = ''; - while (!this.eof() && this.peek() !== '"') { - if (this.peek() === '\\' && this.pos + 1 < this.input.length) { - out += this.input[this.pos + 1]; - this.pos += 2; - } else { - out += this.input[this.pos]; - this.pos++; - } - } - if (this.peek() === '"') this.pos++; - else this.error('Unterminated quoted string', start, this.pos); - return out; - } - - private parseIdent(): string { - const start = this.pos; - if (this.eof() || !IDENT_HEAD.test(this.peek())) return ''; - while (!this.eof() && IDENT_TAIL.test(this.peek())) this.pos++; - return this.input.slice(start, this.pos); - } - - private consumeKeyword(kw: string): boolean { - if (!this.peekKeyword(kw)) return false; - this.pos += kw.length; - return true; - } - - private peekKeyword(kw: string): boolean { - const slice = this.input.substr(this.pos, kw.length); - if (slice.toUpperCase() !== kw) return false; - const after = this.input[this.pos + kw.length]; - return !after || !IDENT_TAIL.test(after); - } - - private skipWs(): void { - while (!this.eof() && /\s/.test(this.peek())) this.pos++; - } - - private peek(): string { - return this.input[this.pos] ?? ''; - } - - private eof(): boolean { - return this.pos >= this.input.length; - } - - private error(message: string, start: number, end: number): void { - this.errors.push({ message, range: [start, end] }); - } -} - -export function parse(input: string): ParseResult { - return new Parser(input).parse(); -} - -const PREC_OR = 1; -const PREC_AND = 2; -const PREC_NOT = 3; - -const SAFE_VALUE = /^[a-zA-Z0-9_\-./@:][a-zA-Z0-9_\-./@:]*$/; - -function quoteValue(v: string): string { - if (v.length > 0 && SAFE_VALUE.test(v)) return v; - return `"${v.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`; -} - -// Bare-text leaves can't use the field-value safe charset because `:` would -// be reparsed as a field separator and a leading `-` as NOT. -function quoteText(v: string): string { - if (v.length === 0) return '""'; - const needsQuote = /[\s:(),"]/.test(v) || v.startsWith('-'); - if (!needsQuote) return v; - return `"${v.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`; -} - -function serializeNode(ast: FilterAst, parentPrec: number): string { - if (ast.type === 'in') { - if (ast.values.length === 0) return `${ast.field}:`; - return `${ast.field}:${ast.values.map(quoteValue).join(',')}`; - } - if (ast.type === 'text') return quoteText(ast.value); - if (ast.type === 'not') { - // `-leaf` shorthand for in/text leaves; otherwise `NOT (...)`. - if (ast.child.type === 'in' || ast.child.type === 'text') { - return `-${serializeNode(ast.child, PREC_NOT)}`; - } - return `NOT ${serializeNode(ast.child, PREC_NOT)}`; - } - if (ast.type === 'and') { - if (ast.children.length === 0) return ''; - const body = ast.children.map(c => serializeNode(c, PREC_AND)).join(' '); - return parentPrec > PREC_AND ? `(${body})` : body; - } - // or - if (ast.children.length === 0) return ''; - const body = ast.children.map(c => serializeNode(c, PREC_OR)).join(' OR '); - return parentPrec > PREC_OR ? `(${body})` : body; -} - -export function serialize(ast: FilterAst): string { - return serializeNode(ast, 0); -} diff --git a/frontend/app/src/lib/filters/legacy.ts b/frontend/app/src/lib/filters/legacy.ts deleted file mode 100644 index 02260724..00000000 --- a/frontend/app/src/lib/filters/legacy.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Adapters between the legacy per-category FilterState and the AST. -// Only handles the flat and-of-in shape — non-flat ASTs (or, not, nesting) -// produced by Query mode collapse to an empty FilterState here. - -import type { FilterState } from '$lib/components/widgets/filter-dialog'; -import type { FilterAst, FilterAnd, FilterIn } from '$lib/filters/ast'; - -export function astFromFilterState(state: FilterState): FilterAnd { - const children: FilterIn[] = []; - for (const [field, values] of Object.entries(state)) { - if (!values || values.size === 0) continue; - children.push({ type: 'in', field, values: [...values] }); - } - return { type: 'and', children }; -} - -export function filterStateFromAst(ast: FilterAst, categoryKeys: string[]): FilterState { - const result: FilterState = {}; - for (const k of categoryKeys) result[k] = new Set(); - if (ast.type !== 'and') return result; - for (const c of ast.children) { - if (c.type !== 'in') continue; - const set = result[c.field] ?? new Set(); - for (const v of c.values) set.add(v); - result[c.field] = set; - } - return result; -} diff --git a/frontend/app/src/lib/hooks/is-mobile.svelte.ts b/frontend/app/src/lib/hooks/is-mobile.svelte.ts deleted file mode 100644 index 4829c00b..00000000 --- a/frontend/app/src/lib/hooks/is-mobile.svelte.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { MediaQuery } from "svelte/reactivity"; - -const DEFAULT_MOBILE_BREAKPOINT = 768; - -export class IsMobile extends MediaQuery { - constructor(breakpoint: number = DEFAULT_MOBILE_BREAKPOINT) { - super(`max-width: ${breakpoint - 1}px`); - } -} diff --git a/frontend/app/src/lib/reports/filterHelpers.ts b/frontend/app/src/lib/reports/filterHelpers.ts deleted file mode 100644 index 010fca3f..00000000 --- a/frontend/app/src/lib/reports/filterHelpers.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Helpers for parsing/building `country in ['XX', ...]` pandas-query fragments - * used by plot and explore card parameters. Shared by PlotEditorDialog and - * ExploreEditorDialog to keep the wire format in one place. - */ - -const COUNTRY_RE = /country in \[(.+)]/; - -export function parseCountriesFromQuery( - query: string | undefined, - availableCountries: string[] | undefined, -): Set { - if (!query) return new Set((availableCountries ?? []).filter(Boolean)); - const match = query.match(COUNTRY_RE); - if (match) { - return new Set( - match[1] - .split(',') - .map((c) => c.trim().replace(/'/g, '')) - .filter(Boolean), - ); - } - return new Set(availableCountries ?? []); -} - -/** - * Build a `country in ['XX', ...]` fragment, or undefined when the selection - * is empty or covers every country (no filter needed). - */ -export function buildCountryQuery( - selected: Iterable, - availableCountries: string[] | undefined, -): string | undefined { - const validSelected = Array.from(selected).filter(Boolean); - const validAvailable = (availableCountries ?? []).filter(Boolean); - if (validSelected.length > 0 && validSelected.length < validAvailable.length) { - const formatted = validSelected.map((c) => `'${c}'`).join(', '); - return `country in [${formatted}]`; - } - return undefined; -} diff --git a/frontend/app/src/lib/reports/overview.yaml b/frontend/app/src/lib/reports/overview.yaml deleted file mode 100644 index 89516553..00000000 --- a/frontend/app/src/lib/reports/overview.yaml +++ /dev/null @@ -1,47 +0,0 @@ -name: Overview -cards: -- type: overview - x: 0 - y: 0 - w: 5 - h: 4 -- type: plot - statistic: energy_balance - plotType: area - parameters: {} - x: 0 - y: 4 - w: 8 - h: 5 -- type: plot - statistic: energy_balance - plotType: bar - parameters: {} - x: 8 - y: 4 - w: 8 - h: 5 -- type: plot - statistic: installed_capacity - plotType: bar - parameters: {} - x: 16 - y: 4 - w: 8 - h: 5 -- type: plot - statistic: capex - plotType: bar - parameters: {} - x: 0 - y: 9 - w: 8 - h: 5 -- type: plot - statistic: opex - plotType: bar - parameters: {} - x: 8 - y: 9 - w: 8 - h: 5 diff --git a/frontend/app/src/lib/stores/auth.svelte.ts b/frontend/app/src/lib/stores/auth.svelte.ts deleted file mode 100644 index 7ebee699..00000000 --- a/frontend/app/src/lib/stores/auth.svelte.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { auth, type AuthProviderInfo } from '$lib/api/client.js'; -import type { User, ApiError, Permission } from '$lib/types.js'; - -class AuthStore { - user: User | null = $state(null); - loading: boolean = $state(true); - error: string | null = $state(null); - authEnabled: boolean | null = $state(null); - providers: AuthProviderInfo[] = $state([]); - - async init(): Promise { - this.loading = true; - this.error = null; - - try { - const { providers } = await auth.providers(); - this.providers = providers; - this.authEnabled = providers.length > 0; - - if (this.authEnabled) { - try { - const response = await auth.me(); - this.user = response; - } catch (err) { - const apiErr = err as ApiError; - if (apiErr.status === 400 || apiErr.status === 401) { - this.user = null; - } else { - console.error('Failed to fetch user:', err); - this.error = apiErr.message; - } - } - } - } catch (err) { - console.error('Failed to fetch auth providers:', err); - this.authEnabled = false; - this.error = (err as Error).message; - } finally { - this.loading = false; - } - } - - async refreshUser(): Promise { - try { - this.user = await auth.me(); - } catch (err) { - const apiErr = err as ApiError; - if (apiErr.status === 400 || apiErr.status === 401) { - this.user = null; - } else { - console.error('Failed to refresh user:', err); - } - } - } - - async logout(): Promise { - this.loading = true; - try { - auth.logout(); - } catch (err) { - console.error('Logout failed:', err); - this.error = (err as Error).message; - this.loading = false; - } - } - - get isAuthenticated(): boolean { - return this.user !== null; - } - - get displayName(): string { - return this.user?.username || 'User'; - } - - get avatarUrl(): string | null { - return this.user?.avatar_url || null; - } - - get permissions(): string[] { - return this.user?.permissions || []; - } - - hasPermission(permission: Permission): boolean { - return this.permissions.includes(permission); - } - - get isAdmin(): boolean { - return this.hasPermission('users:manage'); - } - - get isApproved(): boolean { - return this.permissions.length > 0; - } - - get isPending(): boolean { - return this.isAuthenticated && !this.isApproved; - } -} - -export const authStore = new AuthStore(); diff --git a/frontend/app/src/lib/stores/breadcrumb.svelte.ts b/frontend/app/src/lib/stores/breadcrumb.svelte.ts deleted file mode 100644 index 8f6e607c..00000000 --- a/frontend/app/src/lib/stores/breadcrumb.svelte.ts +++ /dev/null @@ -1,13 +0,0 @@ -let subItems = $state<{ label: string; href?: string }[]>([]); - -export const breadcrumbStore = { - get items() { - return subItems; - }, - set(items: { label: string; href?: string }[]) { - subItems = items; - }, - clear() { - subItems = []; - } -}; diff --git a/frontend/app/src/lib/stores/features.svelte.ts b/frontend/app/src/lib/stores/features.svelte.ts deleted file mode 100644 index 903f6728..00000000 --- a/frontend/app/src/lib/stores/features.svelte.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { version } from '$lib/api/client.js'; - -export const features = $state({ runsEnabled: false, localMode: false, demoMode: false }); - -export async function initFeatures(): Promise { - const response = await version.get(); - features.runsEnabled = Boolean(response.runs_enabled); - features.localMode = Boolean(response.local_mode); - features.demoMode = Boolean(response.demo_mode); -} diff --git a/frontend/app/src/lib/stores/networkPageStore.ts b/frontend/app/src/lib/stores/networkPageStore.ts deleted file mode 100644 index a1fb1069..00000000 --- a/frontend/app/src/lib/stores/networkPageStore.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { writable, derived } from "svelte/store"; -import type { Network } from "$lib/types.js"; - -// Network selection state -export const selectedNetworkIds = writable>(new Set()); -export const networksList = writable([]); -export const loadingNetworks = writable(true); - -// Derived state -export const selectedNetworks = derived( - [networksList, selectedNetworkIds], - ([$networksList, $selectedNetworkIds]) => { - return $networksList.filter((network) => - $selectedNetworkIds.has(network.id), - ); - }, -); - -export const hasSelection = derived( - selectedNetworkIds, - ($ids) => $ids.size > 0, -); - -// Actions -export function selectNetwork(networkId: string): void { - selectedNetworkIds.set(new Set([networkId])); -} - -export function clearSelection(): void { - selectedNetworkIds.set(new Set()); -} diff --git a/frontend/app/src/lib/stores/reportStore.svelte.ts b/frontend/app/src/lib/stores/reportStore.svelte.ts deleted file mode 100644 index ebe2cb00..00000000 --- a/frontend/app/src/lib/stores/reportStore.svelte.ts +++ /dev/null @@ -1,394 +0,0 @@ -import yaml from 'js-yaml'; -import overviewYaml from '$lib/reports/overview.yaml?raw'; -import { networks } from '$lib/api/client.js'; -import { features } from '$lib/stores/features.svelte.js'; - -interface CardBase { - id: string; - name?: string; - x: number; - y: number; - w: number; - h: number; -} - -export interface PlotCardDefinition extends CardBase { - type: 'plot'; - statistic: string; - plotType: string; - parameters: { - bus_carrier?: string[]; - query?: string; - }; - expandBy?: 'bus_carrier' | 'country'; -} - -export interface MarkdownCardDefinition extends CardBase { - type: 'markdown'; - content: string; -} - -export interface ExploreCardDefinition extends CardBase { - type: 'explore'; - bus_carrier?: string[]; - query?: string; - branch_components?: string[]; - geometry?: boolean; -} - -/** @deprecated Use ExploreCardDefinition */ -export interface MapCardDefinition extends CardBase { - type: 'map'; - parameters: Record; -} - -export interface OverviewCardDefinition extends CardBase { - type: 'overview'; -} - -export interface ComponentTableCardDefinition extends CardBase { - type: 'component_table'; - component: string; -} - -export type CardDefinition = - | PlotCardDefinition - | MarkdownCardDefinition - | ExploreCardDefinition - | MapCardDefinition - | OverviewCardDefinition - | ComponentTableCardDefinition; - -/** @deprecated Use PlotCardDefinition */ -export type PlotDefinition = PlotCardDefinition; - -export interface Report { - id: string; - name: string; - cards: CardDefinition[]; - isDefault: boolean; -} - -// Mirror of backend ALLOWED_STATISTICS with human-readable labels -export const STATISTICS: { value: string; label: string }[] = [ - { value: 'energy_balance', label: 'Energy Balance' }, - { value: 'installed_capacity', label: 'Installed Capacity' }, - { value: 'optimal_capacity', label: 'Optimal Capacity' }, - { value: 'expanded_capacity', label: 'Expanded Capacity' }, - { value: 'capex', label: 'CAPEX' }, - { value: 'installed_capex', label: 'Installed CAPEX' }, - { value: 'expanded_capex', label: 'Expanded CAPEX' }, - { value: 'opex', label: 'OPEX' }, - { value: 'system_cost', label: 'System Cost' }, - { value: 'revenue', label: 'Revenue' }, - { value: 'market_value', label: 'Market Value' }, - { value: 'supply', label: 'Supply' }, - { value: 'withdrawal', label: 'Withdrawal' }, - { value: 'curtailment', label: 'Curtailment' }, - { value: 'capacity_factor', label: 'Capacity Factor' }, - { value: 'transmission', label: 'Transmission' }, - { value: 'prices', label: 'Prices' }, -]; - -export const CHART_TYPES: { value: string; label: string }[] = [ - { value: 'area', label: 'Area' }, - { value: 'bar', label: 'Bar' }, - { value: 'line', label: 'Line' }, -]; - -function uid(): string { - return crypto.randomUUID(); -} - -function loadDefaultReport(): Report { - const raw = yaml.load(overviewYaml) as { name: string; cards: Omit[] }; - return { - id: 'default-overview', - name: raw.name, - isDefault: true, - cards: raw.cards.map((c) => ({ ...c, id: uid() }) as CardDefinition), - }; -} - -export interface ReportState { - reports: Report[]; - activeReportId: string; -} - -function defaultState(): ReportState { - return { reports: [loadDefaultReport()], activeReportId: 'default-overview' }; -} - -function migrateState(state: ReportState): ReportState { - for (const report of state.reports) { - // Migrate old row-based format to flat cards - if ('rows' in report && !('cards' in report) && !('plots' in report)) { - const rows = (report as any).rows as { id: string; plots: any[] }[]; - let y = 0; - const cards: CardDefinition[] = []; - for (const row of rows) { - const w = Math.floor(24 / row.plots.length); - const h = Math.max(3, Math.round((row.plots[0]?.height ?? 400) / 80)); - for (let i = 0; i < row.plots.length; i++) { - const p = row.plots[i]; - cards.push({ - id: p.id, - type: 'plot', - statistic: p.statistic, - plotType: p.plotType, - parameters: p.parameters, - x: i * w, - y, - w, - h, - }); - } - y += h; - } - (report as any).cards = cards; - delete (report as any).rows; - } - - // Migrate plots → cards - if ('plots' in report && !('cards' in report)) { - (report as any).cards = ((report as any).plots as any[]).map((p: any) => ({ - ...p, - type: p.type ?? 'plot', - })); - delete (report as any).plots; - } - } - - // Clean empty/none values from plot card parameters - for (const report of state.reports) { - if (!('cards' in report)) continue; - for (const card of report.cards) { - if (card.type !== 'plot' && (card as any).type !== undefined && (card as any).statistic === undefined) continue; - // Ensure type field exists on old data - if (!card.type) (card as any).type = 'plot'; - if (card.type !== 'plot') continue; - const plot = card as PlotCardDefinition; - if (plot.parameters?.bus_carrier) { - plot.parameters.bus_carrier = plot.parameters.bus_carrier.filter( - (c: string) => c && c !== 'none', - ); - if (plot.parameters.bus_carrier.length === 0) delete plot.parameters.bus_carrier; - } - if (plot.parameters?.query) { - const match = plot.parameters.query.match(/country in \[(.+)]/); - if (match) { - const raw = match[1] - .split(',') - .map((c: string) => c.trim().replace(/'/g, '')); - const cleaned = raw.filter((c: string) => c && c !== 'none'); - if (cleaned.length < raw.length) { - delete plot.parameters.query; - } - } - } - } - } - - // Migrate map cards → explore cards - for (const report of state.reports) { - if (!('cards' in report) || !Array.isArray(report.cards)) continue; - report.cards = report.cards.map((c) => { - if (c.type === 'map') { - return { ...c, type: 'explore' } as unknown as CardDefinition; - } - return c; - }); - } - - // Prepend overview card to default report if missing (migrates pre-overview-card state) - for (const report of state.reports) { - if (!report.isDefault && report.id !== 'default-overview') continue; - if (!('cards' in report) || !Array.isArray(report.cards)) continue; - - const existing = report.cards.find((c) => c.type === 'overview'); - if (!existing) { - const overviewCard: OverviewCardDefinition = { - id: uid(), - type: 'overview', - x: 0, - y: 0, - w: 5, - h: 4, - }; - const shifted = report.cards.map((c) => ({ ...c, y: c.y + 4 })); - report.cards = [overviewCard, ...shifted]; - } else if (existing.h <= 2) { - const delta = 4 - existing.h; - existing.h = 4; - for (const c of report.cards) { - if (c.id !== existing.id && c.y >= existing.y + 2) c.y += delta; - } - } - } - - return state; -} - -function createReportStore() { - let state = $state(defaultState()); - let currentNetworkId = $state(null); - let loading = $state(false); - - const DEBOUNCE_MS = 1500; - let pendingTimer: ReturnType | undefined; - let pendingNetworkId: string | undefined; - let pendingPayload: ReportState | undefined; - let initialized = false; - - function saveForNetwork(networkId: string, payload: ReportState) { - fetch(`/api/v1/networks/${networkId}/reports`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(payload), - keepalive: true, - credentials: 'include', - }).catch((e) => console.error('Failed to save reports:', e)); - } - - function flush() { - if (pendingTimer !== undefined) clearTimeout(pendingTimer); - pendingTimer = undefined; - if (pendingNetworkId && pendingPayload) { - saveForNetwork(pendingNetworkId, pendingPayload); - pendingPayload = undefined; - pendingNetworkId = undefined; - } - } - - function schedule(networkId: string, payload: ReportState) { - if (features.demoMode) return; - if (!initialized) { initialized = true; return; } - pendingNetworkId = networkId; - pendingPayload = payload; - if (pendingTimer !== undefined) clearTimeout(pendingTimer); - pendingTimer = setTimeout(flush, DEBOUNCE_MS); - } - - if (typeof window !== 'undefined') { - $effect.root(() => { - $effect(() => { - const snapshot = $state.snapshot(state); - if (!currentNetworkId) return; - schedule(currentNetworkId, snapshot); - }); - }); - - window.addEventListener('beforeunload', flush); - document.addEventListener('visibilitychange', () => { - if (document.visibilityState === 'hidden') flush(); - }); - } - - return { - get reports() { - return state.reports; - }, - get activeReport(): Report { - return state.reports.find((r) => r.id === state.activeReportId) ?? state.reports[0]; - }, - get activeReportId() { - return state.activeReportId; - }, - get loading() { - return loading; - }, - get currentNetworkId() { - return currentNetworkId; - }, - - async loadForNetwork(networkId: string) { - flush(); - - currentNetworkId = networkId; - loading = true; - initialized = false; - - try { - const saved = await networks.getReports(networkId); - if (currentNetworkId !== networkId) return; - - if (saved) { - state = migrateState(saved); - } else { - state = defaultState(); - } - } catch { - if (currentNetworkId !== networkId) return; - state = defaultState(); - } finally { - if (currentNetworkId === networkId) { - loading = false; - } - } - }, - - setActiveReport(id: string) { - state.activeReportId = id; - }, - addReport(name: string, cards?: Omit[]): Report { - const report: Report = { - id: uid(), - name, - isDefault: false, - cards: cards ? cards.map((c) => ({ ...c, id: uid() }) as CardDefinition) : [], - }; - state.reports = [...state.reports, report]; - state.activeReportId = report.id; - return report; - }, - removeReport(id: string) { - state.reports = state.reports.filter((r) => r.id !== id); - if (state.activeReportId === id) { - state.activeReportId = state.reports[0]?.id ?? ''; - } - }, - updateCard(reportId: string, cardId: string, updates: Partial | Partial | Partial | Partial) { - state.reports = state.reports.map((r) => { - if (r.id !== reportId) return r; - return { - ...r, - cards: r.cards.map((c) => (c.id === cardId ? { ...c, ...updates } as CardDefinition : c)), - }; - }); - }, - addCard(reportId: string, card: CardDefinition) { - state.reports = state.reports.map((r) => { - if (r.id !== reportId) return r; - return { ...r, cards: [...r.cards, card] }; - }); - }, - removeCard(reportId: string, cardId: string) { - state.reports = state.reports.map((r) => { - if (r.id !== reportId) return r; - return { ...r, cards: r.cards.filter((c) => c.id !== cardId) }; - }); - }, - updateLayout(reportId: string, items: { id: string; x: number; y: number; w: number; h: number }[]) { - state.reports = state.reports.map((r) => { - if (r.id !== reportId) return r; - return { - ...r, - cards: r.cards.map((c) => { - const item = items.find((i) => i.id === c.id); - return item ? { ...c, x: item.x, y: item.y, w: item.w, h: item.h } : c; - }), - }; - }); - }, - renameReport(id: string, name: string) { - state.reports = state.reports.map((r) => - r.id === id ? { ...r, name } : r, - ); - }, - resetToDefaults() { - state = defaultState(); - }, - }; -} - -export const reportStore = createReportStore(); diff --git a/frontend/app/src/lib/stores/sidebar.svelte.ts b/frontend/app/src/lib/stores/sidebar.svelte.ts deleted file mode 100644 index 0c8943cf..00000000 --- a/frontend/app/src/lib/stores/sidebar.svelte.ts +++ /dev/null @@ -1,10 +0,0 @@ -let open = $state(true); - -export const sidebarStore = { - get open() { - return open; - }, - set open(value: boolean) { - open = value; - } -}; diff --git a/frontend/app/src/lib/types.ts b/frontend/app/src/lib/types.ts deleted file mode 100644 index 3729106b..00000000 --- a/frontend/app/src/lib/types.ts +++ /dev/null @@ -1,357 +0,0 @@ -// API response types -// - -export interface User { - id: string; - username: string; - email?: string; - avatar_url?: string; - permissions: string[]; - role: string; - created_at?: string; - last_login?: string; -} - -export interface ApiKey { - id: string; - name: string; - key_prefix: string; - owner: User; - created_at: string; - last_used_at?: string; - expires_at?: string; - key?: string; -} - -export interface NetworkTag { - name: string; - url?: string; -} - -export interface Carrier { - name: string; - nice_name?: string; -} - -export interface TimestepsInfo { - count: number; - start?: string; - end?: string; - freq?: string; -} - -export interface PeriodsInfo { - count: number; - values: (number | string)[]; - truncated?: boolean; -} - -export interface ScenariosInfo { - count: number; - names: string[]; - truncated?: boolean; -} - -export interface DimensionsInfo { - timesteps: TimestepsInfo; - periods: PeriodsInfo; - scenarios: ScenariosInfo; -} - -export interface Network { - id: string; - name?: string; - filename: string; - file_size?: number; - visibility: Visibility; - owner: User; - source_run_id?: string; - dimensions?: DimensionsInfo; - components_count?: Record; - tags?: (string | NetworkTag)[]; - update_history?: string[]; - created_at?: string; - is_external?: boolean; - file_path?: string; - file_missing?: boolean; -} - -export type Visibility = "public" | "private"; - -export interface BackendPublic { - id: string; - name: string; - is_active: boolean; -} - -export interface Backend extends BackendPublic { - url: string; - created_at: string; - updated_at?: string; -} - -export type RunStatus = "PENDING" | "SETUP" | "RUNNING" | "UPLOADING" | "COMPLETED" | "FAILED" | "ERROR" | "CANCELLED"; - -/** Statuses where the run will not change further (no polling needed). */ -export const RUN_FINAL_STATUSES: ReadonlySet = new Set(["COMPLETED", "FAILED", "ERROR", "CANCELLED"]); - -/** Statuses where user actions (cancel, remove) are no longer available. */ -export const RUN_SETTLED_STATUSES: ReadonlySet = new Set(["UPLOADING", "COMPLETED", "FAILED", "ERROR", "CANCELLED"]); - -export interface RunNetwork { - id: string; - name: string | null; - filename: string; - source_path?: string | null; -} - -export interface UserPublic { - id: string; - username: string; - avatar_url?: string; -} - -export interface RunSummary { - id: string; - status: RunStatus; - workflow: string; - configfile?: string; - git_ref?: string; - git_sha?: string; - started_at?: string; - completed_at?: string; - created_at: string; - owner: UserPublic; - visibility: Visibility; - backend: BackendPublic; - total_job_count?: number; - jobs_finished?: number; -} - -export interface Run extends RunSummary { - snakemake_args?: string[]; - extra_files?: Record; - cache?: { key: string; dirs: string[] }; - import_networks?: string[]; - - networks: RunNetwork[]; -} - -export interface TaskStatus { - task_id: string; - state: "PENDING" | "STARTED" | "SUCCESS" | "FAILURE"; - result?: TaskResult; - error?: string; -} - -export interface TaskResult { - status?: "success" | "error"; - data?: PlotData; - error?: string; - error_details?: { - parameters?: Record; - stack_trace?: string; - }; - generated_at?: string; - request?: { - statistic?: string; - plot_type?: string; - }; -} - -export interface OutputFile { - path: string; - size: number; -} - -export type PlotData = Record; - -export interface PlotResponse { - plot_data: PlotData; - cached: boolean; - generated_at?: string; - statistic?: string; - plot_type?: string; -} - -export interface StatisticsRequest { - network_ids: string[]; - statistic: string; - parameters: Record; -} - -export interface PlotRequest { - network_ids: string[]; - statistic: string; - plot_type: string; - parameters: Record; -} - -export interface VersionInfo { - version: string; - pypsa_version?: string; - local_mode?: boolean; - runs_enabled?: boolean; - [key: string]: unknown; -} - -export interface HealthStatus { - status: string; - [key: string]: unknown; -} - -export interface NetworkUpdate { - visibility?: Visibility; - user_id?: string; -} - -// Paginated response types - -export interface ListMeta { - total: number; - offset: number; - limit: number; - count: number; -} - -export interface NetworkListMeta extends ListMeta { - owners?: User[]; -} - -export interface RunListMeta extends ListMeta { - statuses?: string[]; - workflows?: string[]; - owners?: User[]; - git_refs?: string[]; - configfiles?: string[]; - backends?: BackendPublic[]; -} - -export interface PaginatedResponse { - data: T[]; - meta: M; -} - -// Store types - -export interface AuthState { - user: User | null; - loading: boolean; - error: string | null; - authEnabled: boolean | null; -} - -// Shared utility types - -export type TagType = "default" | "config" | "version" | "model"; -export type TagColor = "tag-model" | "tag-version" | "tag-config" | "tag-default"; -export type Permission = string; - -// Workflow types - -export interface WorkflowFile { - path: string; - file_type: string; -} - -export interface WorkflowJob { - snakemake_id: number; - rule: string; - status: string; - wildcards: Record | null; - threads: number; - started_at?: string; - completed_at?: string; - files: WorkflowFile[]; - log?: string; -} - -export interface WorkflowRule { - name: string; - total_job_count: number; - jobs_finished: number; - jobs: WorkflowJob[]; -} - -export interface WorkflowError { - timestamp: string; - exception: string; - rule: string | null; - traceback: string | null; -} - -export interface RulegraphNode { - rule: string; -} - -export interface RulegraphLink { - source: number; - target: number; - sourcerule: string; - targetrule: string; -} - -export interface Rulegraph { - nodes: RulegraphNode[]; - links: RulegraphLink[]; -} - -export interface Workflow { - workflow_id: string; - status: string; - total_job_count: number; - jobs_finished: number; - rulegraph: Rulegraph | null; - rules: WorkflowRule[]; - errors: WorkflowError[]; -} - -// Component data response - -export interface ComponentDataResponse { - component: string; - columns: string[]; - dtypes: Record; - index: string[]; - data: unknown[][]; - total: number; - offset: number; - limit: number; -} - -// API error type - -export interface UserStatsResponse { - networks_count: number; - runs_total: number; - runs_by_status: Record; - runs_by_backend: Record; - total_storage_bytes: number; - last_activity: string | null; -} - -export interface ApiError extends Error { - status?: number; - cancelled?: boolean; -} - -// Public (unauthenticated) response types - -export interface PublicRunResponse { - id: string; - status: RunStatus; - workflow: string; - configfile?: string; - git_ref?: string; - git_sha?: string; - created_at: string; - started_at?: string; - completed_at?: string; - - total_job_count?: number; - jobs_finished?: number; - visibility: Visibility; - owner: UserPublic; - backend: BackendPublic; - networks: RunNetwork[]; -} diff --git a/frontend/app/src/lib/utils.ts b/frontend/app/src/lib/utils.ts deleted file mode 100644 index 81eef0ae..00000000 --- a/frontend/app/src/lib/utils.ts +++ /dev/null @@ -1,261 +0,0 @@ -import { browser } from '$app/environment'; -import { clsx, type ClassValue } from "clsx"; -import { twMerge } from "tailwind-merge"; -import type { VisibilityState } from '@tanstack/table-core'; -import { toast } from 'svelte-sonner'; -import type { NetworkTag, TagType, TagColor, User } from "./types.js"; -import type { FilterOption } from '$lib/components/widgets/filter-dialog'; - -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 }; - -/** - * Copy text to clipboard with success/error toast. - */ -export async function copyToClipboard(text: string): Promise { - try { - await navigator.clipboard.writeText(text); - toast.success('Copied to clipboard'); - } catch { - toast.error('Failed to copy to clipboard'); - } -} - -/** - * Load persisted table preferences (pageSize, columnVisibility) from localStorage. - */ -export function loadTablePrefs(prefix: string): { - pageSize: number | null; - columnVisibility: VisibilityState | null; -} { - if (!browser) return { pageSize: null, columnVisibility: null }; - const raw = localStorage.getItem(`${prefix}PageSize`); - const pageSize = raw ? parseInt(raw) : null; - let columnVisibility: VisibilityState | null = null; - const savedVis = localStorage.getItem(`${prefix}ColumnVisibility`); - if (savedVis) { - try { columnVisibility = JSON.parse(savedVis); } catch { /* use default */ } - } - return { pageSize: isNaN(pageSize as number) ? null : pageSize, columnVisibility }; -} - -/** - * Save a single table preference to localStorage. - */ -export function saveTablePref(prefix: string, key: 'pageSize' | 'columnVisibility', value: number | VisibilityState): void { - if (!browser) return; - const storageKey = `${prefix}${key === 'pageSize' ? 'PageSize' : 'ColumnVisibility'}`; - localStorage.setItem(storageKey, typeof value === 'number' ? value.toString() : JSON.stringify(value)); -} - -/** - * Correct page if it exceeds total pages; returns null if no change needed. - */ -export function clampPage(page: number, pageSize: number, total: number): number | null { - const totalPages = Math.ceil(total / pageSize); - if (page > totalPages && totalPages > 0) { - return totalPages; - } - return null; -} - -/** - * Build owner filter options with the current user listed first. - */ -export function buildOwnerOptions(availableOwners: User[], currentUsername?: string): FilterOption[] { - const opts: FilterOption[] = []; - const currentUserInOwners = availableOwners.find(o => o.username === currentUsername); - if (currentUserInOwners) { - opts.push({ id: currentUserInOwners.username, label: currentUserInOwners.username, avatarUrl: currentUserInOwners.avatar_url }); - } - for (const owner of availableOwners) { - if (owner.username !== currentUsername) { - opts.push({ id: owner.username, label: owner.username, avatarUrl: owner.avatar_url }); - } - } - return opts; -} - -export function formatFileSize(bytes: number | null | undefined): string { - if (bytes === null || bytes === undefined || bytes === 0) return '—'; - if (bytes < 1024) return `${bytes} B`; - if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; - if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; - return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`; -} - -export function parseUTCDate(dateString: string): Date { - return new Date(dateString.endsWith('Z') ? dateString : dateString + 'Z'); -} - -export function formatDate(dateString: string | null | undefined): string { - if (!dateString) return '—'; - const date = parseUTCDate(dateString); - return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour12: false }); -} - -function formatSeconds(seconds: number): string { - if (seconds < 60) return `${seconds}s`; - const minutes = Math.floor(seconds / 60); - const secs = seconds % 60; - if (minutes < 60) return `${minutes}m ${secs}s`; - const hours = Math.floor(minutes / 60); - const mins = minutes % 60; - if (hours >= 24) { - const days = Math.floor(hours / 24); - const hrs = hours % 24; - return `${days}d ${hrs}h`; - } - return `${hours}h ${mins}m`; -} - -export function formatDuration(startedAt: string | null | undefined, completedAt?: string | null): string | null { - if (!startedAt) return null; - const start = parseUTCDate(startedAt); - const end = completedAt ? parseUTCDate(completedAt) : new Date(); - return formatSeconds(Math.floor((end.getTime() - start.getTime()) / 1000)); -} - -export function formatRelativeTime(dateString: string | null | undefined): string { - if (!dateString) return '—'; - const date = parseUTCDate(dateString); - const now = new Date(); - const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000); - - if (diffInSeconds < 60) return 'just now'; - if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`; - if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`; - if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`; - if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 604800)}w ago`; - if (diffInSeconds < 31536000) return `${Math.floor(diffInSeconds / 2592000)}mo ago`; - return `${Math.floor(diffInSeconds / 31536000)}y ago`; -} - -export function formatRelativeTimeDetailed(dateString: string | null | undefined): string { - if (!dateString) return '—'; - const date = parseUTCDate(dateString); - const now = new Date(); - const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000); - - if (diffInSeconds < 60) return 'just now'; - if (diffInSeconds < 3600) { - const minutes = Math.floor(diffInSeconds / 60); - return `${minutes} ${minutes === 1 ? 'minute' : 'minutes'} ago`; - } - if (diffInSeconds < 86400) { - const hours = Math.floor(diffInSeconds / 3600); - const mins = Math.floor((diffInSeconds % 3600) / 60); - const hLabel = hours === 1 ? 'hour' : 'hours'; - if (mins === 0) return `${hours} ${hLabel} ago`; - return `${hours} ${hLabel}, ${mins} ${mins === 1 ? 'minute' : 'minutes'} ago`; - } - const days = Math.floor(diffInSeconds / 86400); - const hours = Math.floor((diffInSeconds % 86400) / 3600); - const dLabel = days === 1 ? 'day' : 'days'; - if (hours === 0) return `${days} ${dLabel} ago`; - return `${days} ${dLabel}, ${hours} ${hours === 1 ? 'hour' : 'hours'} ago`; -} - -export function formatDurationMs(ms: number): string { - return formatSeconds(Math.round(ms / 1000)); -} - -/** tanstack-table sortingFn that sorts rows by a nullable ISO date field. */ -export function byDate(getField: (row: T) => string | null | undefined) { - return (rowA: { original: T }, rowB: { original: T }) => { - const a = getField(rowA.original); - const b = getField(rowB.original); - const ta = a ? new Date(a).getTime() : 0; - const tb = b ? new Date(b).getTime() : 0; - return ta - tb; - }; -} - -export function formatNumber(num: number): string { - if (num >= 1000) return (num / 1000).toFixed(1) + 'k'; - return num.toString(); -} - -/** Format ISO date as `YYYY-MM-DD`. */ -export function formatStripDateFull(iso: string): string { - const d = parseUTCDate(iso); - if (isNaN(d.getTime())) return iso; - const pad = (n: number) => n.toString().padStart(2, '0'); - return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`; -} - -/** Format ISO date as `YYYY-MM`. */ -export function formatStripDateShort(iso: string): string { - const d = parseUTCDate(iso); - if (isNaN(d.getTime())) return iso; - const pad = (n: number) => n.toString().padStart(2, '0'); - return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}`; -} - -const PANDAS_FREQ_MAP: Record = { - h: '1h', - H: '1h', - D: '1d', - W: 'weekly', - ME: 'monthly', - M: 'monthly', - MS: 'monthly', - QE: 'quarterly', - Q: 'quarterly', - QS: 'quarterly', - YS: 'yearly', - YE: 'yearly', - Y: 'yearly', - A: 'yearly', - AS: 'yearly', -}; - -/** Map a pandas freq alias to a human label. Returns null for null/undefined input. */ -export function formatPandasFreq(freq: string | undefined | null): string | null { - if (!freq) return null; - if (PANDAS_FREQ_MAP[freq]) return PANDAS_FREQ_MAP[freq]; - const m = freq.match(/^(\d+)([A-Za-z]+)$/); - if (m) { - const n = m[1]; - const base = m[2]; - const mapped = PANDAS_FREQ_MAP[base]; - if (mapped) return `${n}${mapped.replace(/^1/, '')}`; - return `${n}${base.toLowerCase()}`; - } - return freq; -} - -export function slugify(name: string): string { - return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''); -} - -export function getJobLogPath(job: { log?: string; files?: { file_type: string; path: string }[] }): string | null { - if (job.log) return job.log; - return job.files?.find(f => f.file_type === 'LOG')?.path ?? null; -} - -export function getTagType(tag: string | NetworkTag): TagType { - if (typeof tag === 'string') return 'default'; - const name = tag.name?.toLowerCase() || ''; - const url = tag.url?.toLowerCase() || ''; - if (name.includes('config') || name.endsWith('.yaml') || name.endsWith('.yml')) return 'config'; - if (url.includes('/commit/') || /^[a-f0-9]{7,}$/.test(name) || name === 'master' || name === 'main') return 'version'; - return 'model'; -} - -export function getTagColor(type: TagType): TagColor { - switch (type) { - case 'model': return 'tag-model'; - case 'version': return 'tag-version'; - case 'config': return 'tag-config'; - default: return 'tag-default'; - } -} diff --git a/frontend/app/src/plotly.d.ts b/frontend/app/src/plotly.d.ts deleted file mode 100644 index b5388448..00000000 --- a/frontend/app/src/plotly.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'plotly.js-dist'; diff --git a/frontend/app/src/routes/+error.svelte b/frontend/app/src/routes/+error.svelte deleted file mode 100644 index 5b45fd1c..00000000 --- a/frontend/app/src/routes/+error.svelte +++ /dev/null @@ -1,8 +0,0 @@ - - -
    -

    {$page.status}

    -

    {$page.error?.message ?? 'Something went wrong'}

    -
    diff --git a/frontend/app/src/routes/+layout.svelte b/frontend/app/src/routes/+layout.svelte deleted file mode 100644 index 931b8b9f..00000000 --- a/frontend/app/src/routes/+layout.svelte +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - - -
    - {#if !bannerDismissed && showSidebar} -
    - - This app is in early development. Report bugs or suggest features by opening an - - issue. - - -
    - {/if} - - {#if authStore.loading} - - {:else if showSidebar} - - - -
    -
    - -
    - - - - {#if breadcrumbStore.items.length > 0} - - {pageName} - - {:else} - {pageName} - {/if} - - {#each breadcrumbStore.items as item} - - - {#if item.href} - {item.label} - {:else} - {item.label} - {/if} - - {/each} - - -
    -
    - {#if toolbar} - {@render toolbar()} - {/if} - -
    -
    -
    - {@render children?.()} -
    -
    -
    - {:else if isPublicView} - -
    -
    - - PyPSA App - PyPSA App - {#if publicVersion} - v{publicVersion} - {/if} - -
    - - -
    -
    -
    - {@render children?.()} -
    -
    - {:else} - {@render children?.()} - {/if} -
    diff --git a/frontend/app/src/routes/+page.svelte b/frontend/app/src/routes/+page.svelte deleted file mode 100644 index 0882c40c..00000000 --- a/frontend/app/src/routes/+page.svelte +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/frontend/app/src/routes/admin/+layout.svelte b/frontend/app/src/routes/admin/+layout.svelte deleted file mode 100644 index ddcad18e..00000000 --- a/frontend/app/src/routes/admin/+layout.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/frontend/app/src/routes/admin/+page.svelte b/frontend/app/src/routes/admin/+page.svelte deleted file mode 100644 index 512e62f6..00000000 --- a/frontend/app/src/routes/admin/+page.svelte +++ /dev/null @@ -1,8 +0,0 @@ - diff --git a/frontend/app/src/routes/admin/api-keys/+page.svelte b/frontend/app/src/routes/admin/api-keys/+page.svelte deleted file mode 100644 index 5b669b5f..00000000 --- a/frontend/app/src/routes/admin/api-keys/+page.svelte +++ /dev/null @@ -1,341 +0,0 @@ - - - - Admin - API Keys - PyPSA App - - -
    - -
    - -{#if keysLoading} - -{:else if keys.length === 0} - -{:else} - (filter = ast)} - onRowClick={(key: ApiKey) => { - selectedKey = key; - detailOpen = true; - }} - /> -{/if} - - - - {#if selectedKey} - {@const expired = isExpired(selectedKey)} - - {selectedKey.name} - API key details. - -
    -
    ID
    -
    {selectedKey.id}
    -
    Prefix
    -
    {selectedKey.key_prefix}...
    -
    Owner
    -
    - -
    -
    Status
    -
    - - {expired ? 'expired' : 'active'} - -
    -
    Created
    -
    -
    Last used
    -
    -
    Expires
    -
    -
    -
    - - -
    - {/if} -
    -
    - - - - - Delete API Key - - Delete "{selectedKey?.name}"? Cannot be undone. - - -
    - - -
    -
    -
    - - - - - Create API Key - Create an API key linked to a bot user. - - {#if createdKey} - { - createdKey = null; - createOpen = false; - }} - /> - {:else} -
    -
    - - -
    -
    - - { newKeyUserId = v; }} - searchPlaceholder="Search bot users..." - emptyText={botUsers.length === 0 ? 'No bot users available. Create one first.' : 'No users found.'} - width="w-full" - > - {#snippet trigger({ props })} - {@const selectedBot = botUsers.find((u) => u.id === newKeyUserId)} - - {/snippet} - -
    -
    - - -
    -
    - - -
    -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/admin/backends/+page.svelte b/frontend/app/src/routes/admin/backends/+page.svelte deleted file mode 100644 index 2ecd2ad4..00000000 --- a/frontend/app/src/routes/admin/backends/+page.svelte +++ /dev/null @@ -1,92 +0,0 @@ - - - - Admin - Backends - PyPSA App - - -{#if loading} - -{:else if backends.length === 0} - -{:else} - (filter = ast)} - onRowClick={(backend: Backend) => goto(`/admin/backends/${backend.id}`)} - /> -{/if} diff --git a/frontend/app/src/routes/admin/backends/[id]/+page.svelte b/frontend/app/src/routes/admin/backends/[id]/+page.svelte deleted file mode 100644 index cd4e1d2b..00000000 --- a/frontend/app/src/routes/admin/backends/[id]/+page.svelte +++ /dev/null @@ -1,145 +0,0 @@ - - - - Admin - {backend?.name ?? 'Backend'} - PyPSA App - - -
    - {#if loading || !backend} -

    Loading...

    - {:else} -
    -
    -

    {backend.name}

    - - {backend.is_active ? 'active' : 'inactive'} - -
    -

    {backend.url}

    -
    - -
    -

    Overview

    -
    -
    ID
    -
    {backend.id}
    -
    URL
    -
    {backend.url}
    -
    Status
    -
    {backend.is_active ? 'active' : 'inactive'}
    -
    Created
    -
    -
    Updated
    -
    -
    -
    - -
    -

    Assigned users

    - u.username} - onAdd={assignUser} - onRemove={removeUser} - emptyText="No users assigned." - addLabel="Assign user" - > - {#snippet rowSnippet(user: User)} - - - - - {user.username.substring(0, 2).toUpperCase()} - - - {user.username} - {user.role} - - {/snippet} - -
    - - {/if} -
    diff --git a/frontend/app/src/routes/admin/components/api-key-columns.ts b/frontend/app/src/routes/admin/components/api-key-columns.ts deleted file mode 100644 index 7a59792a..00000000 --- a/frontend/app/src/routes/admin/components/api-key-columns.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { renderComponent } from '$lib/components/ui/data-table/render-helpers.js'; -import DateTime from '$lib/components/DateTime.svelte'; -import BadgeCell from '$lib/components/cells/BadgeCell.svelte'; -import type { ColumnDef } from '@tanstack/table-core'; -import { byDate } from '$lib/utils.js'; -import type { ApiKey } from '$lib/types.js'; - -interface ApiKeyColumnsHelpers { - isExpired: (key: ApiKey) => boolean; -} - -export const createColumns = (helpers: ApiKeyColumnsHelpers): ColumnDef[] => { - const { isExpired } = helpers; - - return [ - { - accessorKey: 'name', - header: 'Name', - enableSorting: true, - sortingFn: 'alphanumeric', - cell: (info) => info.getValue() as string - }, - { - accessorKey: 'key_prefix', - header: 'Prefix', - enableSorting: false, - cell: (info) => `${info.getValue() as string}...` - }, - { - id: 'owner', - header: 'Owner', - enableSorting: true, - cell: (info) => info.row.original.owner.username - }, - { - accessorKey: 'created_at', - header: 'Created', - enableSorting: true, - sortingFn: byDate((r) => r.created_at), - cell: (info) => renderComponent(DateTime, { value: info.getValue() as string }) - }, - { - accessorKey: 'last_used_at', - header: 'Last used', - enableSorting: true, - sortingFn: byDate((r) => r.last_used_at), - cell: (info) => renderComponent(DateTime, { value: info.getValue() as string }) - }, - { - accessorKey: 'expires_at', - header: 'Expires', - enableSorting: true, - sortingFn: byDate((r) => r.expires_at), - cell: (info) => renderComponent(DateTime, { value: info.getValue() as string }) - }, - { - id: 'status', - header: 'Status', - enableSorting: false, - cell: (info) => { - const expired = isExpired(info.row.original); - return renderComponent(BadgeCell, { - label: expired ? 'expired' : 'active', - variant: expired ? 'outline' : 'default' - }); - } - } - ]; -}; diff --git a/frontend/app/src/routes/admin/components/backend-columns.ts b/frontend/app/src/routes/admin/components/backend-columns.ts deleted file mode 100644 index b3443a5b..00000000 --- a/frontend/app/src/routes/admin/components/backend-columns.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { renderComponent } from '$lib/components/ui/data-table/render-helpers.js'; -import DateTime from '$lib/components/DateTime.svelte'; -import BadgeCell from '$lib/components/cells/BadgeCell.svelte'; -import ActionsCell from '$lib/components/cells/ActionsCell.svelte'; -import Users from '@lucide/svelte/icons/users'; -import type { ColumnDef } from '@tanstack/table-core'; -import { byDate } from '$lib/utils.js'; -import type { Backend } from '$lib/types.js'; - -interface BackendColumnsHelpers { - onManageUsers: (backend: Backend) => void; -} - -export const createColumns = (helpers: BackendColumnsHelpers): ColumnDef[] => { - const { onManageUsers } = helpers; - - return [ - { - accessorKey: 'name', - header: 'Name', - enableSorting: true, - sortingFn: 'alphanumeric', - cell: (info) => { - return info.getValue() as string; - } - }, - { - accessorKey: 'url', - header: 'URL', - enableSorting: false, - cell: (info) => { - return info.getValue() as string; - } - }, - { - id: 'status', - header: 'Status', - enableSorting: true, - cell: (info) => { - const backend = info.row.original; - return renderComponent(BadgeCell, { - label: backend.is_active ? 'active' : 'inactive', - variant: backend.is_active ? 'default' : 'outline' - }); - } - }, - { - accessorKey: 'created_at', - header: 'Created', - enableSorting: true, - sortingFn: byDate((r) => r.created_at), - cell: (info) => { - return renderComponent(DateTime, { value: info.getValue() as string }); - } - }, - { - id: 'actions', - header: '', - enableSorting: false, - cell: (info) => { - const backend = info.row.original; - return renderComponent(ActionsCell, { - actions: [ - { - icon: Users, - label: 'Manage Users', - onclick: () => onManageUsers(backend) - } - ] - }); - } - } - ]; -}; diff --git a/frontend/app/src/routes/admin/components/user-columns.ts b/frontend/app/src/routes/admin/components/user-columns.ts deleted file mode 100644 index bed7399a..00000000 --- a/frontend/app/src/routes/admin/components/user-columns.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { renderComponent } from '$lib/components/ui/data-table/render-helpers.js'; -import DateTime from '$lib/components/DateTime.svelte'; -import UserCell from '$lib/components/cells/UserCell.svelte'; -import BadgeCell from '$lib/components/cells/BadgeCell.svelte'; -import ActionsCell from '$lib/components/cells/ActionsCell.svelte'; -import Check from '@lucide/svelte/icons/check'; -import Settings from '@lucide/svelte/icons/settings'; -import type { ColumnDef } from '@tanstack/table-core'; -import { byDate } from '$lib/utils.js'; -import type { User } from '$lib/types.js'; - -interface UserColumnsHelpers { - onApprove: (userId: string) => void; - onOpenPermissions: (user: User) => void; -} - -function getRoleBadgeVariant(role: string) { - if (role === 'admin') return 'default' as const; - if (role === 'bot' || role === 'user') return 'secondary' as const; - return 'outline' as const; -} - -export const createColumns = (helpers: UserColumnsHelpers): ColumnDef[] => { - const { onApprove, onOpenPermissions } = helpers; - - return [ - { - accessorKey: 'username', - header: 'User', - enableSorting: true, - sortingFn: 'alphanumeric', - cell: (info) => { - return renderComponent(UserCell, { user: info.row.original }); - } - }, - { - accessorKey: 'email', - header: 'Email', - enableSorting: true, - sortingFn: 'alphanumeric', - cell: (info) => { - return (info.getValue() as string) || '\u2014'; - } - }, - { - accessorKey: 'role', - header: 'Role', - enableSorting: true, - cell: (info) => { - const role = info.getValue() as string; - return renderComponent(BadgeCell, { - label: role, - variant: getRoleBadgeVariant(role) - }); - } - }, - { - accessorKey: 'created_at', - header: 'Created', - enableSorting: true, - sortingFn: byDate((r) => r.created_at), - cell: (info) => { - return renderComponent(DateTime, { value: info.getValue() as string }); - } - }, - { - accessorKey: 'last_login', - header: 'Last Login', - enableSorting: true, - sortingFn: byDate((r) => r.last_login), - cell: (info) => { - return renderComponent(DateTime, { value: info.getValue() as string }); - } - }, - { - id: 'actions', - header: '', - enableSorting: false, - cell: (info) => { - const user = info.row.original; - const actions = []; - if (user.role === 'pending') { - actions.push({ - icon: Check, - label: 'Approve', - onclick: () => onApprove(user.id) - }); - } - actions.push({ - icon: Settings, - label: 'Permissions', - onclick: () => onOpenPermissions(user) - }); - return renderComponent(ActionsCell, { actions }); - } - } - ]; -}; diff --git a/frontend/app/src/routes/admin/users/+page.svelte b/frontend/app/src/routes/admin/users/+page.svelte deleted file mode 100644 index 1edbd41d..00000000 --- a/frontend/app/src/routes/admin/users/+page.svelte +++ /dev/null @@ -1,275 +0,0 @@ - - - - Admin - Users - PyPSA App - - -
    - -
    - -{#if loading} - -{:else if users.length === 0} - -{:else} - goto(`/admin/users/${user.id}`)} - /> -{/if} - - - - - Create User - Create a new user account. - -
    -
    - - { - if (e.key === 'Enter') createUser(); - }} - /> -
    -
    - - -

    - Only bot users can be created via the admin panel. -

    -
    -
    - - -
    -
    - - -
    -
    -
    -
    diff --git a/frontend/app/src/routes/admin/users/[id]/+page.svelte b/frontend/app/src/routes/admin/users/[id]/+page.svelte deleted file mode 100644 index 93585cad..00000000 --- a/frontend/app/src/routes/admin/users/[id]/+page.svelte +++ /dev/null @@ -1,587 +0,0 @@ - - - - Admin - {user?.username ?? 'User'} - PyPSA App - - -
    - {#if loading || !user} -

    Loading...

    - {:else} -
    - - - {user.username.substring(0, 2).toUpperCase()} - -
    -
    -

    {user.username}

    - {user.role} - {#if isSelf} - you - {/if} -
    -

    - {user.email || 'No email'} ¡ Last login: -

    -
    -
    - -
    -

    Profile

    -
    -
    ID
    -
    {user.id}
    -
    Email
    -
    {user.email || '—'}
    -
    Created
    -
    -
    Last login
    -
    -
    Role
    -
    - {#if isSelf} - {user.role} (cannot change own role) - {:else} - - {/if} -
    -
    -
    - -
    -

    Permissions

    -
    - {#each groupedPermissions as group (group.name)} -
    -

    - {group.name} -

    -
      - {#each group.perms as perm (perm.full)} - {@const granted = user.permissions?.includes(perm.full)} -
    • - {#if granted} - - {perm.action} - {:else} - - {perm.action} - {/if} -
    • - {/each} -
    -
    - {/each} -
    -
    - - {#if stats} -
    -

    Activity

    -
    -
    Networks
    -
    - {stats.networks_count} - {#if stats.networks_count > 0} - ({formatFileSize(stats.total_storage_bytes)}) - {/if} -
    -
    Runs
    -
    - {stats.runs_total} - {#if barSegments.length > 0} -
    - {#each barSegments as seg} - {@const pct = (seg.count / stats.runs_total) * 100} - - {#if pct >= 15} - {seg.count} {seg.label} - {:else if pct >= 8} - {seg.count} - {/if} - - {/each} -
    - {/if} - {#if Object.keys(stats.runs_by_backend).length > 0} -
    - {#each Object.entries(stats.runs_by_backend) as [name, count], i} - {@const pct = (count / stats.runs_total) * 100} - - {#if pct >= 15} - {count} {name} - {:else if pct >= 8} - {count} - {/if} - - {/each} -
    - {/if} -
    -
    Last activity
    -
    - {#if stats.last_activity} - {formatRelativeTime(stats.last_activity)} - {:else} - — - {/if} -
    -
    -
    - {/if} - -
    -

    Backends

    - b.name} - onAdd={assignBackend} - onRemove={removeBackend} - emptyText="No backends assigned." - addLabel="Assign backend" - /> -
    - - {#if user.role === 'bot'} -
    -
    -

    API keys

    - -
    - {#if userKeys.length === 0} -

    No API keys.

    - {:else} - - - - - - - - - - - - - {#each userKeys as key (key.id)} - - - - - - - - - {/each} - -
    NamePrefixCreatedLast usedExpires
    {key.name}{key.key_prefix}... - -
    - {/if} -
    - {/if} - - {#if !isSelf} -
    -

    Danger zone

    - -
    - {/if} - {/if} -
    - - - - - Delete User - - Delete user "{user?.username}"? Cannot be undone. - - -
    - - -
    -
    -
    - - - - - Delete API Key - - Delete API key "{keyToDelete?.name}"? Cannot be undone. - - -
    - - -
    -
    -
    - - - - - Create API Key - - Create an API key for {user?.username}. - - - {#if createdKey} - { - createdKey = null; - createKeyOpen = false; - }} - /> - {:else} -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/dev/skeletons/+page.svelte b/frontend/app/src/routes/dev/skeletons/+page.svelte deleted file mode 100644 index 1d574b49..00000000 --- a/frontend/app/src/routes/dev/skeletons/+page.svelte +++ /dev/null @@ -1,42 +0,0 @@ - - -
    -

    Skeleton Components Preview

    - -
    -

    1. TableSkeleton (default: 5 rows, 6 cols)

    - -
    - -
    -

    2. PlotSkeleton

    -
    - -
    -
    - -
    -

    3. RunDetailSkeleton

    - -
    - -
    -

    4. NetworksListSkeleton (sidebar)

    -
    - -
    -
    - -
    -

    5. PageSkeleton

    - -
    -
    diff --git a/frontend/app/src/routes/login/+page.svelte b/frontend/app/src/routes/login/+page.svelte deleted file mode 100644 index 9f1cfee7..00000000 --- a/frontend/app/src/routes/login/+page.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - - Login - PyPSA App - - -
    -
    - -
    -
    - -
    -
    -
    - -
    diff --git a/frontend/app/src/routes/login/login-form.svelte b/frontend/app/src/routes/login/login-form.svelte deleted file mode 100644 index c28a2bf7..00000000 --- a/frontend/app/src/routes/login/login-form.svelte +++ /dev/null @@ -1,216 +0,0 @@ - - -
    - - {#if hasCredentials} -
    -

    Login to your account

    -

    - {#if features.demoMode} - This is a public demo instance. It is regularly reset. - Uploads to this instance are disabled. -
    - Click Login to continue. - {:else} - Enter your email below to login to your account - {/if} -

    -
    - - Email - - - - -
    - - -
    -
    - {#if errorMsg} - - {/if} - - - - {/if} - - {#if hasCredentials && hasOAuth} - Or continue with - {/if} - - {#if !hasCredentials && hasOAuth} -
    -

    Login to your account

    -
    - {/if} - - {#each oauthProviders as p (p.id)} - {@const Icon = iconFor(p.icon)} - - - - {/each} - -

    - Don't have an account? - - Sign up - -

    -
    -
    diff --git a/frontend/app/src/routes/networks/+page.svelte b/frontend/app/src/routes/networks/+page.svelte deleted file mode 100644 index f09d13c2..00000000 --- a/frontend/app/src/routes/networks/+page.svelte +++ /dev/null @@ -1,459 +0,0 @@ - - -
    -
    - - {#if !features.demoMode} - - {/if} - - - {#if viewState === 'loading'} - 10 ? 10 : pageSize} /> - {:else if viewState === 'empty'} - - {:else} - viewNetwork(network.id)} - /> - {/if} -
    -
    - - - - - {#if deleteTarget} - - Delete network? - - {deleteTarget.filename} - - -
    - {#if deleteTarget.is_external} -

    - This network was registered in place. By default the underlying file is kept on disk and only the database reference is removed. -

    - - {:else} -

    - This will remove both the database record and the file from disk. This action cannot be undone. -

    - {/if} -
    - - - - - {/if} -
    -
    - - - - - {#if editNetwork} - - Change Owner - - {editNetwork.filename} - - -
    -
    - - { editOwner = v; }} - searchPlaceholder="Search users..." - emptyText="No users found." - width="w-full" - > - {#snippet trigger({ props })} - {@const ownerUser = allUsers.find((u) => u.id === editOwner)} - - {/snippet} - -
    -
    - - - - - {/if} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/+layout.svelte b/frontend/app/src/routes/networks/[id]/+layout.svelte deleted file mode 100644 index 7ad794cf..00000000 --- a/frontend/app/src/routes/networks/[id]/+layout.svelte +++ /dev/null @@ -1,110 +0,0 @@ - - -{#if loading} - -{:else if error && !network} -
    -
    - -

    Error Loading Network

    -

    {error}

    -
    -
    -{:else if network} - {@const isDataRoute = $page.url.pathname.includes(`/networks/${networkId}/data`)} -
    -
    - Reports - Data -
    -
    - {#if network.file_missing} -
    -
    - -
    -
    Network file is no longer available
    -
    - The underlying file was moved or deleted. Charts and component data cannot be rendered. - {#if network.file_path} -
    {network.file_path}
    - {/if} -
    -
    -
    -
    - {/if} - {@render children?.()} -{/if} diff --git a/frontend/app/src/routes/networks/[id]/+page.svelte b/frontend/app/src/routes/networks/[id]/+page.svelte deleted file mode 100644 index 2aa4f172..00000000 --- a/frontend/app/src/routes/networks/[id]/+page.svelte +++ /dev/null @@ -1,21 +0,0 @@ - diff --git a/frontend/app/src/routes/networks/[id]/components/ComponentTableCard.svelte b/frontend/app/src/routes/networks/[id]/components/ComponentTableCard.svelte deleted file mode 100644 index 9af9b055..00000000 --- a/frontend/app/src/routes/networks/[id]/components/ComponentTableCard.svelte +++ /dev/null @@ -1,162 +0,0 @@ - - -
    -
    -
    - {#if onfullscreen} - - {:else} - {card.name ?? 'Component Table'} - {/if} - -
    -
    - - - {#snippet child({ props })} - - {/snippet} - - - goto(`/networks/${networkId}/data/${card.component}`)}> - - Full view - - - - Remove - - - -
    -
    - -
    - {#if loading && !response} -
    - Loadingâ€Ļ -
    - {:else if error} -
    - {error} -
    - {:else if response} - { currentPage = page; }} - onPageSizeChange={(size) => { pageSize = size; currentPage = 1; }} - /> - {/if} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/ExploreCard.svelte b/frontend/app/src/routes/networks/[id]/components/ExploreCard.svelte deleted file mode 100644 index 5a4508e4..00000000 --- a/frontend/app/src/routes/networks/[id]/components/ExploreCard.svelte +++ /dev/null @@ -1,240 +0,0 @@ - - -
    - -
    - {#if onfullscreen} - - {:else} - {card.name ?? 'Explore'} - {/if} -
    - - - - {#snippet child({ props })} - - {/snippet} - - - - - Remove - - - -
    -
    - - -
    -
    -
    - -
    - {#if loading} -
    - -
    - {:else if error} -
    -

    {error}

    -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/ExploreEditorDialog.svelte b/frontend/app/src/routes/networks/[id]/components/ExploreEditorDialog.svelte deleted file mode 100644 index ffc4a2f9..00000000 --- a/frontend/app/src/routes/networks/[id]/components/ExploreEditorDialog.svelte +++ /dev/null @@ -1,243 +0,0 @@ - - - { if (!v) onclose(); }}> - e.preventDefault()}> - - {initialCard ? 'Edit Explore Map' : 'Add Explore Map'} - - -
    - -
    - -
    - -
    - - -
    - Branch Components -
    - {#each BRANCH_COMPONENTS as bc} - - {/each} -
    -
    - - -
    - -

    Show actual line paths instead of straight lines

    -
    - - - {#if carriers.length > 0} -
    - Carriers -
    - {#each carriers as carrier} - - {/each} -
    -
    - {/if} - - - {#if countries.length > 0} -
    - Countries -
    - {#each countries as country} - - {/each} -
    -
    - {/if} -
    - - -
    - Preview -
    - {#key JSON.stringify([previewCard.bus_carrier, previewCard.query, previewCard.branch_components, previewCard.geometry])} - {}} - onremove={() => {}} - /> - {/key} -
    -
    -
    - - - - - -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/MapCard.svelte b/frontend/app/src/routes/networks/[id]/components/MapCard.svelte deleted file mode 100644 index 003af9b8..00000000 --- a/frontend/app/src/routes/networks/[id]/components/MapCard.svelte +++ /dev/null @@ -1,235 +0,0 @@ - - -
    - -
    - {#if onfullscreen} - - {:else} - Map - {/if} -
    - - - {#snippet child({ props })} - - {/snippet} - - - - - Remove - - - -
    -
    - - -
    - -
    -
    - -
    - - {#if loading} -
    - -
    - {:else if error} -
    -

    {error}

    -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/MarkdownCard.svelte b/frontend/app/src/routes/networks/[id]/components/MarkdownCard.svelte deleted file mode 100644 index 57d44dd6..00000000 --- a/frontend/app/src/routes/networks/[id]/components/MarkdownCard.svelte +++ /dev/null @@ -1,104 +0,0 @@ - - -
    - -
    - {#if onfullscreen} - - {:else} - {card.name ?? 'Notes'} - {/if} -
    - {#if editing} - - {:else} - - {/if} - - - {#snippet child({ props })} - - {/snippet} - - - - - Remove - - - -
    -
    - - -
    - {#if editing} - - {:else} -
    - {@html renderedHtml} -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/OverviewCard.svelte b/frontend/app/src/routes/networks/[id]/components/OverviewCard.svelte deleted file mode 100644 index ae917a90..00000000 --- a/frontend/app/src/routes/networks/[id]/components/OverviewCard.svelte +++ /dev/null @@ -1,152 +0,0 @@ - - -
    - -
    - Overview -
    - - - {#snippet child({ props })} - - {/snippet} - - - - - Remove - - - -
    -
    - - -
    - -
    -
    - {#if network.name && network.name !== network.filename} -

    {network.name}

    -
    - {network.filename} -
    - {:else} -

    {network.filename}

    - {/if} -
    - {#if network.tags && Array.isArray(network.tags) && network.tags.length > 0} -
    - {#each network.tags as tag} - {@const tagType = getTagType(tag)} - {@const colorClasses = getTagColor(tagType)} - {#if typeof tag === 'object' && tag.name && tag.url} - e.stopPropagation()} - > - {tag.name} - - - - - - - {:else if typeof tag === 'string'} - - {tag} - - {/if} - {/each} -
    - {/if} -
    - - - {#if network.dimensions} -
    - {#if network.dimensions.timesteps.count > 0} - - {/if} - {#if network.dimensions.periods.count > 0} - - {/if} - {#if network.dimensions.scenarios.count > 1} - - {/if} -
    - {/if} - - -
    - {#if network.owner} -
    - {#if network.owner.avatar_url} - {network.owner.username} - {/if} - {network.owner.username} -
    - â€ĸ - {/if} -
    - - -
    - {#if network.file_size} - â€ĸ -
    - - {formatFileSize(network.file_size)} -
    - {/if} - {#if network.source_run_id} - â€ĸ - e.stopPropagation()} - > - - source run - - {/if} -
    -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/PlotCard.svelte b/frontend/app/src/routes/networks/[id]/components/PlotCard.svelte deleted file mode 100644 index 792a1abc..00000000 --- a/frontend/app/src/routes/networks/[id]/components/PlotCard.svelte +++ /dev/null @@ -1,354 +0,0 @@ - - - - -
    - {#if showActions} - -
    -
    - {#if onfullscreen} - - {:else} - {label ?? title} - {/if} - {#if adjustmentHints.length > 0} - - - {#snippet child({ props }: { props: Record })} - - - - {/snippet} - - - {#each adjustmentHints as hint} -

    {hint}

    - {/each} -
    -
    - {/if} -
    -
    - - - - {#snippet child({ props })} - - {/snippet} - - - - - Remove - - - -
    -
    - {/if} - - -
    - {#if loading} - - {:else if emptyData} -
    - -

    No data available

    -
    - {:else if error} -
    -

    {error}

    -
    - {:else} -
    -
    -
    - {/if} -
    -
    - - diff --git a/frontend/app/src/routes/networks/[id]/components/PlotEditorDialog.svelte b/frontend/app/src/routes/networks/[id]/components/PlotEditorDialog.svelte deleted file mode 100644 index 42f2652c..00000000 --- a/frontend/app/src/routes/networks/[id]/components/PlotEditorDialog.svelte +++ /dev/null @@ -1,373 +0,0 @@ - - - { if (!v) onclose(); }}> - e.preventDefault()}> - - {initialPlot ? 'Edit Plot' : 'Add Plot'} - - -
    - -
    - -
    - -
    - - -
    - Statistic - { - statistic = v; - }} - > - - {STATISTICS.find((s) => s.value === statistic)?.label ?? statistic} - - - {#each STATISTICS as stat} - {stat.label} - {/each} - - -
    - - -
    - Plot Type -
    - {#each CHART_TYPES as ct} - - {/each} -
    -
    - - -
    - Expand by -
    - {#each [{ value: '', label: 'None' }, { value: 'bus_carrier', label: 'Per Carrier' }, { value: 'country', label: 'Per Country' }] as opt} - - {/each} -
    - {#if expandBy} -

    - One plot per {expandBy === 'bus_carrier' ? 'carrier' : 'country'} — select specific ones below or leave empty for all -

    - {/if} -
    - - - {#if carriers.length > 0 || unavailableCarriers.length > 0} -
    - Carriers -
    - {#each carriers as carrier} - - {/each} - {#if unavailableCarriers.length > 0} -
    -
    - Not on this network -
    -
    - {#each unavailableCarriers as carrier} - - {/each} - - {/if} -
    -
    - {/if} - - - {#if countries.length > 0 || unavailableCountries.length > 0} -
    - Countries -
    - {#each countries as country} - - {/each} - {#if unavailableCountries.length > 0} -
    -
    - Not on this network -
    -
    - {#each unavailableCountries as country} - - {/each} - - {/if} -
    -
    - {/if} -
    - - -
    - Preview -
    - {#key `${previewPlot.expandBy}`} - {#if previewGroupItems} - {}} - onremove={() => {}} - showActions={false} - /> - {:else} - - {/if} - {/key} -
    -
    -
    - - - - - -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/PlotGroup.svelte b/frontend/app/src/routes/networks/[id]/components/PlotGroup.svelte deleted file mode 100644 index b07bb4fe..00000000 --- a/frontend/app/src/routes/networks/[id]/components/PlotGroup.svelte +++ /dev/null @@ -1,184 +0,0 @@ - - -
    - - - - -
    - {#if onfullscreen} - - {:else} - {groupTitle} - {/if} -
    - - {#if overflowing} - - {:else} -
    - {#each items as item, i (item.label)} - - {/each} -
    - {/if} - -
    - - {#if showActions} -
    - - - - {#snippet child({ props })} - - {/snippet} - - - - - Remove - - - -
    - {/if} -
    - - -
    - {#if activeItem} - {#key activeItem.label} - - {/key} - {/if} -
    -
    - - diff --git a/frontend/app/src/routes/networks/[id]/components/ReportGrid.svelte b/frontend/app/src/routes/networks/[id]/components/ReportGrid.svelte deleted file mode 100644 index a40ec2e8..00000000 --- a/frontend/app/src/routes/networks/[id]/components/ReportGrid.svelte +++ /dev/null @@ -1,628 +0,0 @@ - - -{#if fullscreenRc} - {@const rc = fullscreenRc} -
    -
    - {#if rc.card.type === 'markdown'} - reportStore.updateCard(report.id, rc.card.id, { content })} - /> - {:else if rc.card.type === 'explore'} - - {:else if rc.card.type === 'map'} - - {:else if rc.card.type === 'overview'} - - {:else if rc.card.type === 'component_table'} - - {:else if rc.isGroup && rc.groupItems} - - {:else} - - {/if} -
    -
    -{:else} -
    - -
    - {#each resolvedCards as rc (rc.resolvedId)} -
    -
    - {#if rc.card.type === 'markdown'} - reportStore.updateCard(report.id, rc.card.id, { content })} - onremove={() => reportStore.removeCard(report.id, rc.card.id)} - onfullscreen={() => goto(`/networks/${networkId}/report/${slug}?card=${rc.resolvedId}`)} - /> - {:else if rc.card.type === 'explore'} - oneditexplore?.(rc.card as ExploreCardDefinition)} - onremove={() => reportStore.removeCard(report.id, rc.card.id)} - onfullscreen={() => goto(`/networks/${networkId}/report/${slug}?card=${rc.resolvedId}`)} - /> - {:else if rc.card.type === 'map'} - reportStore.removeCard(report.id, rc.card.id)} - onfullscreen={() => goto(`/networks/${networkId}/report/${slug}?card=${rc.resolvedId}`)} - /> - {:else if rc.card.type === 'overview'} - reportStore.removeCard(report.id, rc.card.id)} - /> - {:else if rc.card.type === 'component_table'} - reportStore.removeCard(report.id, rc.card.id)} - onfullscreen={() => goto(`/networks/${networkId}/report/${slug}?card=${rc.resolvedId}`)} - /> - {:else if rc.isGroup && rc.groupItems} - oneditplot(rc.card as PlotCardDefinition)} - onremove={() => reportStore.removeCard(report.id, rc.card.id)} - onfullscreen={() => goto(`/networks/${networkId}/report/${slug}?card=${rc.resolvedId}`)} - /> - {:else} - oneditplot(rc.card as PlotCardDefinition)} - onremove={() => reportStore.removeCard(report.id, rc.card.id)} - onfullscreen={() => goto(`/networks/${networkId}/report/${slug}?card=${rc.resolvedId}`)} - /> - {/if} -
    -
    - {/each} -
    - - {#if resolvedCards.length === 0} - - {/if} -
    -{/if} - - diff --git a/frontend/app/src/routes/networks/[id]/components/ReportTabs.svelte b/frontend/app/src/routes/networks/[id]/components/ReportTabs.svelte deleted file mode 100644 index ad8c47fe..00000000 --- a/frontend/app/src/routes/networks/[id]/components/ReportTabs.svelte +++ /dev/null @@ -1,137 +0,0 @@ - - -
    -
    -
    - {#each reportStore.reports as report (report.id)} - {@const reportSlug = slugify(report.name)} - {@const isActive = reportSlug === currentSlug} - - {#if editingId === report.id} - - e.stopPropagation()} - /> - {:else} - startRename(report)}>{report.name} - {/if} - {#if !report.isDefault} - - {/if} - - {/each} -
    - -
    -
    - - - e.preventDefault()}> - - New Report - -
    - -
    -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/dimensions/PeriodsStrip.svelte b/frontend/app/src/routes/networks/[id]/components/dimensions/PeriodsStrip.svelte deleted file mode 100644 index 515ca20b..00000000 --- a/frontend/app/src/routes/networks/[id]/components/dimensions/PeriodsStrip.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -
    - -
    - {#if showEndpoints} -
    - {startLabel} -
    - {overlayLabel} -
    - {endLabel} -
    - {:else} -
    - {overlayLabel} -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/dimensions/ScenariosStrip.svelte b/frontend/app/src/routes/networks/[id]/components/dimensions/ScenariosStrip.svelte deleted file mode 100644 index ad899cc1..00000000 --- a/frontend/app/src/routes/networks/[id]/components/dimensions/ScenariosStrip.svelte +++ /dev/null @@ -1,37 +0,0 @@ - - -
    - -
    - {#if showEndpoints} -
    - {startLabel} -
    - {overlayLabel} -
    - {endLabel} -
    - {:else} -
    - {overlayLabel} -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/dimensions/TimestepsStrip.svelte b/frontend/app/src/routes/networks/[id]/components/dimensions/TimestepsStrip.svelte deleted file mode 100644 index 4eee6051..00000000 --- a/frontend/app/src/routes/networks/[id]/components/dimensions/TimestepsStrip.svelte +++ /dev/null @@ -1,38 +0,0 @@ - - -
    - -
    - {#if showEndpoints} -
    - {startLabel} -
    - {overlayLabel} -
    - {endLabel} -
    - {:else} -
    - {overlayLabel} -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/components/plotRenderer.ts b/frontend/app/src/routes/networks/[id]/components/plotRenderer.ts deleted file mode 100644 index 103d2be6..00000000 --- a/frontend/app/src/routes/networks/[id]/components/plotRenderer.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { PlotData } from '$lib/types.js'; - -let PlotlyModule: any = null; - -export async function loadPlotly(): Promise { - if (!PlotlyModule) { - PlotlyModule = await import('plotly.js-dist'); - } - return PlotlyModule; -} - -export function renderPlot( - element: HTMLElement, - plotData: PlotData, - Plotly: any, - height?: number, -): void { - // Purge existing plot - if ((element as any)._plotly) { - try { - Plotly.purge(element); - } catch { - // Ignore purge errors - } - } - - const layout = { - ...(plotData.layout as Record), - autosize: true, - width: undefined, - height: height || undefined, - margin: { l: 60, r: 30, t: 30, b: 60 }, - }; - - Plotly.newPlot(element, plotData.data, layout, { - responsive: true, - displayModeBar: true, - displaylogo: false, - }); -} - -export function purgePlot(element: HTMLElement, Plotly: any): void { - try { - Plotly.purge(element); - } catch { - // Ignore - } -} - -export function resizePlot(element: HTMLElement, Plotly: any): void { - if (element && document.body.contains(element)) { - try { - Plotly.Plots.resize(element); - } catch { - // Ignore resize errors - } - } -} - -export function humanizeStatistic(statistic: string): string { - return statistic - .split('_') - .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) - .join(' '); -} - -export function humanizePlotType(plotType: string): string { - return plotType.charAt(0).toUpperCase() + plotType.slice(1); -} - -export function plotTitle(statistic: string, plotType: string): string { - return `${humanizeStatistic(statistic)} ${humanizePlotType(plotType)}`; -} diff --git a/frontend/app/src/routes/networks/[id]/data/+layout.svelte b/frontend/app/src/routes/networks/[id]/data/+layout.svelte deleted file mode 100644 index edacc550..00000000 --- a/frontend/app/src/routes/networks/[id]/data/+layout.svelte +++ /dev/null @@ -1,49 +0,0 @@ - - -
    - -
    - {@render children?.()} -
    -
    diff --git a/frontend/app/src/routes/networks/[id]/data/+page.svelte b/frontend/app/src/routes/networks/[id]/data/+page.svelte deleted file mode 100644 index a754bc55..00000000 --- a/frontend/app/src/routes/networks/[id]/data/+page.svelte +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/frontend/app/src/routes/networks/[id]/data/[component]/+page.svelte b/frontend/app/src/routes/networks/[id]/data/[component]/+page.svelte deleted file mode 100644 index d62fd973..00000000 --- a/frontend/app/src/routes/networks/[id]/data/[component]/+page.svelte +++ /dev/null @@ -1,192 +0,0 @@ - - -{#if loading && !response} - 10 ? 10 : pageSize} /> -{:else if error} -
    -
    - -

    {error}

    -
    -
    -{:else if response} -
    -
    - - handleSearchChange((e.target as HTMLInputElement).value)} - class="h-8 pl-9 pr-8 text-sm" - /> - {#if search} - - {/if} -
    -
    - -{/if} diff --git a/frontend/app/src/routes/networks/[id]/data/[component]/columns.ts b/frontend/app/src/routes/networks/[id]/data/[component]/columns.ts deleted file mode 100644 index e21f7162..00000000 --- a/frontend/app/src/routes/networks/[id]/data/[component]/columns.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { ColumnDef } from '@tanstack/table-core'; - -type RowData = Record; - -const NUMERIC_DTYPES = new Set(['int64', 'float64', 'int32', 'float32', 'int', 'float']); - -export function buildColumns( - responseColumns: string[], - dtypes: Record -): ColumnDef[] { - const indexCol: ColumnDef = { - accessorKey: '__index__', - header: 'Name', - enableSorting: true, - }; - - const dataCols: ColumnDef[] = responseColumns.map((col) => { - const isNumeric = NUMERIC_DTYPES.has(dtypes[col] ?? ''); - return { - accessorKey: col, - header: col, - enableSorting: true, - meta: { align: isNumeric ? 'right' : 'left' }, - }; - }); - - return [indexCol, ...dataCols]; -} diff --git a/frontend/app/src/routes/networks/[id]/report/[slug]/+page.svelte b/frontend/app/src/routes/networks/[id]/report/[slug]/+page.svelte deleted file mode 100644 index e3bced72..00000000 --- a/frontend/app/src/routes/networks/[id]/report/[slug]/+page.svelte +++ /dev/null @@ -1,289 +0,0 @@ - - -
    - {#if !fullscreenCardId} -
    - - -
    - {/if} - -
    - - - e.preventDefault()}> - - Add Card - -
    - - - - - -
    -
    -
    - - (editorOpen = false)} -/> - - (exploreEditorOpen = false)} -/> diff --git a/frontend/app/src/routes/networks/[id]/types.ts b/frontend/app/src/routes/networks/[id]/types.ts deleted file mode 100644 index 27989630..00000000 --- a/frontend/app/src/routes/networks/[id]/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Network } from '$lib/types.js'; - -export interface NetworkWithFacets extends Network { - facets?: { - carriers?: Record; - countries?: string[]; - }; -} diff --git a/frontend/app/src/routes/networks/cells/dimensions-cell.svelte b/frontend/app/src/routes/networks/cells/dimensions-cell.svelte deleted file mode 100644 index 549af5b6..00000000 --- a/frontend/app/src/routes/networks/cells/dimensions-cell.svelte +++ /dev/null @@ -1,32 +0,0 @@ - - -
    - {#if network.dimensions} - {#if network.dimensions.timesteps?.count} -
    - - {network.dimensions.timesteps.count.toLocaleString()} -
    - {/if} - {#if network.dimensions.periods?.count} -
    - - {network.dimensions.periods.count.toLocaleString()} -
    - {/if} - {#if network.dimensions.scenarios?.count} -
    - - {network.dimensions.scenarios.count.toLocaleString()} -
    - {/if} - {:else} - - - {/if} -
    diff --git a/frontend/app/src/routes/networks/cells/file-cell.svelte b/frontend/app/src/routes/networks/cells/file-cell.svelte deleted file mode 100644 index c5d6b8d6..00000000 --- a/frontend/app/src/routes/networks/cells/file-cell.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - -
    - {#if network.file_missing} - - {/if} -
    - {network.filename} -
    -
    -{#if network.name} -
    - {network.name} -
    -{/if} diff --git a/frontend/app/src/routes/networks/cells/path-cell.svelte b/frontend/app/src/routes/networks/cells/path-cell.svelte deleted file mode 100644 index f08485b1..00000000 --- a/frontend/app/src/routes/networks/cells/path-cell.svelte +++ /dev/null @@ -1,48 +0,0 @@ - - -{#if fullPath} -
    - - -
    -{/if} diff --git a/frontend/app/src/routes/networks/cells/tags-cell.svelte b/frontend/app/src/routes/networks/cells/tags-cell.svelte deleted file mode 100644 index af6d5218..00000000 --- a/frontend/app/src/routes/networks/cells/tags-cell.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -
    - {#if network.tags && Array.isArray(network.tags) && network.tags.length > 0} - {#each network.tags as tag} - {@const tagType = getTagType(tag)} - {@const colorClasses = getTagColor(tagType)} - {#if typeof tag === 'object' && tag.name && tag.url} - - e.stopPropagation()} - > - {tag.name} - - - - - - - {:else if typeof tag === 'string'} - - - {tag} - - {/if} - {/each} - {/if} -
    diff --git a/frontend/app/src/routes/networks/components/ActionsBar.svelte b/frontend/app/src/routes/networks/components/ActionsBar.svelte deleted file mode 100644 index 145a6906..00000000 --- a/frontend/app/src/routes/networks/components/ActionsBar.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - -
    - -
    diff --git a/frontend/app/src/routes/networks/components/RegisterPathDialog.svelte b/frontend/app/src/routes/networks/components/RegisterPathDialog.svelte deleted file mode 100644 index 3474807f..00000000 --- a/frontend/app/src/routes/networks/components/RegisterPathDialog.svelte +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - Register network from path - - Paste the absolute path to a .nc file. The file stays in place; only its path - is recorded. - - -
    - -
    - - -
    -
    -
    -
    diff --git a/frontend/app/src/routes/networks/components/UploadButton.svelte b/frontend/app/src/routes/networks/components/UploadButton.svelte deleted file mode 100644 index 317562e6..00000000 --- a/frontend/app/src/routes/networks/components/UploadButton.svelte +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - {#snippet child({ props }: { props: Record })} - - {/snippet} - - - {#if features.localMode} - (pathOpen = true)} disabled={importing}> - - From path - - {:else} - fileInput.click()} disabled={importing}> - - From file - - (urlOpen = true)} disabled={importing}> - - From URL - - {/if} - - - - onUpload?.()} -/> - - onUpload?.()} -/> diff --git a/frontend/app/src/routes/networks/components/UrlImportDialog.svelte b/frontend/app/src/routes/networks/components/UrlImportDialog.svelte deleted file mode 100644 index fca86645..00000000 --- a/frontend/app/src/routes/networks/components/UrlImportDialog.svelte +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - Import network from URL - Paste a direct link to a PyPSA .nc file. - -
    - -
    - - -
    -
    -
    -
    diff --git a/frontend/app/src/routes/networks/components/columns.ts b/frontend/app/src/routes/networks/components/columns.ts deleted file mode 100644 index 5ea5e0fb..00000000 --- a/frontend/app/src/routes/networks/components/columns.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { renderComponent } from '$lib/components/ui/data-table/render-helpers.js'; -import FileCell from '../cells/file-cell.svelte'; -import PathCell from '../cells/path-cell.svelte'; -import DimensionsCell from '../cells/dimensions-cell.svelte'; -import TagsCell from '../cells/tags-cell.svelte'; -import DateTime from '$lib/components/DateTime.svelte'; -import ActionsCell from '$lib/components/cells/ActionsCell.svelte'; -import VisibilityCell from '$lib/components/cells/VisibilityCell.svelte'; -import Lock from '@lucide/svelte/icons/lock'; -import Globe from '@lucide/svelte/icons/globe'; -import Trash2 from '@lucide/svelte/icons/trash-2'; -import UserRoundCog from '@lucide/svelte/icons/user-round-cog'; -import OwnerCell from '$lib/components/cells/OwnerCell.svelte'; -import type { ColumnDef } from '@tanstack/table-core'; -import { byDate } from '$lib/utils.js'; -import type { Network, NetworkTag, TagType, TagColor, Visibility } from '$lib/types.js'; - -interface DatabaseColumnsHelpers { - getTagType: (tag: string | NetworkTag) => TagType; - getTagColor: (type: TagType) => TagColor; - formatFileSize: (bytes: number | null | undefined) => string; - handleDelete: (id: string) => void; - handleVisibilityToggle: (id: string, visibility: Visibility) => void; - canEditNetwork: (network: Network) => boolean; - authEnabled: boolean; - handleOwnerChange?: (network: Network) => void; - getDeletingId?: () => string | null; - getUpdatingVisibilityId?: () => string | null; -} - -export const createColumns = (helpers: DatabaseColumnsHelpers): ColumnDef[] => { - const { - getTagType, - getTagColor, - formatFileSize, - handleDelete, - handleVisibilityToggle, - canEditNetwork, - authEnabled, - handleOwnerChange, - getDeletingId = () => null, - getUpdatingVisibilityId = () => null - } = helpers; - - return [ - { - accessorKey: 'filename', - header: 'File', - enableSorting: true, - sortingFn: 'alphanumeric', - cell: (info) => { - const network = info.row.original; - return renderComponent(FileCell, { network }); - }, - }, - { - accessorKey: 'file_path', - header: 'Path', - enableSorting: false, - cell: (info) => { - const network = info.row.original; - return renderComponent(PathCell, { network }); - } - }, - { - accessorKey: 'dimensions', - header: 'Dimensions', - enableSorting: false, - cell: (info) => { - const network = info.row.original; - return renderComponent(DimensionsCell, { network }); - } - }, - { - accessorKey: 'tags', - header: 'Tags', - enableSorting: false, - cell: (info) => { - const network = info.row.original; - return renderComponent(TagsCell, { - network, - getTagType, - getTagColor - }); - }, - }, - // Auth-only columns - ...(authEnabled - ? [ - { - accessorKey: 'visibility', - header: 'Visibility', - enableSorting: true, - cell: (info: { row: { original: Network } }) => { - const network = info.row.original; - return renderComponent(VisibilityCell, { - item: network, - canEdit: canEditNetwork(network), - onToggle: handleVisibilityToggle - }); - } - }, - { - accessorKey: 'owner', - header: 'Owner', - enableSorting: false, - cell: (info: { row: { original: Network } }) => { - const network = info.row.original; - return renderComponent(OwnerCell, { item: network }); - } - } - ] as ColumnDef[] - : []), - { - accessorKey: 'file_size', - header: 'Size', - enableSorting: true, - sortingFn: 'basic', - cell: (info) => { - return formatFileSize(info.getValue() as number); - } - }, - { - accessorKey: 'created_at', - header: 'Created', - enableSorting: true, - sortingFn: byDate((r) => r.created_at), - cell: (info) => { - const val = info.getValue() as string | undefined; - return renderComponent(DateTime, { value: val }); - } - }, - { - id: 'actions', - header: 'Actions', - enableSorting: false, - cell: (info) => { - const network = info.row.original; - const canEdit = canEditNetwork(network); - const isPublic = network.visibility === 'public'; - const isDeleting = getDeletingId() === network.id; - const isUpdatingVisibility = getUpdatingVisibilityId() === network.id; - const actions = []; - if (canEdit) { - if (handleOwnerChange) { - actions.push({ - icon: UserRoundCog, - label: 'Change owner', - onclick: () => handleOwnerChange(network) - }); - } - actions.push({ - icon: isPublic ? Lock : Globe, - label: isPublic ? 'Make private' : 'Make public', - onclick: () => handleVisibilityToggle(network.id, isPublic ? 'private' : 'public'), - loading: isUpdatingVisibility, - loadingLabel: 'Updating...' - }); - actions.push({ - icon: Trash2, - label: 'Delete', - onclick: () => handleDelete(network.id), - loading: isDeleting, - loadingLabel: 'Deleting...', - variant: 'destructive' as const - }); - } - return renderComponent(ActionsCell, { actions }); - } - } - ] as ColumnDef[]; -}; diff --git a/frontend/app/src/routes/pending-approval/+page.svelte b/frontend/app/src/routes/pending-approval/+page.svelte deleted file mode 100644 index 094fd8de..00000000 --- a/frontend/app/src/routes/pending-approval/+page.svelte +++ /dev/null @@ -1,55 +0,0 @@ - - - - Pending Approval - PyPSA App - - -
    -
    - -
    -
    -
    -
    -

    Account Pending Approval

    -

    - Thank you for signing up, {authStore.user?.username}! -

    -
    - -

    - Your account is pending approval by an administrator. - You will be able to access the application once approved. -

    - - -
    -
    -
    -
    - -
    diff --git a/frontend/app/src/routes/runs/+page.svelte b/frontend/app/src/routes/runs/+page.svelte deleted file mode 100644 index 75dd5628..00000000 --- a/frontend/app/src/routes/runs/+page.svelte +++ /dev/null @@ -1,340 +0,0 @@ - - -
    -
    -
    - -
    - - {#if viewState === 'loading'} - 10 ? 10 : pageSize} /> - {:else if viewState === 'empty'} - - {:else} - goto(`/runs/${run.id}`)} - > - {#snippet renderOption({ category, option })} - {#if category.key === 'status'} - - {:else if category.key === 'owner'} - - - {#if option.avatarUrl} - - {/if} - {option.label.slice(0, 2).toUpperCase()} - - {option.label} - - {:else} - {option.label} - {/if} - {/snippet} - - {/if} -
    -
    - - loadRuns()} /> diff --git a/frontend/app/src/routes/runs/[id]/+page.svelte b/frontend/app/src/routes/runs/[id]/+page.svelte deleted file mode 100644 index 687ce055..00000000 --- a/frontend/app/src/routes/runs/[id]/+page.svelte +++ /dev/null @@ -1,624 +0,0 @@ - - -
    -
    - {#if isPublicMode} - - {#if publicLoading} - - {:else if publicNotFound} - - {:else if publicError} -
    -

    {publicError}

    -
    - {:else if publicRun} - - - - {/if} - {:else} - - {#if loading && !run} - - {:else if run} - - {#snippet actions()} - - - {#snippet child({ props }: { props: Record })} - - {/snippet} - - - {#if !isSettled} - - - Cancel - - {/if} - {#if isSettled} - - - Rerun - - {/if} - {#if canEditRun} - - {#if run?.visibility === 'public'} - - Make private - {:else} - - Make public - {/if} - - {/if} - - - - Remove - - - - {/snippet} - {#snippet extraChips()} - {#if run && authStore.authEnabled} -
    -
    - {#if run.visibility === 'public'} - - Public - {:else} - - Private - {/if} -
    - {/if} - {/snippet} -
    - - - {#if run.status !== 'PENDING' && run.status !== 'SETUP'} - - {/if} - - - {#if isTerminal} -
    - - {#if outputsOpen && outputFiles && outputFiles.length > 0} -
    - -
    - {/if} -
    - {/if} - - -
    - - {#if logsOpen} -
    - {#if logs.length === 0} - - {#if streaming} - Waiting for logs... - {:else if isTerminal} - No logs available. - {:else} - Connecting... - {/if} - - {:else} - {#each logs as line, i} -
    {line}
    - {/each} - {/if} -
    - {/if} -
    - - -
    - - {#if configOpen} -
    -
    Workflow
    -
    {run.workflow}
    - - {#if run.configfile} -
    Config
    -
    {run.configfile}
    - {/if} - - {#if run.snakemake_args?.length} -
    Args
    -
    {run.snakemake_args.join(' ')}
    - {/if} - - {#if run.cache} -
    Cache
    -
    - key: {run.cache.key}, dirs: {run.cache.dirs.join(', ')} -
    - {/if} - - {#if run.import_networks?.length} -
    Import networks
    -
    {run.import_networks.join(', ')}
    - {/if} - - {#if run.extra_files && Object.keys(run.extra_files).length} -
    Extra files
    -
    {Object.keys(run.extra_files).join(', ')}
    - {/if} -
    - {/if} -
    - {:else} - - {/if} - {/if} -
    -
    diff --git a/frontend/app/src/routes/runs/[id]/dag/+page.svelte b/frontend/app/src/routes/runs/[id]/dag/+page.svelte deleted file mode 100644 index 3d3e640b..00000000 --- a/frontend/app/src/routes/runs/[id]/dag/+page.svelte +++ /dev/null @@ -1,180 +0,0 @@ - - -
    - - {#if workflow} -
    - {workflow.jobs_finished}/{workflow.total_job_count} jobs -
    - {#each layerOptions as layer} - - {/each} -
    -
    - {/if} - - -
    - -
    - {#if loading && !workflow} -
    - -
    - {:else if error} -
    - {error} -
    - {:else if workflow?.rulegraph} - { selectedRuleName = name; }} - /> - {:else} -
    - No DAG available. -
    - {/if} -
    - - - {#if selectedRule} -
    -
    - Rule Details - -
    - -
    - {/if} -
    -
    diff --git a/frontend/app/src/routes/runs/cells/StatusBadge.svelte b/frontend/app/src/routes/runs/cells/StatusBadge.svelte deleted file mode 100644 index 199ff9ac..00000000 --- a/frontend/app/src/routes/runs/cells/StatusBadge.svelte +++ /dev/null @@ -1,37 +0,0 @@ - - - - {#if statusConfig.active} - - {/if} - {statusConfig.label} - diff --git a/frontend/app/src/routes/runs/cells/jobs-cell.svelte b/frontend/app/src/routes/runs/cells/jobs-cell.svelte deleted file mode 100644 index 752fd68d..00000000 --- a/frontend/app/src/routes/runs/cells/jobs-cell.svelte +++ /dev/null @@ -1,10 +0,0 @@ - - -{#if run.total_job_count != null} - {run.jobs_finished ?? 0}/{run.total_job_count} -{:else} - — -{/if} diff --git a/frontend/app/src/routes/runs/cells/status-cell.svelte b/frontend/app/src/routes/runs/cells/status-cell.svelte deleted file mode 100644 index c09223ba..00000000 --- a/frontend/app/src/routes/runs/cells/status-cell.svelte +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/frontend/app/src/routes/runs/cells/text-with-title-cell.svelte b/frontend/app/src/routes/runs/cells/text-with-title-cell.svelte deleted file mode 100644 index 7ebe7485..00000000 --- a/frontend/app/src/routes/runs/cells/text-with-title-cell.svelte +++ /dev/null @@ -1,5 +0,0 @@ - - -{text} diff --git a/frontend/app/src/routes/runs/cells/workflow-cell.svelte b/frontend/app/src/routes/runs/cells/workflow-cell.svelte deleted file mode 100644 index ed5b6a99..00000000 --- a/frontend/app/src/routes/runs/cells/workflow-cell.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -{#if ref} -
    - {ref} - {source} -
    -{:else} - {source} -{/if} diff --git a/frontend/app/src/routes/runs/components/CreateRunDialog.svelte b/frontend/app/src/routes/runs/components/CreateRunDialog.svelte deleted file mode 100644 index 66ebe53f..00000000 --- a/frontend/app/src/routes/runs/components/CreateRunDialog.svelte +++ /dev/null @@ -1,356 +0,0 @@ - - -{#snippet infoTip(text: string | undefined)} - {#if text} - - - {#snippet child({ props }: { props: Record })} - - - - {/snippet} - -

    {text}

    -
    - {/if} -{/snippet} - - - - - Create Run - Trigger a new workflow run. - - -
    -
    -
    - - {@render infoTip(descriptions.workflow)} -
    - (workflowError = '')} - /> - {#if workflowError} -

    {workflowError}

    - {/if} -
    - -
    -
    - - {@render infoTip(descriptions.git_ref)} -
    - -
    - -
    -
    - - {@render infoTip(descriptions.configfile)} -
    - -
    - - {#if backendsLoaded && backends.length > 1} -
    -
    - - {@render infoTip(descriptions.backend_id)} -
    - - {selectedBackendName} - - {#each backends as b} - - {b.name}{!b.is_active ? ' (inactive)' : ''} - - {/each} - - -
    - {/if} - -
    - - - {@render infoTip(descriptions.visibility)} -
    - -
    -
    - - {@render infoTip(descriptions.import_networks)} -
    - -
    - -
    - Advanced -
    -
    -
    - - {@render infoTip(descriptions.snakemake_args)} -
    - -
    - -
    -
    - - {@render infoTip(descriptions.callback_url)} -
    - -
    - -
    -
    - - {@render infoTip(descriptions.extra_files)} -
    - - {#if extraFilesError} -

    {extraFilesError}

    - {/if} -
    - -
    -
    - - {@render infoTip(descriptions['cache.key'])} -
    - -
    - -
    -
    - - {@render infoTip(descriptions['cache.dirs'])} -
    - -
    -
    -
    -
    - - - - - -
    -
    diff --git a/frontend/app/src/routes/runs/components/OutputFilesTree.svelte b/frontend/app/src/routes/runs/components/OutputFilesTree.svelte deleted file mode 100644 index ef4dac85..00000000 --- a/frontend/app/src/routes/runs/components/OutputFilesTree.svelte +++ /dev/null @@ -1,246 +0,0 @@ - - -{#snippet treeRow(node: TreeNode, depth: number)} - {#if node.isDir} - - {#if expanded.has(node.path)} - {#each node.children as child} - {@render treeRow(child, depth + 1)} - {/each} - {/if} - {:else} - - {/if} -{/snippet} - -
    - {#each tree as node} - {@render treeRow(node, 0)} - {/each} -
    diff --git a/frontend/app/src/routes/runs/components/RulePanel.svelte b/frontend/app/src/routes/runs/components/RulePanel.svelte deleted file mode 100644 index d01d30db..00000000 --- a/frontend/app/src/routes/runs/components/RulePanel.svelte +++ /dev/null @@ -1,293 +0,0 @@ - - -{#snippet jobDetail(jobIndex: number, inputs: {file_type: string; path: string}[], outputs: {file_type: string; path: string}[], logPath: string | null, currentTab: 'files' | 'logs', setTab: (tab: 'files' | 'logs') => void)} - {@const hasFiles = inputs.length > 0 || outputs.length > 0} - {@const hasLog = !!logPath} - {#if hasFiles || hasLog} -
    -
    - {#if hasFiles} - - {/if} - {#if hasLog} - - {/if} - {#if currentTab === 'logs' && hasLog && logPath} - e.stopPropagation()} - > - - Raw logs - - - {/if} -
    - {#if currentTab === 'files' && hasFiles} -
    - {#if inputs.length > 0} -
    - Inputs -
      - {#each inputs as f} -
    • {shortPath(f.path)}
    • - {/each} -
    -
    - {/if} - {#if outputs.length > 0} -
    - Outputs -
      - {#each outputs as f} -
    • {shortPath(f.path)}
    • - {/each} -
    -
    - {/if} -
    - {:else if currentTab === 'logs' && hasLog && logPath} - {#if logLoading[jobIndex]} - Loadingâ€Ļ - {:else if logCache[jobIndex] !== undefined} -
    {logCache[jobIndex]}
    - {/if} - {/if} -
    - {/if} -{/snippet} - -{#if rule.jobs?.length === 1} - {@const job = rule.jobs[0]} - {@const inputs = job.files?.filter(f => f.file_type === 'INPUT') ?? []} - {@const outputs = job.files?.filter(f => f.file_type === 'OUTPUT') ?? []} - {@const logPath = getJobLogPath(job)} - {@render jobDetail(0, inputs, outputs, logPath, activeTab, (tab) => { activeTabOverride = tab; })} -{:else if rule.jobs?.length > 1} - - - - Wildcards - {#if anyJobLogs} - - {/if} - Duration - - - - - {#each rule.jobs as job, i} - {@const expandable = jobIsExpandable(job)} - {@const duration = jobDuration(job)} - {@const status = job.status.toLowerCase()} - {@const inputs = job.files?.filter(f => f.file_type === 'INPUT') ?? []} - {@const outputs = job.files?.filter(f => f.file_type === 'OUTPUT') ?? []} - { if (expandable) expandedJobIndex = expandedJobIndex === i ? null : i; }} - > - -
    - - {formatWildcards(job.wildcards)} -
    -
    - {#if anyJobLogs} - - {#if getJobLogPath(job)} - - {/if} - - {/if} - - {#if duration > 0} -
    -
    -
    -
    - {formatDuration(duration)} -
    - {:else} - - {/if} -
    - - {#if expandable} - - {/if} - -
    - {#if expandable && expandedJobIndex === i} - - - - {@const logPath = getJobLogPath(job)} - {@const hasFiles = inputs.length > 0 || outputs.length > 0} - {@const defaultJobTab = hasFiles ? 'files' : 'logs'} - {@const currentTab = activeJobTab[i] ?? defaultJobTab} - {@render jobDetail(i, inputs, outputs, logPath, currentTab, (tab) => { activeJobTab[i] = tab; })} - - - {/if} - {/each} -
    -
    -{:else} -

    No jobs yet.

    -{/if} diff --git a/frontend/app/src/routes/runs/components/RunHeader.svelte b/frontend/app/src/routes/runs/components/RunHeader.svelte deleted file mode 100644 index 4dd3992c..00000000 --- a/frontend/app/src/routes/runs/components/RunHeader.svelte +++ /dev/null @@ -1,141 +0,0 @@ - - -
    - -
    - -
    - {#if configDisplay && workflowDisplay} -

    {workflowDisplay}

    - {/if} -

    - {#if configDisplay} - {configDisplay} - {:else if workflowDisplay} - {workflowDisplay} - {:else} - Run {run.id.slice(0, 8)} - {/if} -

    -
    - {#if actions} -
    - {@render actions()} -
    - {/if} -
    - - -
    - {#if run.git_ref || run.git_sha} -
    - - {run.git_ref || ''}{run.git_sha ? `@${run.git_sha.slice(0, 8)}` : ''} -
    -
    - {/if} - {#if duration} -
    - - {duration} -
    -
    - {/if} -
    - - -
    -
    -
    - - {run.backend.name} -
    - {#if extraChips} - {@render extraChips()} - {/if} - {#if run.owner} -
    - {#if run.owner.avatar_url} - {run.owner.username} - {/if} - {run.owner.username} -
    - {/if} -
    - - - {#if run.networks.length > 0} -
    -

    Output networks

    -
    - {#each run.networks as network} - - - {network.source_path ?? network.filename} - - - {/each} -
    -
    - {/if} - - - {#if !isTerminal && progress} -
    -
    - {progress.done}/{progress.total} - {progress.pct}% -
    -
    -
    -
    -
    - {/if} -
    diff --git a/frontend/app/src/routes/runs/components/WorkflowDag.svelte b/frontend/app/src/routes/runs/components/WorkflowDag.svelte deleted file mode 100644 index 991c5e74..00000000 --- a/frontend/app/src/routes/runs/components/WorkflowDag.svelte +++ /dev/null @@ -1,347 +0,0 @@ - - -{#if layoutNodes.length > 0} -
    - - - - - - - - {#each layoutEdges as edge} - - {/each} - - {#each layoutNodes as node} - {@const hasLayers = activeLayers.size > 0} - {@const labelY = hasLayers ? node.y + 16 : node.y + node.height / 2} - onSelectRule(node.id)} - role="button" - tabindex="0" - onkeydown={(e) => { if (e.key === 'Enter') onSelectRule(node.id); }} - > - - - {node.id} - - - {#if hasLayers} - {@const baseY = node.y + 28} - {@const wcAll = activeLayers.has('wildcards') ? ruleWildcards(node.id) : []} - {@const wcShown = wcAll.slice(0, MAX_LIST_ITEMS)} - {@const wcMore = wcAll.length - wcShown.length} - {@const wcSectionH = wcAll.length > 0 ? SECTION_HEADER + cappedCount(wcAll.length) * 14 : 0} - {@const filesAll = activeLayers.has('files') ? ruleOutputFiles(node.id) : []} - {@const filesShown = filesAll.slice(0, MAX_LIST_ITEMS)} - {@const filesMore = filesAll.length - filesShown.length} - {@const filesSectionH = filesAll.length > 0 ? SECTION_HEADER + cappedCount(filesAll.length) * 14 : 0} - {@const durationMs = activeLayers.has('duration') ? ruleDurationMs(node.id) : 0} - - {#if wcAll.length > 0} - - WILDCARDS - - {#each wcShown as wc, i} - - {truncate(wc, 22)} - - {/each} - {#if wcMore > 0} - - +{wcMore} more - - {/if} - {/if} - - {#if filesAll.length > 0} - {@const filesY = baseY + wcSectionH} - - FILES - - {#each filesShown as file, i} - - â€ĸ {truncate(file.split('/').pop() ?? file, 20)} - - {/each} - {#if filesMore > 0} - - +{filesMore} more - - {/if} - {/if} - - {#if durationMs > 0} - {@const durY = baseY + wcSectionH + filesSectionH} - {@const barMaxW = node.width - 16} - {@const barW = maxDuration > 0 ? (durationMs / maxDuration) * barMaxW : 0} - - DURATION - - - {rules.some(r => r.name === node.id && r.total_job_count > 1) ? 'ø ' : ''}{formatDurationMs(durationMs)} - - - {/if} - - {/if} - - {/each} - -
    -{/if} diff --git a/frontend/app/src/routes/runs/components/WorkflowSection.svelte b/frontend/app/src/routes/runs/components/WorkflowSection.svelte deleted file mode 100644 index b2a7022b..00000000 --- a/frontend/app/src/routes/runs/components/WorkflowSection.svelte +++ /dev/null @@ -1,296 +0,0 @@ - - -{#if workflow && (workflow.total_job_count > 0 || workflow.errors.length > 0)} -
    - - - {#if sectionOpen} -
    - - {#if workflow.rules.length > 0} - - - - Rule - {#if anyWildcards} - - {/if} - {#if anyLogs} - - {/if} - Duration - - - - - {#each sortedRules as rule} - {@const status = ruleStatus(rule)} - {@const hasJobs = ruleHasJobs(rule)} - {@const duration = ruleDuration(rule)} - {@const ruleLogPath = getRuleLogPath(rule)} - {@const hasNonEmptyLog = !!ruleLogPath} - { if (hasJobs) expandedRuleName = expandedRuleName === rule.name ? null : rule.name; }} - > - -
    - - {rule.name} -
    -
    - {#if anyWildcards} - - {#if rule.total_job_count > 1} - - - {rule.jobs_finished < rule.total_job_count - ? `${rule.jobs_finished}/${rule.total_job_count}` - : `×${rule.total_job_count}`} - - {/if} - - {/if} - {#if anyLogs} - - {#if hasNonEmptyLog} - - {/if} - - {/if} - - {#if duration > 0} -
    -
    -
    -
    - {rule.total_job_count > 1 ? 'ø ' : ''}{formatDuration(duration)} -
    - {:else} - - {/if} -
    - - {#if hasJobs} - - {/if} - -
    - {#if hasJobs && expandedRuleName === rule.name} - - - - - - - {/if} - {/each} -
    -
    - {/if} -
    - {/if} -
    -{/if} diff --git a/frontend/app/src/routes/runs/components/columns.ts b/frontend/app/src/routes/runs/components/columns.ts deleted file mode 100644 index d057280c..00000000 --- a/frontend/app/src/routes/runs/components/columns.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { renderComponent } from '$lib/components/ui/data-table/render-helpers.js'; -import { formatDate, formatDuration, byDate } from '$lib/utils.js'; -import DateTime from '$lib/components/DateTime.svelte'; -import StatusCell from '../cells/status-cell.svelte'; -import TextWithTitleCell from '../cells/text-with-title-cell.svelte'; -import WorkflowCell from '../cells/workflow-cell.svelte'; -import JobsCell from '../cells/jobs-cell.svelte'; -import ActionsCell from '$lib/components/cells/ActionsCell.svelte'; -import VisibilityCell from '$lib/components/cells/VisibilityCell.svelte'; -import X from '@lucide/svelte/icons/x'; -import Trash2 from '@lucide/svelte/icons/trash-2'; -import RotateCw from '@lucide/svelte/icons/rotate-cw'; -import LockKeyhole from '@lucide/svelte/icons/lock-keyhole'; -import Globe from '@lucide/svelte/icons/globe'; -import OwnerCell from '$lib/components/cells/OwnerCell.svelte'; -import type { ColumnDef } from '@tanstack/table-core'; -import { RUN_SETTLED_STATUSES } from '$lib/types.js'; -import type { RunSummary, Visibility } from '$lib/types.js'; - -interface RunsColumnsHelpers { - handleCancel: (id: string) => void; - handleRemove: (id: string) => void; - handleRerun: (run: RunSummary) => void; - handleVisibilityToggle: (id: string, visibility: Visibility) => void; - canEditRun: (run: RunSummary) => boolean; - authEnabled: boolean; - getCancellingId?: () => string | null; - getRemovingId?: () => string | null; - getUpdatingVisibilityId?: () => string | null; - getTick?: () => number; -} - -export const createColumns = (helpers: RunsColumnsHelpers): ColumnDef[] => { - const { - handleCancel, - handleRemove, - handleRerun, - handleVisibilityToggle, - canEditRun, - authEnabled, - getCancellingId = () => null, - getRemovingId = () => null, - getUpdatingVisibilityId = () => null, - getTick = () => 0 - } = helpers; - - return [ - { - accessorKey: 'status', - header: 'Status', - enableSorting: true, - cell: (info) => { - const run = info.row.original; - return renderComponent(StatusCell, { run }); - } - }, - { - accessorKey: 'workflow', - header: 'Workflow', - enableSorting: true, - sortingFn: 'alphanumeric', - cell: (info) => { - const run = info.row.original; - return renderComponent(WorkflowCell, { run }); - } - }, - { - accessorKey: 'configfile', - header: 'Config', - enableSorting: true, - sortingFn: 'alphanumeric', - cell: (info) => { - return (info.getValue() as string) || '\u2014'; - } - }, - { - id: 'duration', - header: 'Duration', - enableSorting: false, - cell: (info) => { - const run = info.row.original; - // Read tick to force re-render every second while run is active - if (!run.completed_at) getTick(); - const text = formatDuration(run.started_at, run.completed_at) ?? '\u2014'; - const title = run.completed_at ? formatDate(run.completed_at) : ''; - return renderComponent(TextWithTitleCell, { text, title }); - } - }, - { - id: 'jobs', - header: 'Jobs', - enableSorting: false, - cell: (info) => { - const run = info.row.original; - return renderComponent(JobsCell, { run }); - } - }, - { - accessorKey: 'created_at', - header: 'Created', - enableSorting: true, - sortingFn: byDate((r) => r.created_at), - cell: (info) => { - const val = info.getValue() as string; - // Read tick to force re-render every second while run is active - if (!info.row.original.completed_at) getTick(); - return renderComponent(DateTime, { value: val }); - } - }, - { - id: 'backend', - header: 'Backend', - enableSorting: false, - cell: (info) => { - const run = info.row.original; - return run.backend?.name || '\u2014'; - } - }, - // Only shown when auth is enabled - ...(authEnabled - ? [ - { - accessorKey: 'visibility', - header: 'Visibility', - enableSorting: true, - cell: (info: { row: { original: RunSummary } }) => { - const run = info.row.original; - return renderComponent(VisibilityCell, { - item: run, - canEdit: canEditRun(run), - onToggle: handleVisibilityToggle - }); - } - }, - { - accessorKey: 'owner', - header: 'Owner', - enableSorting: false, - cell: (info: { row: { original: RunSummary } }) => { - const run = info.row.original; - return renderComponent(OwnerCell, { item: run }); - } - } - ] as ColumnDef[] - : []), - { - id: 'actions', - header: '', - enableSorting: false, - cell: (info) => { - const run = info.row.original; - const isSettled = RUN_SETTLED_STATUSES.has(run.status); - const isCancelling = getCancellingId() === run.id; - const isRemoving = getRemovingId() === run.id; - const isUpdatingVisibility = getUpdatingVisibilityId() === run.id; - const isPublic = run.visibility === 'public'; - const canEdit = canEditRun(run); - const actions = []; - if (!isSettled) { - actions.push({ - icon: X, - label: 'Cancel', - onclick: () => handleCancel(run.id), - loading: isCancelling - }); - } - if (isSettled) { - actions.push({ - icon: RotateCw, - label: 'Rerun', - onclick: () => handleRerun(run) - }); - } - if (authEnabled && canEdit) { - actions.push({ - icon: isPublic ? LockKeyhole : Globe, - label: isPublic ? 'Make private' : 'Make public', - onclick: () => handleVisibilityToggle(run.id, isPublic ? 'private' : 'public'), - loading: isUpdatingVisibility, - loadingLabel: 'Updating...' - }); - } - actions.push({ - icon: Trash2, - label: 'Remove', - onclick: () => handleRemove(run.id), - loading: isRemoving, - variant: 'destructive' as const - }); - return renderComponent(ActionsCell, { actions }); - } - } - ] as ColumnDef[]; -}; diff --git a/frontend/app/static/pypsa-logo.svg b/frontend/app/static/pypsa-logo.svg deleted file mode 100644 index 5c92eec6..00000000 --- a/frontend/app/static/pypsa-logo.svg +++ /dev/null @@ -1,25 +0,0 @@ - - diff --git a/frontend/app/static/robots.txt b/frontend/app/static/robots.txt deleted file mode 100644 index eb053628..00000000 --- a/frontend/app/static/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: diff --git a/frontend/app/svelte.config.js b/frontend/app/svelte.config.js deleted file mode 100644 index 62fa6fa2..00000000 --- a/frontend/app/svelte.config.js +++ /dev/null @@ -1,27 +0,0 @@ -import adapter from '@sveltejs/adapter-static'; - -// Use environment variable to determine output path -// In Docker builds, use 'build' directory (default for adapter-static) -// In local development, output directly to backend static directory -const isDockerBuild = process.env.DOCKER_BUILD === 'true'; -const outputPath = isDockerBuild ? 'build' : '../../src/pypsa_app/backend/static/app'; - -/** @type {import('@sveltejs/kit').Config} */ -const config = { - kit: { - // Use static adapter for building to static files that can be served by FastAPI - adapter: adapter({ - pages: outputPath, - assets: outputPath, - fallback: 'index.html', // SPA mode - all routes return index.html - precompress: false, - strict: true - }), - // Keep API routes pointing to /api/v1 - paths: { - base: '' - } - } -}; - -export default config; diff --git a/frontend/app/tailwind.config.js b/frontend/app/tailwind.config.js deleted file mode 100644 index a09b28c6..00000000 --- a/frontend/app/tailwind.config.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -export default { - darkMode: 'selector', - content: ['./src/**/*.{html,js,svelte,ts}'] -}; diff --git a/frontend/app/tsconfig.json b/frontend/app/tsconfig.json deleted file mode 100644 index a8f10c8e..00000000 --- a/frontend/app/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "moduleResolution": "bundler" - } -} diff --git a/frontend/app/vite.config.js b/frontend/app/vite.config.js deleted file mode 100644 index 5978bb7a..00000000 --- a/frontend/app/vite.config.js +++ /dev/null @@ -1,18 +0,0 @@ -import { sveltekit } from '@sveltejs/kit/vite'; -import { defineConfig } from 'vite'; -import tailwindcss from '@tailwindcss/vite'; - -export default defineConfig({ - plugins: [tailwindcss(), sveltekit()], - server: { - proxy: { - '/api': { - target: 'http://localhost:8000', - changeOrigin: true - } - } - }, - ssr: { - noExternal: ['bits-ui', 'mode-watcher', '@deck.gl/core', '@deck.gl/layers', '@deck.gl/carto', 'maplibre-gl'] - } -}); diff --git a/frontend/src/lib/components/ui/breadcrumb.jsx b/frontend/src/lib/components/ui/breadcrumb.jsx deleted file mode 100644 index d5192423..00000000 --- a/frontend/src/lib/components/ui/breadcrumb.jsx +++ /dev/null @@ -1,92 +0,0 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { ChevronRight, MoreHorizontal } from "lucide-react" - -import { cn } from "$lib/lib/utils" - -const Breadcrumb = React.forwardRef( - ({ ...props }, ref) =>