From 17e769c598937251d3eecf553de6cb035e8a5a7b Mon Sep 17 00:00:00 2001 From: Chris Kruining Date: Tue, 1 Apr 2025 14:17:20 +0200 Subject: [PATCH] got started on new look. pivoting to api implementations now --- .vscode/settings.json | 13 ++ app.config.ts | 29 ++-- bun.lock | 97 +++++++++-- package.json | 9 +- src/app.tsx | 5 +- src/components/dropdown/dropdown.module.css | 96 +++++++++++ src/components/dropdown/dropdown.tsx | 52 ++++++ src/components/dropdown/index.ts | 4 + src/components/hero/hero.module.css | 28 +++- src/components/hero/hero.tsx | 4 +- src/components/list/list.module.css | 12 +- src/components/list/list.tsx | 3 +- src/components/select/index.ts | 3 + src/components/select/select.module.css | 95 +++++++++++ src/components/select/select.tsx | 67 ++++++++ src/features/overview/list-item.module.css | 92 +++++----- src/features/overview/list-item.tsx | 4 +- src/features/overview/overview.module.css | 11 +- src/features/overview/overview.tsx | 16 +- src/features/shell/shell.module.css | 166 +++++++++++++++--- src/features/shell/shell.tsx | 40 +++-- src/features/theme/context.ts | 80 +++++++++ src/features/theme/index.ts | 4 + src/features/theme/picker.module.css | 9 + src/features/theme/picker.tsx | 43 +++++ src/index.css | 176 +++++++++++++++++++- src/routes/(shell).tsx | 16 +- src/routes/sitemap.xml.ts | 36 ++++ tsconfig.json | 6 +- 29 files changed, 1080 insertions(+), 136 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/components/dropdown/dropdown.module.css create mode 100644 src/components/dropdown/dropdown.tsx create mode 100644 src/components/dropdown/index.ts create mode 100644 src/components/select/index.ts create mode 100644 src/components/select/select.module.css create mode 100644 src/components/select/select.tsx create mode 100644 src/features/theme/context.ts create mode 100644 src/features/theme/index.ts create mode 100644 src/features/theme/picker.module.css create mode 100644 src/features/theme/picker.tsx create mode 100644 src/routes/sitemap.xml.ts diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..1ea911e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "cssvar.files": [ + "./node_modules/open-props/open-props.min.css", + "./src/index.css" + ], + "cssvar.ignore": [], + "cssvar.extensions": [ + "css", + "postcss", + "jsx", + "tsx" + ] +} \ No newline at end of file diff --git a/app.config.ts b/app.config.ts index 20fdd9e..1e12038 100644 --- a/app.config.ts +++ b/app.config.ts @@ -1,23 +1,32 @@ import { defineConfig } from '@solidjs/start/config'; +import { browserslistToTargets, Features } from 'lightningcss'; +import browserslist from 'browserslist'; import solidSvg from 'vite-plugin-solid-svg'; import devtools from 'solid-devtools/vite'; export default defineConfig({ - build: { - sourceMap: true, - }, vite: { + css: { + transformer: 'lightningcss', + lightningcss: { + targets: browserslistToTargets(browserslist('>= .25%')), + include: Features.Nesting | Features.LightDark | Features.Colors | Features.LogicalProperties, + customAtRules: { + property: { + prelude: '', + body: 'style-block', + }, + }, + }, + }, + build: { + cssMinify: 'lightningcss', + }, plugins: [ devtools({ autoname: true, }), solidSvg(), - { - name: 'temp', - configResolved(config) { - console.log(config.resolve.alias); - }, - }, ], }, solid: { @@ -31,4 +40,4 @@ export default defineConfig({ routes: ['/sitemaps.xml'], }, }, -}); +}); \ No newline at end of file diff --git a/bun.lock b/bun.lock index b5e2417..fba0103 100644 --- a/bun.lock +++ b/bun.lock @@ -4,14 +4,21 @@ "": { "name": "streamarr", "dependencies": { + "@solid-primitives/context": "^0.3.0", "@solidjs/meta": "^0.29.4", - "@solidjs/router": "^0.14.10", + "@solidjs/router": "^0.15.3", "@solidjs/start": "^1.1.3", + "open-props": "^1.7.14", + "sitemap": "^8.0.0", "solid-icons": "^1.1.0", "solid-js": "^1.9.5", "vinxi": "^0.5.3", }, "devDependencies": { + "@testing-library/jest-dom": "^6.6.3", + "browserslist": "^4.24.4", + "bun-types": "^1.2.7", + "lightningcss": "^1.29.3", "solid-devtools": "^0.33.0", "vite-plugin-solid-svg": "^0.8.1", "vite-tsconfig-paths": "^5.1.4", @@ -20,6 +27,8 @@ }, }, "packages": { + "@adobe/css-tools": ["@adobe/css-tools@4.4.2", "", {}, "sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A=="], + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], @@ -270,6 +279,8 @@ "@solid-primitives/bounds": ["@solid-primitives/bounds@0.0.122", "", { "dependencies": { "@solid-primitives/event-listener": "^2.3.3", "@solid-primitives/resize-observer": "^2.0.26", "@solid-primitives/static-store": "^0.0.8", "@solid-primitives/utils": "^6.2.3" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-kUq/IprOdFr/rg2upon5lQGOoTnDAmxQS4ASKK2l+VwoKSctdPwgu/4qJxEITZikL+nB0myYZzBZWptySV0cRg=="], + "@solid-primitives/context": ["@solid-primitives/context@0.3.0", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-hVLWfZbXuz23gpJ+flCllbKidlIDCcSTOtlhSo9AhQ/vNiwvenLK8J4B2Hw2WCa4ETGPpQcNfgQHSNffEV5YeQ=="], + "@solid-primitives/cursor": ["@solid-primitives/cursor@0.0.115", "", { "dependencies": { "@solid-primitives/utils": "^6.2.3" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-8nEmUN/sacXPChwuJOAi6Yi6VnxthW/Jk8VGvvcF38AenjUvOA6FHI6AkJILuFXjQw1PGxia1YbH/Mn77dPiOA=="], "@solid-primitives/event-listener": ["@solid-primitives/event-listener@2.4.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-TSfR1PNTfojFEYGSxSMCnUhXsaYWBo4p+cm73QmWODa9YnaQAk6PB7VjzG2bOT2D817VlvuOqTj0Qdq+MZrdGg=="], @@ -296,7 +307,7 @@ "@solidjs/meta": ["@solidjs/meta@0.29.4", "", { "peerDependencies": { "solid-js": ">=1.8.4" } }, "sha512-zdIWBGpR9zGx1p1bzIPqF5Gs+Ks/BH8R6fWhmUa/dcK1L2rUC8BAcZJzNRYBQv74kScf1TSOs0EY//Vd/I0V8g=="], - "@solidjs/router": ["@solidjs/router@0.14.10", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-5B8LVgvvXijfXyXWPVLUm7RQ05BhjIpAyRkYVDZtrR3OaSvftXobWc6qSEwk4ICLoGi/IE9CUp2LUdCBIs9AXg=="], + "@solidjs/router": ["@solidjs/router@0.15.3", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-iEbW8UKok2Oio7o6Y4VTzLj+KFCmQPGEpm1fS3xixwFBdclFVBvaQVeibl1jys4cujfAK5Kn6+uG2uBm3lxOMw=="], "@solidjs/start": ["@solidjs/start@1.1.3", "", { "dependencies": { "@tanstack/server-functions-plugin": "^1.105.2", "@vinxi/plugin-directives": "^0.5.0", "@vinxi/server-components": "^0.5.0", "defu": "^6.1.2", "error-stack-parser": "^2.1.4", "html-to-image": "^1.11.11", "radix3": "^1.1.0", "seroval": "^1.0.2", "seroval-plugins": "^1.0.2", "shiki": "^1.26.1", "source-map-js": "^1.0.2", "terracotta": "^1.0.4", "tinyglobby": "^0.2.2", "vite-plugin-solid": "^2.11.1" }, "peerDependencies": { "vinxi": "^0.5.3" } }, "sha512-JjBQDk+5xIRVgAdh3A5/caWq1g2LaVh41mQTcl7ACKfmnYRkHkvGezV4XnckTBxXkmFYkXKxwCWavguPA0JE5g=="], @@ -308,6 +319,8 @@ "@tanstack/server-functions-plugin": ["@tanstack/server-functions-plugin@1.114.12", "", { "dependencies": { "@babel/code-frame": "7.26.2", "@babel/core": "^7.26.8", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.26.8", "@babel/traverse": "^7.26.8", "@babel/types": "^7.26.8", "@tanstack/directive-functions-plugin": "1.114.12", "babel-dead-code-elimination": "^1.0.9", "dedent": "^1.5.3", "tiny-invariant": "^1.3.3" } }, "sha512-tBxLS6eKPrqiViAw5R7yIgdjB7iuLCnsAGcXyHdpMCzHVT8dA/Ac4TwhWYHMt2ltsxnShm2zz9n0ErwRpugJpQ=="], + "@testing-library/jest-dom": ["@testing-library/jest-dom@6.6.3", "", { "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.6.3", "lodash": "^4.17.21", "redent": "^3.0.0" } }, "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA=="], + "@trysound/sax": ["@trysound/sax@0.2.0", "", {}, "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA=="], "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], @@ -328,10 +341,16 @@ "@types/micromatch": ["@types/micromatch@4.0.9", "", { "dependencies": { "@types/braces": "*" } }, "sha512-7V+8ncr22h4UoYRLnLXSpTxjQrNUXtWHGeMPRJt1nULXI57G9bIcpyrHlmrQ7QK24EyyuXvYcSSWAM8GA9nqCg=="], + "@types/node": ["@types/node@22.13.14", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w=="], + "@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="], + "@types/sax": ["@types/sax@1.2.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A=="], + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + "@types/ws": ["@types/ws@8.18.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw=="], + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], "@vercel/nft": ["@vercel/nft@0.29.2", "", { "dependencies": { "@mapbox/node-pre-gyp": "^2.0.0", "@rollup/pluginutils": "^5.1.3", "acorn": "^8.6.0", "acorn-import-attributes": "^1.9.5", "async-sema": "^3.1.1", "bindings": "^1.4.0", "estree-walker": "2.0.2", "glob": "^10.4.5", "graceful-fs": "^4.2.9", "node-gyp-build": "^4.2.2", "picomatch": "^4.0.2", "resolve-from": "^5.0.0" }, "bin": { "nft": "out/cli.js" } }, "sha512-A/Si4mrTkQqJ6EXJKv5EYCDQ3NL6nJXxG8VGXePsaiQigsomHYQC9xSpX8qGk7AEZk4b1ssbYIqJ0ISQQ7bfcA=="], @@ -378,7 +397,7 @@ "ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - "ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "ansis": ["ansis@3.17.0", "", {}, "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg=="], @@ -388,8 +407,12 @@ "archiver-utils": ["archiver-utils@5.0.2", "", { "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA=="], + "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], @@ -434,6 +457,8 @@ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + "bun-types": ["bun-types@1.2.7", "", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }, "sha512-P4hHhk7kjF99acXqKvltyuMQ2kf/rzIw3ylEDpCxDS9Xa0X0Yp/gJu/vDCucmWpiur5qJ0lwB2bWzOXa2GlHqA=="], + "c12": ["c12@3.0.2", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.1.8", "defu": "^6.1.4", "dotenv": "^16.4.7", "exsolve": "^1.0.0", "giget": "^2.0.0", "jiti": "^2.4.2", "ohash": "^2.0.5", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.0.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-6Tzk1/TNeI3WBPpK0j/Ss4+gPj3PUJYbWl/MWDJBThFvwNGNkXtd7Cz8BJtD4aRwoGHtzQD0SnxamgUiBH0/Nw=="], "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], @@ -446,7 +471,7 @@ "chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="], - "chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + "chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="], "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], @@ -514,6 +539,8 @@ "css-what": ["css-what@6.1.0", "", {}, "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="], + "css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="], + "csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="], "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], @@ -544,12 +571,14 @@ "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], - "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "diff": ["diff@7.0.0", "", {}, "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="], + "dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="], + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], @@ -660,6 +689,8 @@ "h3": ["h3@1.13.0", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": ">=0.2.0 <0.4.0", "defu": "^6.1.4", "destr": "^2.0.3", "iron-webcrypto": "^1.2.1", "ohash": "^1.1.4", "radix3": "^1.1.2", "ufo": "^1.5.4", "uncrypto": "^0.1.3", "unenv": "^1.10.0" } }, "sha512-vFEAu/yf8UMUcB4s43OaDaigcqpQd14yanmOsn+NcRX3/guSKncyE2rOYhq8RIchgJrPSs/QiIddnTTR1ddiAg=="], + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], @@ -690,6 +721,8 @@ "ignore": ["ignore@7.0.3", "", {}, "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA=="], + "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + "index-to-position": ["index-to-position@1.0.0", "", {}, "sha512-sCO7uaLVhRJ25vz1o8s9IFM3nVS4DkuQnyjMwiQPKvQuBYBDmb8H7zx8ki7nVh4HJQOdVWebyvLE0qt+clruxA=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], @@ -754,6 +787,28 @@ "lazystream": ["lazystream@1.0.1", "", { "dependencies": { "readable-stream": "^2.0.5" } }, "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw=="], + "lightningcss": ["lightningcss@1.29.3", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.29.3", "lightningcss-darwin-x64": "1.29.3", "lightningcss-freebsd-x64": "1.29.3", "lightningcss-linux-arm-gnueabihf": "1.29.3", "lightningcss-linux-arm64-gnu": "1.29.3", "lightningcss-linux-arm64-musl": "1.29.3", "lightningcss-linux-x64-gnu": "1.29.3", "lightningcss-linux-x64-musl": "1.29.3", "lightningcss-win32-arm64-msvc": "1.29.3", "lightningcss-win32-x64-msvc": "1.29.3" } }, "sha512-GlOJwTIP6TMIlrTFsxTerwC0W6OpQpCGuX1ECRLBUVRh6fpJH3xTqjCjRgQHTb4ZXexH9rtHou1Lf03GKzmhhQ=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.29.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-fb7raKO3pXtlNbQbiMeEu8RbBVHnpyqAoxTyTRMEWFQWmscGC2wZxoHzZ+YKAepUuKT9uIW5vL2QbFivTgprZg=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.29.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-KF2XZ4ZdmDGGtEYmx5wpzn6u8vg7AdBHaEOvDKu8GOs7xDL/vcU2vMKtTeNe1d4dogkDdi3B9zC77jkatWBwEQ=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.29.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-VUWeVf+V1UM54jv9M4wen9vMlIAyT69Krl9XjI8SsRxz4tdNV/7QEPlW6JASev/pYdiynUCW0pwaFquDRYdxMw=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.29.3", "", { "os": "linux", "cpu": "arm" }, "sha512-UhgZ/XVNfXQVEJrMIWeK1Laj8KbhjbIz7F4znUk7G4zeGw7TRoJxhb66uWrEsonn1+O45w//0i0Fu0wIovYdYg=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.29.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-Pqau7jtgJNmQ/esugfmAT1aCFy/Gxc92FOxI+3n+LbMHBheBnk41xHDhc0HeYlx9G0xP5tK4t0Koy3QGGNqypw=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.29.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-dxakOk66pf7KLS7VRYFO7B8WOJLecE5OPL2YOk52eriFd/yeyxt2Km5H0BjLfElokIaR+qWi33gB8MQLrdAY3A=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.29.3", "", { "os": "linux", "cpu": "x64" }, "sha512-ySZTNCpbfbK8rqpKJeJR2S0g/8UqqV3QnzcuWvpI60LWxnFN91nxpSSwCbzfOXkzKfar9j5eOuOplf+klKtINg=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.29.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3pVZhIzW09nzi10usAXfIGTTSTYQ141dk88vGFNCgawIzayiIzZQxEcxVtIkdvlEq2YuFsL9Wcj/h61JHHzuFQ=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.29.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-VRnkAvtIkeWuoBJeGOTrZxsNp4HogXtcaaLm8agmbYtLDOhQdpgxW6NjZZjDXbvGF+eOehGulXZ3C1TiwHY4QQ=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.3", "", { "os": "win32", "cpu": "x64" }, "sha512-IszwRPu2cPnDQsZpd7/EAr0x2W7jkaWqQ1SwCVIZ/tSbZVXPLt6k8s6FkcyBjViCzvB5CW0We0QbbP7zp2aBjQ=="], + "listhen": ["listhen@1.9.0", "", { "dependencies": { "@parcel/watcher": "^2.4.1", "@parcel/watcher-wasm": "^2.4.1", "citty": "^0.1.6", "clipboardy": "^4.0.0", "consola": "^3.2.3", "crossws": ">=0.2.0 <0.4.0", "defu": "^6.1.4", "get-port-please": "^3.1.2", "h3": "^1.12.0", "http-shutdown": "^1.2.2", "jiti": "^2.1.2", "mlly": "^1.7.1", "node-forge": "^1.3.1", "pathe": "^1.1.2", "std-env": "^3.7.0", "ufo": "^1.5.4", "untun": "^0.1.3", "uqr": "^0.1.2" }, "bin": { "listen": "bin/listhen.mjs", "listhen": "bin/listhen.mjs" } }, "sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg=="], "local-pkg": ["local-pkg@1.1.1", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.0.1", "quansync": "^0.2.8" } }, "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg=="], @@ -798,6 +853,8 @@ "mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="], + "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], + "minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], @@ -850,6 +907,8 @@ "open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], + "open-props": ["open-props@1.7.14", "", {}, "sha512-rTsf6dGrNhlyyN5+ZAdht50s5A7vzHC/gaA56sQnSfwQU53YzWCMjdzX2hhlK+aK+3ojEwTxsvRSlk3FP8TTHA=="], + "openapi-typescript": ["openapi-typescript@7.6.1", "", { "dependencies": { "@redocly/openapi-core": "^1.28.0", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", "parse-json": "^8.1.0", "supports-color": "^9.4.0", "yargs-parser": "^21.1.1" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-typescript": "bin/cli.js" } }, "sha512-F7RXEeo/heF3O9lOXo2bNjCOtfp7u+D6W3a3VNEH2xE6v+fxLtn5nq0uvUcA1F5aT+CMhNeC5Uqtg5tlXFX/ag=="], "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], @@ -914,6 +973,8 @@ "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="], + "redent": ["redent@3.0.0", "", { "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg=="], + "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="], "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="], @@ -946,6 +1007,8 @@ "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="], + "scule": ["scule@1.3.0", "", {}, "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="], "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -974,6 +1037,8 @@ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "sitemap": ["sitemap@8.0.0", "", { "dependencies": { "@types/node": "^17.0.5", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.2.4" }, "bin": { "sitemap": "dist/cli.js" } }, "sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A=="], + "slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], "smob": ["smob@1.5.0", "", {}, "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig=="], @@ -1022,9 +1087,11 @@ "strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="], + "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], + "strip-literal": ["strip-literal@3.0.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA=="], - "supports-color": ["supports-color@9.4.0", "", {}, "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw=="], + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], @@ -1080,7 +1147,7 @@ "unctx": ["unctx@2.4.1", "", { "dependencies": { "acorn": "^8.14.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.17", "unplugin": "^2.1.0" } }, "sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg=="], - "undici-types": ["undici-types@5.28.4", "", {}, "sha512-3OeMF5Lyowe8VW0skf5qaIE7Or3yS9LS7fvMUI0gg4YxpIBVg0L8BxCmROw2CcYhSkpR68Epz7CGc8MPj94Uww=="], + "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], "unenv": ["unenv@1.10.0", "", { "dependencies": { "consola": "^3.2.3", "defu": "^6.1.4", "mime": "^3.0.0", "node-fetch-native": "^1.6.4", "pathe": "^1.1.2" } }, "sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ=="], @@ -1180,10 +1247,10 @@ "@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], - "@mapbox/node-pre-gyp/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], - "@mapbox/node-pre-gyp/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], + "@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + "@parcel/watcher-wasm/napi-wasm": ["napi-wasm@1.1.3", "", { "bundled": true }, "sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg=="], "@poppinss/dumper/supports-color": ["supports-color@10.0.0", "", {}, "sha512-HRVVSbCCMbj7/kdWF9Q+bbckjBHLtHMEoJWlkmYzzdwhYMkjkOwubLM6t7NbWKjgKamGDrWL1++KrjUO1t9oAQ=="], @@ -1214,6 +1281,8 @@ "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], + "boxen/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + "c12/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "c12/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], @@ -1234,6 +1303,8 @@ "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], + "dax-sh/undici-types": ["undici-types@5.28.4", "", {}, "sha512-3OeMF5Lyowe8VW0skf5qaIE7Or3yS9LS7fvMUI0gg4YxpIBVg0L8BxCmROw2CcYhSkpR68Epz7CGc8MPj94Uww=="], + "dot-prop/type-fest": ["type-fest@4.37.0", "", {}, "sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg=="], "is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], @@ -1274,6 +1345,8 @@ "open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + "openapi-typescript/supports-color": ["supports-color@9.4.0", "", {}, "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw=="], + "parse-json/type-fest": ["type-fest@4.37.0", "", {}, "sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg=="], "readdir-glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], @@ -1288,6 +1361,8 @@ "send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + "sitemap/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="], + "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -1326,7 +1401,7 @@ "vite/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], - "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -1344,8 +1419,6 @@ "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], diff --git a/package.json b/package.json index 49dde19..f2690ef 100644 --- a/package.json +++ b/package.json @@ -14,14 +14,21 @@ "test:ci": "vitest run" }, "dependencies": { + "@solid-primitives/context": "^0.3.0", "@solidjs/meta": "^0.29.4", - "@solidjs/router": "^0.14.10", + "@solidjs/router": "^0.15.3", "@solidjs/start": "^1.1.3", + "open-props": "^1.7.14", + "sitemap": "^8.0.0", "solid-icons": "^1.1.0", "solid-js": "^1.9.5", "vinxi": "^0.5.3" }, "devDependencies": { + "@testing-library/jest-dom": "^6.6.3", + "browserslist": "^4.24.4", + "bun-types": "^1.2.7", + "lightningcss": "^1.29.3", "solid-devtools": "^0.33.0", "vite-plugin-solid-svg": "^0.8.1", "vite-tsconfig-paths": "^5.1.4", diff --git a/src/app.tsx b/src/app.tsx index ffdbcc4..488daab 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -3,6 +3,7 @@ import { Router } from "@solidjs/router"; import { FileRoutes } from "@solidjs/start/router"; import { Suspense } from "solid-js"; import './index.css'; +import { ThemeContextProvider } from "./features/theme"; export default function App() { return ( @@ -10,7 +11,9 @@ export default function App() { root={props => ( Streamarr - Home - {props.children} + + {props.children} + )} > diff --git a/src/components/dropdown/dropdown.module.css b/src/components/dropdown/dropdown.module.css new file mode 100644 index 0000000..158052a --- /dev/null +++ b/src/components/dropdown/dropdown.module.css @@ -0,0 +1,96 @@ +.box { + display: contents; + + &:has(> :popover-open) > .button { + background-color: var(--surface-500); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } +} + +.button { + position: relative; + display: grid; + grid-template-columns: inherit; + place-items: center start; + + /* Make sure the height of the button does not collapse when it is empty */ + block-size: 1em; + box-sizing: content-box; + + padding: var(--size-2); + background-color: transparent; + border: none; + border-radius: var(--radius-2); + font-size: 1rem; + line-height: 1; + + cursor: pointer; + + &:hover { + background-color: var(--surface-4); + } + + &:has(> .caret) { + padding-inline-end: calc(1em + (2 * var(--size-2))); + } + + & > .caret { + position: absolute; + inset-inline-end: var(--size-2); + inset-block-start: 50%; + translate: 0 -50%; + inline-size: 1em; + } +} + +.dialog { + display: none; + position: relative; + grid-template-columns: inherit; + + inset-inline-start: anchor(start); + inset-block-start: anchor(end); + position-try-fallbacks: flip-block, flip-inline; + + /* inline-size: anchor-size(self-inline); */ + background-color: var(--surface-4); + padding: var(--size-2); + border: none; + box-shadow: var(--shadow-2); + + &:popover-open { + display: grid; + } + + & > header { + display: grid; + grid-column: 1 / -1; + + gap: var(--size-1); + } + + & > main { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; + row-gap: var(--size-1); + } +} + +.option { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; + place-items: center start; + + border-radius: var(--radius-2); + padding: var(--size-1); + margin-inline: calc(-1 * var(--size-1)); + + cursor: pointer; + + &.selected { + background-color: color(from var(--cyan-4) srgb r g b / .1); + } +} \ No newline at end of file diff --git a/src/components/dropdown/dropdown.tsx b/src/components/dropdown/dropdown.tsx new file mode 100644 index 0000000..d43add3 --- /dev/null +++ b/src/components/dropdown/dropdown.tsx @@ -0,0 +1,52 @@ +import { createSignal, JSX, createEffect, Show } from "solid-js"; +import { FaSolidAngleDown } from "solid-icons/fa"; +import css from './dropdown.module.css'; + +export interface DropdownApi { + show(): void; + hide(): void; +} + +interface DropdownProps { + api?: (api: DropdownApi) => any, + id: string; + class?: string; + open?: boolean; + showCaret?: boolean; + text: JSX.Element; + children: JSX.Element; +} + +export function Dropdown(props: DropdownProps) { + const [dialog, setDialog] = createSignal(); + const [open, setOpen] = createSignal(props.open ?? false); + + createEffect(() => { + dialog()?.[open() ? 'showPopover' : 'hidePopover'](); + }); + + createEffect(() => { + props.api?.({ + show() { + dialog()?.showPopover(); + }, + hide() { + dialog()?.hidePopover(); + }, + }); + }); + + return
+ + + setOpen(e.newState === 'open')}> + {props.children} + +
; +} \ No newline at end of file diff --git a/src/components/dropdown/index.ts b/src/components/dropdown/index.ts new file mode 100644 index 0000000..f3bcb0e --- /dev/null +++ b/src/components/dropdown/index.ts @@ -0,0 +1,4 @@ + + +export type { DropdownApi } from './dropdown'; +export { Dropdown } from './dropdown'; \ No newline at end of file diff --git a/src/components/hero/hero.module.css b/src/components/hero/hero.module.css index 8ed3e2d..a3aa5b6 100644 --- a/src/components/hero/hero.module.css +++ b/src/components/hero/hero.module.css @@ -1,6 +1,7 @@ .container { + position: relative; display: grid; - grid: repeat(3, auto) / 10em 1fr; + grid: repeat(3, auto) / 15em 1fr; grid-template-areas: "thumbnail ." "thumbnail title" @@ -8,12 +9,26 @@ "thumbnail summary"; align-content: end; gap: 1em; + padding: 2em; block-size: 80vh; + overflow: clip; + + color: var(--gray-0); + + &::after { + content: ''; + position: absolute; + inset: 0; + display: block; + background: linear-gradient(transparent 50%, #0007 75%); + } } .title { grid-area: title; font-size: 2.5em; + z-index: 1; + filter: contrast(9); } .thumbnail { @@ -23,23 +38,26 @@ border-radius: 1em; object-fit: cover; object-position: center; + z-index: 1; } .background { - position: fixed; + position: absolute; inset: 0; - z-index: -1; - block-size: 90vh; + block-size: 100%; inline-size: 100%; object-fit: cover; object-position: center; + z-index: 0; } .detail { grid-area: detail; + z-index: 1; } .summary { grid-area: summary; text-wrap: balance; -} + z-index: 1; +} \ No newline at end of file diff --git a/src/components/hero/hero.tsx b/src/components/hero/hero.tsx index 1e00747..6b6fc8b 100644 --- a/src/components/hero/hero.tsx +++ b/src/components/hero/hero.tsx @@ -4,11 +4,13 @@ import css from "./hero.module.css"; type HeroProps = { entry: Entry; + class?: string; }; export function Hero(props: HeroProps) { return ( -
+
+

{props.entry.title}

diff --git a/src/components/list/list.module.css b/src/components/list/list.module.css index 79e0651..d3c7741 100644 --- a/src/components/list/list.module.css +++ b/src/components/list/list.module.css @@ -13,17 +13,19 @@ grid-auto-flow: column; gap: 2em; - padding: 10em 4em 5em; + padding: 12em 4em 5em; scroll-padding: 4em; - margin: -10em -4em 0em; - margin-block-start: -10em; + margin: -12em -4em 0em; - overflow: auto visible; + overflow: visible auto; scroll-snap-type: inline proximity; @media (hover: none) { + padding: 5em; + margin: 0; + & > * { scroll-snap-align: start; } } -} +} \ No newline at end of file diff --git a/src/components/list/list.tsx b/src/components/list/list.tsx index d5bf8c7..2cff1ad 100644 --- a/src/components/list/list.tsx +++ b/src/components/list/list.tsx @@ -4,12 +4,13 @@ import css from "./list.module.css"; interface ListProps { label: string; items: T[]; + class?: string; children: (item: Accessor) => JSX.Element; } export function List(props: ListProps) { return ( -
+
{props.label} diff --git a/src/components/select/index.ts b/src/components/select/index.ts new file mode 100644 index 0000000..30079fc --- /dev/null +++ b/src/components/select/index.ts @@ -0,0 +1,3 @@ + + +export { Select } from './select'; \ No newline at end of file diff --git a/src/components/select/select.module.css b/src/components/select/select.module.css new file mode 100644 index 0000000..1380df8 --- /dev/null +++ b/src/components/select/select.module.css @@ -0,0 +1,95 @@ +.box { + display: contents; + + &:has(> :popover-open) > .button { + background-color: var(--surface-500); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } +} + +.button { + position: relative; + display: grid; + grid-template-columns: inherit; + place-items: center start; + + /* Make sure the height of the button does not collapse when it is empty */ + block-size: 1em; + box-sizing: content-box; + + padding: var(--size-2); + background-color: transparent; + border: none; + border-radius: var(--radius-2); + font-size: 1rem; + + cursor: pointer; + + &:hover { + background-color: var(--surface-700); + } + + &:has(> .caret) { + padding-inline-end: calc(1em + (2 * var(--size-2))); + } + + & > .caret { + position: absolute; + inset-inline-end: var(--size-2); + inset-block-start: 50%; + translate: 0 -50%; + inline-size: 1em; + } +} + +.dialog { + display: none; + position: relative; + grid-template-columns: inherit; + + inset-inline-start: anchor(start); + inset-block-start: anchor(end); + position-try-fallbacks: flip-block, flip-inline; + + /* inline-size: anchor-size(self-inline); */ + background-color: var(--surface-3); + padding: var(--size-2); + border: none; + box-shadow: var(--shadow-2); + + &:popover-open { + display: grid; + } + + & > header { + display: grid; + grid-column: 1 / -1; + + gap: var(--padding-s); + } + + & > main { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; + row-gap: var(--padding-s); + } +} + +.option { + display: grid; + grid-template-columns: subgrid; + grid-column: 1 / -1; + place-items: center start; + + border-radius: var(--radii-m); + padding: var(--padding-s); + margin-inline: calc(-1 * var(--padding-s)); + + cursor: pointer; + + &.selected { + background-color: oklch(from var(--info) l c h / .1); + } +} \ No newline at end of file diff --git a/src/components/select/select.tsx b/src/components/select/select.tsx new file mode 100644 index 0000000..eba8db2 --- /dev/null +++ b/src/components/select/select.tsx @@ -0,0 +1,67 @@ +import { createMemo, createSignal, For, JSX, Setter, createEffect, Show } from "solid-js"; +import { Dropdown, DropdownApi } from "../dropdown"; +import css from './select.module.css'; + +interface SelectProps { + id: string; + class?: string; + value: K; + setValue?: Setter; + values: Record; + open?: boolean; + showCaret?: boolean; + children: (key: K, value: T) => JSX.Element; + filter?: (query: string, key: K, value: T) => boolean; +} + +export function Select(props: SelectProps) { + const [dropdown, setDropdown] = createSignal(); + const [key, setKey] = createSignal(props.value); + const [query, setQuery] = createSignal(''); + + const showCaret = createMemo(() => props.showCaret ?? true); + const values = createMemo(() => { + let entries = Object.entries(props.values) as [K, T][]; + const filter = props.filter; + const q = query(); + + if (filter) { + entries = entries.filter(([k, v]) => filter(q, k, v)); + } + + return entries; + }); + + createEffect(() => { + props.setValue?.(() => key()); + }); + + const text = { + key => { + const value = createMemo(() => props.values[key()]); + + return <>{props.children(key(), value())}; + } + } + + return + +
+ setQuery(e.target.value)} /> +
+
+ +
+ { + ([k, v]) => { + const selected = createMemo(() => key() === k); + + return { + setKey(() => k); + dropdown()?.hide(); + }}>{props.children(k, v)}; + } + } +
+
+} \ No newline at end of file diff --git a/src/features/overview/list-item.module.css b/src/features/overview/list-item.module.css index a8d4ced..34d60cf 100644 --- a/src/features/overview/list-item.module.css +++ b/src/features/overview/list-item.module.css @@ -6,7 +6,7 @@ place-items: start center; position: relative; inline-size: clamp(15em 20vw 30em); - aspect-ratio: 3 / 5; + aspect-ratio: var(--ratio-portrait); transform: translateY(calc(-2 * var(--padding))); z-index: 1; contain: layout size style; @@ -15,23 +15,23 @@ grid-area: 1/ 1; inline-size: 100%; block-size: 100%; - border-radius: 1em; + border-radius: var(--radius-3); object-fit: cover; - object-position: center; + object-position: top center; z-index: 1; - box-shadow: 0 0 1em #000; + box-shadow: var(--shadow-2); background: /* Dot */ - radial-gradient(circle at 25% 30% #7772 #7774 1em transparent 1em) + radial-gradient(circle at 25% 30% #7772 #7774 1em transparent 1em), /* Dot */ - radial-gradient(circle at 85% 15% #7772 #7774 1em transparent 1em) + radial-gradient(circle at 85% 15% #7772 #7774 1em transparent 1em), /* Bottom fade */ - linear-gradient(165deg transparent 60% #555 60% #333) + linear-gradient(165deg transparent 60% #555 60% #333), /* wave dark part */ - radial-gradient(ellipse 5em 2.25em at 0.5em calc(50% - 1em) #333 100% transparent 100%) + radial-gradient(ellipse 5em 2.25em at 0.5em calc(50% - 1em) #333 100% transparent 100%), /* wave light part */ - radial-gradient(ellipse 5em 2.25em at calc(100% - 0.5em) calc(50% + 1em) #555 100% transparent 100%) + radial-gradient(ellipse 5em 2.25em at calc(100% - 0.5em) calc(50% + 1em) #555 100% transparent 100%), /* Base */ linear-gradient(to bottom #333 50% #555 50%); @@ -42,7 +42,7 @@ } & > main { - --ofset: calc(1.5 * var(--padding)); + --offset: calc(1.5 * var(--padding)); grid-area: 1/ 1; display: grid; align-content: end; @@ -50,53 +50,55 @@ inline-size: calc(100% + (3 * var(--padding))); block-size: calc(100% + (4 * var(--padding))); padding: calc(0.5 * var(--padding)); - background-color: #444; - border-radius: 0.5em; + background-color: var(--surface-3); + border-radius: var(--radius-2); transform: translate3d(0 0 0); clip-path: inset(-1em); - box-shadow: 0 0 1em #000; + box-shadow: var(--shadow-2); z-index: 0; &:focus-within { - outline: 1px solid #fff; + outline: 1px solid var(--text-2); outline-offset: 10px; } } -} -@media (hover) { - &:not(:hover):not(:focus-within) { - transform: translateY(0); - z-index: 0; - will-change: transform; - - & > img { - transform: scale(1) translateY(0); + @media (hover) { + &:not(:hover):not(:focus-within) { + transform: translateY(0); + z-index: 0; will-change: transform; - } - - & > main { - clip-path: inset(40%); - } - } - - @media (prefers-reduced-motion: no-preference) { - transition: transform 0.2s linear; - - & > img { - transition: transform 0.2s ease-in-out; - } - - & > main { - transition: clip-path 0.2s ease-in-out; - } - - &:is(:hover :focus-within) { - transition-delay: 0s 0.3s; - z-index: 1; & > img { - transition: transform 0.2s ease-in-out; + transform: scale(1) translateY(0); + will-change: transform; + } + + & > main { + clip-path: inset(40%); + } + } + + @media (prefers-reduced-motion: no-preference) { + & { + transition: transform var(--duration-moderate-1) linear; + } + + & > img { + transition: transform var(--duration-moderate-1) ease-in-out; + } + + & > main { + transition: clip-path var(--duration-moderate-1) ease-in-out; + } + + &:is(:hover :focus-within) { + transition-delay: var(--duration-instant) var(--duration-moderate-2); + z-index: 1; + + & > img { + transition: transform var(--duration-moderate-1) ease-in-out; + } } } } diff --git a/src/features/overview/list-item.tsx b/src/features/overview/list-item.tsx index 5a3474e..5bea4f7 100644 --- a/src/features/overview/list-item.tsx +++ b/src/features/overview/list-item.tsx @@ -4,10 +4,12 @@ import css from "./list-item.module.css"; export const ListItem: Component<{ entry: Entry }> = (props) => { return ( -
+
+ {props.entry.title} + Lets go!
diff --git a/src/features/overview/overview.module.css b/src/features/overview/overview.module.css index 41a362d..84eda8c 100644 --- a/src/features/overview/overview.module.css +++ b/src/features/overview/overview.module.css @@ -2,4 +2,13 @@ display: grid; grid-auto-flow: row; gap: 2em; -} + border-radius: inherit; + + & > .hero { + border-radius: inherit; + } + + & > .list { + padding-inline: 2em; + } +} \ No newline at end of file diff --git a/src/features/overview/overview.tsx b/src/features/overview/overview.tsx index fb98a33..efc8919 100644 --- a/src/features/overview/overview.tsx +++ b/src/features/overview/overview.tsx @@ -1,4 +1,4 @@ -import { Component, Index } from "solid-js"; +import { Component, createEffect, createSignal, Index, onMount } from "solid-js"; import type { Entry, Category } from "../content"; import { ListItem } from "./list-item"; import { List } from "~/components/list"; @@ -11,13 +11,21 @@ type OverviewProps = { }; export const Overview: Component = (props) => { + const [container, setContainer] = createSignal(); + + onMount(() => { + new MutationObserver(() => { + container()?.querySelector(`.${css.list} > ul > div:nth-child(4) > main > a`)?.focus({ preventScroll: true }); + }).observe(document.body, { subtree: true, childList: true }); + }); + return ( -
- +
+ {(category) => ( - + {(entry) => } )} diff --git a/src/features/shell/shell.module.css b/src/features/shell/shell.module.css index 4605d6d..3162206 100644 --- a/src/features/shell/shell.module.css +++ b/src/features/shell/shell.module.css @@ -1,37 +1,161 @@ .container { + position: relative; display: grid; - grid: 100% / 100%; + grid: 2em 1fr / 7.5em 1fr; + grid-template-areas: + 'top top' + 'nav content' + ; + inline-size: 100%; + block-size: 100%; z-index: 0; - overflow-inline: clip; - overflow-block: auto; + overflow: clip; container-type: inline-size; + background-color: var(--surface-1); + + &:has(.nav a:hover) > .body { + filter: blur(3px); + } } .body { - grid-area: 1 / 1; + grid-area: 2 / 1 / 3 / 3; inline-size: 100%; - block-size: fit-content; - padding-inline: 2em; - padding-block-end: 5em; - background: linear-gradient(180deg, transparent, transparent 90vh, #333 90vh, #333); + block-size: 100%; + background: linear-gradient(180deg, transparent, transparent 90vh, var(--surface-500) 90vh, var(--surface-500)); + overflow: clip auto; + padding-inline-start: 7.5em; + transition: filter var(--duration-moderate-1) var(--ease-3); - @container (inline-size >=600px) { - padding-inline-start: 7.5em; + & > div { + border-top-left-radius: var(--radius-4); + background-color: var(--surface-2); + isolation: isolate; + inline-size: 100%; + block-size: fit-content; + min-block-size: 100%; } } -.nav { - grid-area: 1 / 1; - display: none; - grid-auto-flow: row; - align-content: start; - inline-size: 7.5em; - padding: 1em; - position: sticky; - inset-block-start: 0; +.top { + grid-area: top; + display: block grid; + grid-auto-flow: column; + place-content: center end; + z-index: 1; + background-color: inherit; + padding: .5em; +} + +.nav { + grid-area: nav; + display: block grid; + grid-auto-flow: row; + justify-content: space-between; + inline-size: 7.5em; + block-size: 100%; + padding: 1em; + background-color: inherit; + z-index: 0; + + & > ul { + display: block grid; + grid-template-columns: auto auto; + align-content: center; + inline-size: 100%; + gap: .5em; + transform-origin: left center; + padding: 0; + margin: 0; + + & > a { + grid-column: span 2; + display: block grid; + grid-template-columns: subgrid; + align-items: center; + text-decoration: none; + transform-origin: center left; + transition: transform 2s var(--ease-spring-5), opacity 0.3s var(--ease-3); + color: var(--red-4); + + & > svg { + fill: var(--red-4); + } + } + + &:has(a:hover:nth-child(1)) { + --target: 1; + } + + &:has(a:hover:nth-child(2)) { + --target: 2; + } + + &:has(a:hover:nth-child(3)) { + --target: 3; + } + + &:has(a:hover:nth-child(4)) { + --target: 4; + } + + &:has(a:hover:nth-child(5)) { + --target: 5; + } + + &:has(a:hover:nth-child(6)) { + --target: 6; + } + + &:has(a:hover:nth-child(7)) { + --target: 7; + } + + &:has(a:hover:nth-child(8)) { + --target: 8; + } + + &:has(a:hover:nth-child(9)) { + --target: 9; + } + + &:has(a:hover:nth-child(10)) { + --target: 10; + } + + &:has(a:hover:nth-child(11)) { + --target: 11; + } + + &:has(a:hover:nth-child(12)) { + --target: 12; + } + + &:has(a:hover:nth-child(13)) { + --target: 13; + } + + &:has(a:hover:nth-child(14)) { + --target: 14; + } + + &:has(a:hover:nth-child(15)) { + --target: 15; + } + + &:has(a:hover) > a:not(:hover) { + opacity: .25; + } + + &:has(a:hover) > a { + transform: scale(max(1, calc(1.5 - (.2 * abs(var(--target) - var(--sibling-index)))))); + } + } + + &:is(:hover, :focus-within) { + z-index: 1; + - @container (inline-size >=600px) { - display: grid; } } \ No newline at end of file diff --git a/src/features/shell/shell.tsx b/src/features/shell/shell.tsx index 6ca8553..f99955c 100644 --- a/src/features/shell/shell.tsx +++ b/src/features/shell/shell.tsx @@ -6,32 +6,46 @@ import { } from "solid-icons/fa"; import { ParentComponent, Component } from "solid-js"; import css from "./shell.module.css"; +import { ColorSchemePicker } from "../theme"; export const Shell: ParentComponent = (props) => { return (
+
); }; +const Top: Component = (props) => { + return ( + + ); +}; + const Nav: Component = (props) => { return ( ); }; diff --git a/src/features/theme/context.ts b/src/features/theme/context.ts new file mode 100644 index 0000000..50dc279 --- /dev/null +++ b/src/features/theme/context.ts @@ -0,0 +1,80 @@ +import { ContextProviderProps, createContextProvider } from "@solid-primitives/context"; +import { action, createAsyncStore, query, useAction } from "@solidjs/router"; +import { createStore } from "solid-js/store"; +import { useSession } from "vinxi/http"; + + +export enum ColorScheme { + Auto = 'light dark', + Light = 'light', + Dark = 'dark', +} + +export interface State { + colorScheme: ColorScheme; + hue: number; +} + +const getSession = async () => { + 'use server'; + + return useSession({ + password: process.env.SESSION_SECRET!, + }); +}; + +export const getState = query(async () => { + 'use server'; + + const session = await getSession(); + + if (Object.getOwnPropertyNames(session.data).length === 0) { + await session.update({ + colorScheme: ColorScheme.Auto, + hue: 0, + }) + } + + return session.data; +}, 'color-scheme'); + +const setState = action(async (state: State) => { + 'use server'; + + const session = await getSession(); + await session.update(prev => ({ ...prev, ...state })); +}, 'color-scheme'); + +interface ThemeContextType { + readonly theme: State; + setColorScheme(colorScheme: ColorScheme): void; + setHue(colorScheme: number): void; +} + +const [ThemeContextProvider, useTheme] = createContextProvider((props) => { + const updateState = useAction(setState); + const state = createAsyncStore(() => getState()); + + return { + get theme() { + return state.latest ?? { colorScheme: null }; + }, + + setColorScheme(colorScheme) { + updateState({ colorScheme, hue: state.latest!.hue }); + }, + setHue(hue) { + updateState({ hue, colorScheme: state.latest!.colorScheme }); + }, + }; +}, { + theme: { + colorScheme: ColorScheme.Auto, + hue: 180, + }, + + setColorScheme(colorScheme) { }, + setHue(hue) { }, +}); + +export { ThemeContextProvider, useTheme }; \ No newline at end of file diff --git a/src/features/theme/index.ts b/src/features/theme/index.ts new file mode 100644 index 0000000..561afbd --- /dev/null +++ b/src/features/theme/index.ts @@ -0,0 +1,4 @@ + + +export { ThemeContextProvider, useTheme } from './context'; +export { ColorSchemePicker } from './picker'; \ No newline at end of file diff --git a/src/features/theme/picker.module.css b/src/features/theme/picker.module.css new file mode 100644 index 0000000..66baa23 --- /dev/null +++ b/src/features/theme/picker.module.css @@ -0,0 +1,9 @@ +.picker { + grid-template-columns: auto 1fr; +} + +.hue { + display: flex; + flex-flow: row; + align-items: center; +} \ No newline at end of file diff --git a/src/features/theme/picker.tsx b/src/features/theme/picker.tsx new file mode 100644 index 0000000..0acce5a --- /dev/null +++ b/src/features/theme/picker.tsx @@ -0,0 +1,43 @@ +import { WiMoonAltFirstQuarter, WiMoonAltFull, WiMoonAltNew } from "solid-icons/wi"; +import { Component, createEffect, For, Match, on, Setter, Switch } from "solid-js"; +import { ColorScheme, useTheme } from "./context"; +import css from './picker.module.css'; +import { Select } from "~/components/select"; + +const colorSchemes: Record = Object.fromEntries(Object.entries(ColorScheme).map(([k, v]) => [v, k])) as any; + +export const ColorSchemePicker: Component = (props) => { + const themeContext = useTheme(); + + const setScheme: Setter = (next) => { + + if (typeof next === 'function') { + next = next(); + } + + themeContext.setColorScheme(next); + }; + + createEffect(on(() => themeContext.theme.colorScheme, (colorScheme) => { + console.log(colorScheme); + })); + + return <> + + + {/* */} + ; +}; \ No newline at end of file diff --git a/src/index.css b/src/index.css index 5d0ee5f..f972d71 100644 --- a/src/index.css +++ b/src/index.css @@ -1,17 +1,177 @@ @layer reset, base, tokens, recipes, utilities; -html { - display: grid; - grid: 100% / 100%; - inline-size: 100%; - block-size: 100%; - overflow: clip; +@import "open-props/style" layer(tokens); +@import "open-props/normalize" layer(reset); +@import "open-props/durations" layer(base); - & > body { +@import 'open-props/theme.light.switch.min.css' layer(tokens); +@import 'open-props/theme.dark.switch.min.css' layer(tokens); + +@layer base { + html { display: grid; grid: 100% / 100%; inline-size: 100%; block-size: 100%; - overflow-y: auto; + overflow: clip; + + /* font-size: clamp(1rem, -0.875rem + 8.333vw, 3.5rem); */ + + & > body { + display: grid; + grid: 100% / 100%; + inline-size: 100%; + block-size: 100%; + + margin: 0; + font-family: sans-serif; + + overflow: clip; + background-color: var(--surface-3); + color: var(--text-2); + accent-color: var(--primary-500); + + * { + box-sizing: border-box; + + &:focus-visible { + outline: 1px solid var(--info); + } + } + } } } + +@layer reset { + @property --sibling-index { + syntax: ''; + inherits: false; + initial-value: 1; + } + + @property --sibling-count { + syntax: ''; + inherits: false; + initial-value: 0; + } + + :nth-child(1) { + --sibling-index: 1; + } + + :nth-child(2) { + --sibling-index: 2; + } + + :nth-child(3) { + --sibling-index: 3; + } + + :nth-child(4) { + --sibling-index: 4; + } + + :nth-child(5) { + --sibling-index: 5; + } + + :nth-child(6) { + --sibling-index: 6; + } + + :nth-child(7) { + --sibling-index: 7; + } + + :nth-child(8) { + --sibling-index: 8; + } + + :nth-child(9) { + --sibling-index: 9; + } + + :nth-child(10) { + --sibling-index: 10; + } + + :nth-child(11) { + --sibling-index: 11; + } + + :nth-child(12) { + --sibling-index: 12; + } + + :nth-child(13) { + --sibling-index: 13; + } + + :nth-child(14) { + --sibling-index: 14; + } + + :nth-child(15) { + --sibling-index: 15; + } + + :has(> :last-child:nth-child(1)) { + --sibbling-count: 1; + } + + :has(> :last-child:nth-child(2)) { + --sibbling-count: 2; + } + + :has(> :last-child:nth-child(3)) { + --sibbling-count: 3; + } + + :has(> :last-child:nth-child(4)) { + --sibbling-count: 4; + } + + :has(> :last-child:nth-child(5)) { + --sibbling-count: 5; + } + + :has(> :last-child:nth-child(6)) { + --sibbling-count: 6; + } + + :has(> :last-child:nth-child(7)) { + --sibbling-count: 7; + } + + :has(> :last-child:nth-child(8)) { + --sibbling-count: 8; + } + + :has(> :last-child:nth-child(9)) { + --sibbling-count: 9; + } + + :has(> :last-child:nth-child(10)) { + --sibbling-count: 10; + } + + :has(> :last-child:nth-child(11)) { + --sibbling-count: 11; + } + + :has(> :last-child:nth-child(12)) { + --sibbling-count: 12; + } + + :has(> :last-child:nth-child(13)) { + --sibbling-count: 13; + } + + :has(> :last-child:nth-child(14)) { + --sibbling-count: 14; + } + + :has(> :last-child:nth-child(15)) { + --sibbling-count: 15; + } +} \ No newline at end of file diff --git a/src/routes/(shell).tsx b/src/routes/(shell).tsx index cd4c57b..9c2bc2b 100644 --- a/src/routes/(shell).tsx +++ b/src/routes/(shell).tsx @@ -1,7 +1,19 @@ -import { ParentProps } from "solid-js"; +import { Meta } from "@solidjs/meta"; +import { createEffect, on, ParentProps } from "solid-js"; import { Shell } from "~/features/shell"; +import { useTheme } from "~/features/theme"; export default function ShellPage(props: ParentProps) { - return {props.children}; + const themeContext = useTheme(); + + createEffect(on(() => themeContext.theme.colorScheme, (colorScheme) => { + document.documentElement.dataset.theme = colorScheme; + })); + + return + + + {props.children} + ; } diff --git a/src/routes/sitemap.xml.ts b/src/routes/sitemap.xml.ts new file mode 100644 index 0000000..4cdfeea --- /dev/null +++ b/src/routes/sitemap.xml.ts @@ -0,0 +1,36 @@ +import { SitemapStream, streamToPromise } from 'sitemap' +import { App } from 'vinxi'; + +const BASE_URL = 'https://ca-euw-prd-calque-app.purplecoast-f5b7f657.westeurope.azurecontainerapps.io'; + +export async function GET() { + + const sitemap = new SitemapStream({ hostname: BASE_URL }); + + sitemap.write({ url: BASE_URL, changefreq: 'monthly', }); + + for (const route of await getRoutes()) { + sitemap.write({ url: route, changefreq: 'monthly', }); + } + + sitemap.end(); + + return new Response( + (await streamToPromise(sitemap)).toString(), + { status: 200, headers: { 'Content-Type': 'text/xml' } } + ); +} + +const getRoutes = async () => { + const router = ((globalThis as any).app as App).getRouter('client').internals.routes; + + if (router === undefined) { + return []; + } + + const routes = await router.getRoutes() as { page: boolean, $$route?: object, path: string }[]; + + return routes + .filter(r => r.page === true && r.$$route === undefined && !r.path.match(/^.+\*\d+$/)) + .map(r => r.path.replace(/\/\(\w+\)/g, '')); +}; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index c3008fd..4b4fbe5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,6 @@ "types": [ "@solidjs/start/env", "@testing-library/jest-dom", - "@types/wicg-file-system-access", "vinxi/types/client", "vite-plugin-solid-svg/types-component-solid", "bun-types" @@ -26,8 +25,5 @@ ] }, "sourceMap": true - }, - "include": [ - "src" - ] + } } \ No newline at end of file