got started on new look. pivoting to api implementations now

This commit is contained in:
Chris Kruining 2025-04-01 14:17:20 +02:00
parent aa12f5443c
commit 17e769c598
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
29 changed files with 1080 additions and 136 deletions

13
.vscode/settings.json vendored Normal file
View file

@ -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"
]
}

View file

@ -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: '<custom-ident>',
body: 'style-block',
},
},
},
},
build: {
cssMinify: 'lightningcss',
},
plugins: [
devtools({
autoname: true,
}),
solidSvg(),
{
name: 'temp',
configResolved(config) {
console.log(config.resolve.alias);
},
},
],
},
solid: {

View file

@ -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=="],

View file

@ -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",

View file

@ -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 => (
<MetaProvider>
<Title>Streamarr - Home</Title>
<Suspense>{props.children}</Suspense>
<Suspense>
<ThemeContextProvider>{props.children}</ThemeContextProvider>
</Suspense>
</MetaProvider>
)}
>

View file

@ -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);
}
}

View file

@ -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<HTMLDialogElement>();
const [open, setOpen] = createSignal<boolean>(props.open ?? false);
createEffect(() => {
dialog()?.[open() ? 'showPopover' : 'hidePopover']();
});
createEffect(() => {
props.api?.({
show() {
dialog()?.showPopover();
},
hide() {
dialog()?.hidePopover();
},
});
});
return <section class={`${css.box} ${props.class}`}>
<button id={`${props.id}_button`} popoverTarget={`${props.id}_dialog`} class={css.button}>
{props.text}
<Show when={props.showCaret}>
<FaSolidAngleDown class={css.caret} />
</Show>
</button>
<dialog ref={setDialog} id={`${props.id}_dialog`} anchor={`${props.id}_button`} popover class={css.dialog} onToggle={e => setOpen(e.newState === 'open')}>
{props.children}
</dialog>
</section>;
}

View file

@ -0,0 +1,4 @@
export type { DropdownApi } from './dropdown';
export { Dropdown } from './dropdown';

View file

@ -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;
}

View file

@ -4,11 +4,13 @@ import css from "./hero.module.css";
type HeroProps = {
entry: Entry;
class?: string;
};
export function Hero(props: HeroProps) {
return (
<div class={css.container}>
<div class={`${css.container} ${props.class ?? ''}`}>
<h2 class={css.title}>{props.entry.title}</h2>
<img src={props.entry.thumbnail} class={css.thumbnail} />

View file

@ -13,15 +13,17 @@
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;
}

View file

@ -4,12 +4,13 @@ import css from "./list.module.css";
interface ListProps<T> {
label: string;
items: T[];
class?: string;
children: (item: Accessor<T>) => JSX.Element;
}
export function List<T>(props: ListProps<T>) {
return (
<section class={css.container}>
<section class={`${css.container} ${props.class ?? ''}`}>
<b role="heading" class={css.heading}>
{props.label}
</b>

View file

@ -0,0 +1,3 @@
export { Select } from './select';

View file

@ -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);
}
}

View file

@ -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<T, K extends string> {
id: string;
class?: string;
value: K;
setValue?: Setter<K>;
values: Record<K, T>;
open?: boolean;
showCaret?: boolean;
children: (key: K, value: T) => JSX.Element;
filter?: (query: string, key: K, value: T) => boolean;
}
export function Select<T, K extends string>(props: SelectProps<T, K>) {
const [dropdown, setDropdown] = createSignal<DropdownApi>();
const [key, setKey] = createSignal<K>(props.value);
const [query, setQuery] = createSignal<string>('');
const showCaret = createMemo(() => props.showCaret ?? true);
const values = createMemo(() => {
let entries = Object.entries<T>(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 = <Show when={key()}>{
key => {
const value = createMemo(() => props.values[key()]);
return <>{props.children(key(), value())}</>;
}
}</Show>
return <Dropdown api={setDropdown} id={props.id} class={`${css.box} ${props.class}`} showCaret={showCaret()} open={props.open} text={text}>
<Show when={props.filter !== undefined}>
<header>
<input value={query()} onInput={e => setQuery(e.target.value)} />
</header>
</Show>
<main>
<For each={values()}>{
([k, v]) => {
const selected = createMemo(() => key() === k);
return <span class={`${css.option} ${selected() ? css.selected : ''}`} onpointerdown={() => {
setKey(() => k);
dropdown()?.hide();
}}>{props.children(k, v)}</span>;
}
}</For>
</main>
</Dropdown>
}

View file

@ -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,21 +50,20 @@
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) {
@media (hover) {
&:not(:hover):not(:focus-within) {
transform: translateY(0);
z-index: 0;
@ -81,22 +80,25 @@
}
@media (prefers-reduced-motion: no-preference) {
transition: transform 0.2s linear;
& {
transition: transform var(--duration-moderate-1) linear;
}
& > img {
transition: transform 0.2s ease-in-out;
transition: transform var(--duration-moderate-1) ease-in-out;
}
& > main {
transition: clip-path 0.2s ease-in-out;
transition: clip-path var(--duration-moderate-1) ease-in-out;
}
&:is(:hover :focus-within) {
transition-delay: 0s 0.3s;
transition-delay: var(--duration-instant) var(--duration-moderate-2);
z-index: 1;
& > img {
transition: transform 0.2s ease-in-out;
transition: transform var(--duration-moderate-1) ease-in-out;
}
}
}
}

View file

@ -4,10 +4,12 @@ import css from "./list-item.module.css";
export const ListItem: Component<{ entry: Entry }> = (props) => {
return (
<div class={css.tile}>
<div class={css.listItem}>
<img src={props.entry.thumbnail} />
<main>
<strong>{props.entry.title}</strong>
<a href={`/content/${props.entry.id}`}>Lets go!</a>
</main>
</div>

View file

@ -2,4 +2,13 @@
display: grid;
grid-auto-flow: row;
gap: 2em;
border-radius: inherit;
& > .hero {
border-radius: inherit;
}
& > .list {
padding-inline: 2em;
}
}

View file

@ -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<OverviewProps> = (props) => {
const [container, setContainer] = createSignal<HTMLElement>();
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 (
<div class={css.container}>
<Hero entry={props.highlight}></Hero>
<div ref={setContainer} class={css.container}>
<Hero class={css.hero} entry={props.highlight}></Hero>
<Index each={props.categories}>
{(category) => (
<List label={category().label} items={category().entries}>
<List class={css.list} label={category().label} items={category().entries}>
{(entry) => <ListItem entry={entry()} />}
</List>
)}

View file

@ -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: 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);
& > div {
border-top-left-radius: var(--radius-4);
background-color: var(--surface-2);
isolation: isolate;
inline-size: 100%;
block-size: fit-content;
padding-inline: 2em;
padding-block-end: 5em;
background: linear-gradient(180deg, transparent, transparent 90vh, #333 90vh, #333);
@container (inline-size >=600px) {
padding-inline-start: 7.5em;
min-block-size: 100%;
}
}
.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: 1 / 1;
display: none;
grid-area: nav;
display: block grid;
grid-auto-flow: row;
align-content: start;
justify-content: space-between;
inline-size: 7.5em;
block-size: 100%;
padding: 1em;
position: sticky;
inset-block-start: 0;
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;
}
}

View file

@ -6,20 +6,33 @@ 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 (
<main class={css.container}>
<Top />
<Nav />
<div class={css.body}>{props.children}</div>
<div class={css.body}>
<div>{props.children}</div>
</div>
</main>
);
};
const Top: Component = (props) => {
return (
<aside class={css.top}>
<ColorSchemePicker />
</aside>
);
};
const Nav: Component = (props) => {
return (
<nav class={css.nav}>
<ul>
<A href="/">
<FaSolidHouseChimney />
Home
@ -32,6 +45,7 @@ const Nav: Component = (props) => {
<FaSolidMagnifyingGlass />
Search
</A>
</ul>
</nav>
);
};

View file

@ -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<State>({
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<ThemeContextType, ContextProviderProps>((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 };

View file

@ -0,0 +1,4 @@
export { ThemeContextProvider, useTheme } from './context';
export { ColorSchemePicker } from './picker';

View file

@ -0,0 +1,9 @@
.picker {
grid-template-columns: auto 1fr;
}
.hue {
display: flex;
flex-flow: row;
align-items: center;
}

View file

@ -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<ColorScheme, keyof typeof ColorScheme> = Object.fromEntries(Object.entries(ColorScheme).map(([k, v]) => [v, k])) as any;
export const ColorSchemePicker: Component = (props) => {
const themeContext = useTheme();
const setScheme: Setter<ColorScheme> = (next) => {
if (typeof next === 'function') {
next = next();
}
themeContext.setColorScheme(next);
};
createEffect(on(() => themeContext.theme.colorScheme, (colorScheme) => {
console.log(colorScheme);
}));
return <>
<label aria-label="Color scheme picker">
<Select id="color-scheme-picker" class={css.picker} value={themeContext.theme.colorScheme} setValue={setScheme} values={colorSchemes}>{
(k, v) => <>
<Switch>
<Match when={k === ColorScheme.Auto}><WiMoonAltFirstQuarter /></Match>
<Match when={k === ColorScheme.Light}><WiMoonAltNew /></Match>
<Match when={k === ColorScheme.Dark}><WiMoonAltFull /></Match>
</Switch>
{v}
</>
}</Select>
</label>
{/* <label class={css.hue} aria-label="Hue slider">
<input type="range" min="0" max="360" value={theme.hue} onInput={e => setHue(e.target.valueAsNumber)} />
</label> */}
</>;
};

View file

@ -1,17 +1,177 @@
@layer reset, base, tokens, recipes, utilities;
html {
@import "open-props/style" layer(tokens);
@import "open-props/normalize" layer(reset);
@import "open-props/durations" layer(base);
@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: clip;
/* font-size: clamp(1rem, -0.875rem + 8.333vw, 3.5rem); */
& > body {
display: grid;
grid: 100% / 100%;
inline-size: 100%;
block-size: 100%;
overflow-y: auto;
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: '<integer>';
inherits: false;
initial-value: 1;
}
@property --sibling-count {
syntax: '<integer>';
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;
}
}

View file

@ -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 <Shell>{props.children}</Shell>;
const themeContext = useTheme();
createEffect(on(() => themeContext.theme.colorScheme, (colorScheme) => {
document.documentElement.dataset.theme = colorScheme;
}));
return <Shell>
<Meta name="color-scheme" content={themeContext.theme.colorScheme} />
{props.children}
</Shell>;
}

36
src/routes/sitemap.xml.ts Normal file
View file

@ -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, ''));
};

View file

@ -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"
]
}
}