From d0479d72ef448b2000d9ea158a82d67a51bf3ecd Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Sun, 24 Mar 2024 21:31:32 -0500 Subject: [PATCH 01/17] Green: Remove sass in favor of tailwind (shadecn dep) --- package-lock.json | 821 +++++++++++++++++- package.json | 4 +- postcss.config.js | 7 + src/components/entry/EntryForm.svelte | 2 +- src/components/purchases/PastPurchase.svelte | 4 +- .../purchases/PastPurchasesList.svelte | 2 +- src/{global.scss => global.css} | 4 + src/routes/+page.svelte | 4 +- tailwind.config.js | 8 + 9 files changed, 847 insertions(+), 9 deletions(-) create mode 100644 postcss.config.js rename src/{global.scss => global.css} (75%) create mode 100644 tailwind.config.js diff --git a/package-lock.json b/package-lock.json index 180667d..6568bc0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,15 +24,17 @@ "@sveltejs/kit": "^1.20.4", "@typescript-eslint/eslint-plugin": "^7.3.1", "@typescript-eslint/parser": "^7.3.1", + "autoprefixer": "^10.4.19", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.35.1", + "postcss": "^8.4.38", "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.2", - "sass": "^1.63.6", "svelte": "^4.0.0", "svelte-check": "^3.4.3", "svelte-forms-lib": "^2.0.1", + "tailwindcss": "^3.4.1", "tslib": "^2.4.1", "typescript": "^5.0.0", "vite": "^4.3.6" @@ -47,6 +49,18 @@ "node": ">=0.10.0" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1232,6 +1246,102 @@ "node": ">=16.0.0" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -1315,6 +1425,16 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@playwright/test": { "version": "1.42.1", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz", @@ -1825,6 +1945,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -1838,6 +1964,12 @@ "node": ">= 8" } }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1878,6 +2010,43 @@ "node": ">= 4.0.0" } }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/axobject-query": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", @@ -1964,6 +2133,38 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -1981,6 +2182,35 @@ "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2216,6 +2446,12 @@ "integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==", "dev": true }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2228,6 +2464,12 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2240,6 +2482,18 @@ "node": ">=6.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.715", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz", + "integrity": "sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg==", + "dev": true + }, "node_modules/elementtree": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz", @@ -2763,6 +3017,47 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -2818,6 +3113,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2944,6 +3248,18 @@ "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -2967,7 +3283,9 @@ "version": "4.3.5", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -3039,6 +3357,18 @@ "node": ">=8" } }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -3125,6 +3455,33 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3211,6 +3568,12 @@ "node": ">=10" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", @@ -3392,6 +3755,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -3440,6 +3814,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3449,6 +3829,33 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3559,6 +3966,12 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "node_modules/path-scurry": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", @@ -3625,6 +4038,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/playwright": { "version": "1.42.1", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", @@ -3696,6 +4127,42 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, "node_modules/postcss-load-config": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", @@ -3725,6 +4192,25 @@ } } }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, "node_modules/postcss-safe-parser": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", @@ -3780,6 +4266,12 @@ "node": ">=4" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3886,6 +4378,15 @@ } ] }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -3919,6 +4420,23 @@ "node": ">=0.10.0" } }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -4074,6 +4592,8 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.72.0.tgz", "integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -4252,6 +4772,21 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4263,6 +4798,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -4287,6 +4835,92 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4299,6 +4933,18 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/svelecte": { "version": "3.17.3", "resolved": "https://registry.npmjs.org/svelecte/-/svelecte-3.17.3.tgz", @@ -4495,6 +5141,102 @@ "resolved": "https://registry.npmjs.org/svelte-tiny-virtual-list/-/svelte-tiny-virtual-list-2.0.5.tgz", "integrity": "sha512-xg9ckb8UeeIme4/5qlwCrl2QNmUZ8SCQYZn3Ji83cUsoASqRNy3KWjpmNmzYvPDqCHSZjruBBsoB7t5hwuzw5g==" }, + "node_modules/tailwindcss": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.19.1", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/tailwindcss/node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -4536,6 +5278,27 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/through2": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", @@ -4595,6 +5358,12 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -4669,6 +5438,36 @@ "node": ">=8" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4803,6 +5602,24 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 9b1a6f8..f556428 100644 --- a/package.json +++ b/package.json @@ -30,15 +30,17 @@ "@sveltejs/kit": "^1.20.4", "@typescript-eslint/eslint-plugin": "^7.3.1", "@typescript-eslint/parser": "^7.3.1", + "autoprefixer": "^10.4.19", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.35.1", + "postcss": "^8.4.38", "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.2", - "sass": "^1.63.6", "svelte": "^4.0.0", "svelte-check": "^3.4.3", "svelte-forms-lib": "^2.0.1", + "tailwindcss": "^3.4.1", "tslib": "^2.4.1", "typescript": "^5.0.0", "vite": "^4.3.6" diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..f780382 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,7 @@ +export default { + plugins: { + "tailwindcss/nesting": {}, + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/src/components/entry/EntryForm.svelte b/src/components/entry/EntryForm.svelte index c0dd44f..24c9bfd 100644 --- a/src/components/entry/EntryForm.svelte +++ b/src/components/entry/EntryForm.svelte @@ -137,7 +137,7 @@ - diff --git a/src/components/purchases/PastPurchasesList.svelte b/src/components/purchases/PastPurchasesList.svelte index dc42d04..bde3b7c 100644 --- a/src/components/purchases/PastPurchasesList.svelte +++ b/src/components/purchases/PastPurchasesList.svelte @@ -25,7 +25,7 @@ {/if} - diff --git a/src/components/ui/button/button.svelte b/src/components/ui/button/button.svelte new file mode 100644 index 0000000..0634d48 --- /dev/null +++ b/src/components/ui/button/button.svelte @@ -0,0 +1,25 @@ + + + + + diff --git a/src/components/ui/button/index.ts b/src/components/ui/button/index.ts new file mode 100644 index 0000000..cfb5560 --- /dev/null +++ b/src/components/ui/button/index.ts @@ -0,0 +1,49 @@ +import Root from "./button.svelte"; +import { tv, type VariantProps } from "tailwind-variants"; +import type { Button as ButtonPrimitive } from "bits-ui"; + +const buttonVariants = tv({ + base: "inline-flex items-center justify-center rounded-md text-sm font-medium whitespace-nowrap ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, +}); + +type Variant = VariantProps["variant"]; +type Size = VariantProps["size"]; + +type Props = ButtonPrimitive.Props & { + variant?: Variant; + size?: Size; +}; + +type Events = ButtonPrimitive.Events; + +export { + Root, + type Props, + type Events, + // + Root as Button, + type Props as ButtonProps, + type Events as ButtonEvents, + buttonVariants, +}; diff --git a/src/global.css b/src/global.css deleted file mode 100644 index f489baa..0000000 --- a/src/global.css +++ /dev/null @@ -1,17 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -.center { - justify-content: center; -} -.space-between { - justify-content: space-between; -} -.row-item { - display: flex; - margin-bottom: 1em; - label { - margin-right: 1em; - } -} \ No newline at end of file diff --git a/src/global.pcss b/src/global.pcss new file mode 100644 index 0000000..6ff7062 --- /dev/null +++ b/src/global.pcss @@ -0,0 +1,78 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 72.2% 50.6%; + --destructive-foreground: 210 40% 98%; + + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --ring: hsl(212.7,26.8%,83.9); + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..230a1fb --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,62 @@ +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; +import { cubicOut } from "svelte/easing"; +import type { TransitionConfig } from "svelte/transition"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +type FlyAndScaleParams = { + y?: number; + x?: number; + start?: number; + duration?: number; +}; + +export const flyAndScale = ( + node: Element, + params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 } +): TransitionConfig => { + const style = getComputedStyle(node); + const transform = style.transform === "none" ? "" : style.transform; + + const scaleConversion = ( + valueA: number, + scaleA: [number, number], + scaleB: [number, number] + ) => { + const [minA, maxA] = scaleA; + const [minB, maxB] = scaleB; + + const percentage = (valueA - minA) / (maxA - minA); + const valueB = percentage * (maxB - minB) + minB; + + return valueB; + }; + + const styleToString = ( + style: Record + ): string => { + return Object.keys(style).reduce((str, key) => { + if (style[key] === undefined) return str; + return str + `${key}:${style[key]};`; + }, ""); + }; + + return { + duration: params.duration ?? 200, + delay: 0, + css: (t) => { + const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]); + const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]); + const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]); + + return styleToString({ + transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`, + opacity: t + }); + }, + easing: cubicOut + }; +}; \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 4211f61..57796f7 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,10 +1,10 @@
diff --git a/svelte.config.js b/svelte.config.js index 9e370fe..fedd5d4 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -27,7 +27,7 @@ const config = { strict: true, }), alias: { - "@/*": "./src/lib", + $components: "src/components", }, }, }; diff --git a/tailwind.config.js b/tailwind.config.js index 03114c6..8d260d9 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,8 +1,64 @@ +import { fontFamily } from "tailwindcss/defaultTheme"; + /** @type {import('tailwindcss').Config} */ -export default { - content: ["./src/**/*.{html,js,svelte,ts}"], - theme: { - extend: {}, - }, - plugins: [], +const config = { + darkMode: ["class"], + content: ["./src/**/*.{html,js,svelte,ts}"], + safelist: ["dark"], + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px" + } + }, + extend: { + colors: { + border: "hsl(var(--border) / )", + input: "hsl(var(--input) / )", + ring: "hsl(var(--ring) / )", + background: "hsl(var(--background) / )", + foreground: "hsl(var(--foreground) / )", + primary: { + DEFAULT: "hsl(var(--primary) / )", + foreground: "hsl(var(--primary-foreground) / )" + }, + secondary: { + DEFAULT: "hsl(var(--secondary) / )", + foreground: "hsl(var(--secondary-foreground) / )" + }, + destructive: { + DEFAULT: "hsl(var(--destructive) / )", + foreground: "hsl(var(--destructive-foreground) / )" + }, + muted: { + DEFAULT: "hsl(var(--muted) / )", + foreground: "hsl(var(--muted-foreground) / )" + }, + accent: { + DEFAULT: "hsl(var(--accent) / )", + foreground: "hsl(var(--accent-foreground) / )" + }, + popover: { + DEFAULT: "hsl(var(--popover) / )", + foreground: "hsl(var(--popover-foreground) / )" + }, + card: { + DEFAULT: "hsl(var(--card) / )", + foreground: "hsl(var(--card-foreground) / )" + } + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)" + }, + fontFamily: { + sans: [...fontFamily.sans] + } + } + }, }; + +export default config; From 9508110ba106103d73379ab776acbc2bf2d7bac7 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Sat, 30 Mar 2024 15:53:39 -0500 Subject: [PATCH 04/17] WIP: Amount starting to look good: todo: switch to grid to show errors --- package-lock.json | 482 +++++++++++++++--- package.json | 5 +- src/components/entry/NewEntryForm.svelte | 92 ++++ src/components/entry/formSchema.ts | 21 + src/components/ui/form/form-button.svelte | 10 + .../ui/form/form-description.svelte | 17 + .../ui/form/form-element-field.svelte | 26 + .../ui/form/form-field-errors.svelte | 26 + src/components/ui/form/form-field.svelte | 26 + src/components/ui/form/form-fieldset.svelte | 31 ++ src/components/ui/form/form-label.svelte | 17 + src/components/ui/form/form-legend.svelte | 17 + src/components/ui/form/index.ts | 33 ++ src/components/ui/input/index.ts | 27 + src/components/ui/input/input.svelte | 35 ++ src/components/ui/label/index.ts | 7 + src/components/ui/label/label.svelte | 21 + src/lib/Debug.ts | 4 +- src/routes/+page.svelte | 10 +- src/routes/+page.ts | 12 + tsconfig.json | 31 +- 21 files changed, 872 insertions(+), 78 deletions(-) create mode 100644 src/components/entry/NewEntryForm.svelte create mode 100644 src/components/entry/formSchema.ts create mode 100644 src/components/ui/form/form-button.svelte create mode 100644 src/components/ui/form/form-description.svelte create mode 100644 src/components/ui/form/form-element-field.svelte create mode 100644 src/components/ui/form/form-field-errors.svelte create mode 100644 src/components/ui/form/form-field.svelte create mode 100644 src/components/ui/form/form-fieldset.svelte create mode 100644 src/components/ui/form/form-label.svelte create mode 100644 src/components/ui/form/form-legend.svelte create mode 100644 src/components/ui/form/index.ts create mode 100644 src/components/ui/input/index.ts create mode 100644 src/components/ui/input/input.svelte create mode 100644 src/components/ui/label/index.ts create mode 100644 src/components/ui/label/label.svelte create mode 100644 src/routes/+page.ts diff --git a/package-lock.json b/package-lock.json index 082b00d..cb47409 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,9 +17,12 @@ "clsx": "^2.1.0", "date-fns": "^3.3.1", "firebase": "^10.1.0", + "formsnap": "^1.0.0", "svelecte": "^3.17.2", + "sveltekit-superforms": "^2.11.0", "tailwind-merge": "^2.2.2", - "tailwind-variants": "^0.2.1" + "tailwind-variants": "^0.2.1", + "zod": "^3.22.4" }, "devDependencies": { "@playwright/test": "^1.37.0", @@ -149,7 +152,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -165,7 +167,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -181,7 +182,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "android" @@ -197,7 +197,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -213,7 +212,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -229,7 +227,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -245,7 +242,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -261,7 +257,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -277,7 +272,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -293,7 +287,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "linux" @@ -309,7 +302,6 @@ "cpu": [ "loong64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -325,7 +317,6 @@ "cpu": [ "mips64el" ], - "dev": true, "optional": true, "os": [ "linux" @@ -341,7 +332,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -357,7 +347,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -373,7 +362,6 @@ "cpu": [ "s390x" ], - "dev": true, "optional": true, "os": [ "linux" @@ -389,7 +377,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -405,7 +392,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "netbsd" @@ -421,7 +407,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "openbsd" @@ -437,7 +422,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "sunos" @@ -453,7 +437,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -469,7 +452,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -485,7 +467,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1065,6 +1046,21 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, + "node_modules/@gcornut/valibot-json-schema": { + "version": "0.0.26", + "resolved": "https://registry.npmjs.org/@gcornut/valibot-json-schema/-/valibot-json-schema-0.0.26.tgz", + "integrity": "sha512-8eZpGLP1awX9UGEK+VUFiyXnjiIV/h5RPC7wt2KQG6O7YkXEw7t2pUxHhR5ULcoN0BsZ3FOWZqyzu3tFF7aXxw==", + "optional": true, + "bin": { + "valibot-json-schema": "bin/index.js" + }, + "peerDependencies": { + "@types/json-schema": ">= 7.0.14", + "esbuild": ">= 0.18.20", + "esbuild-runner": ">= 2.2.2", + "valibot": ">= 0.21.0" + } + }, "node_modules/@grpc/grpc-js": { "version": "1.9.14", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz", @@ -1094,6 +1090,21 @@ "node": ">=6" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "optional": true + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "optional": true, + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -1513,8 +1524,16 @@ "node_modules/@polka/url": { "version": "1.0.0-next.25", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", - "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", - "dev": true + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" + }, + "node_modules/@poppinss/macroable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@poppinss/macroable/-/macroable-1.0.1.tgz", + "integrity": "sha512-bO3+rnqGhE+gdx4DOyYjY9jCm2+c5Ncyl2Gmst0w271rIFnsB00btonpdmAqvFNzS8rcas+APGm+47fYMmkpQA==", + "optional": true, + "engines": { + "node": ">=18.16.0" + } }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", @@ -1570,6 +1589,39 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "optional": true, + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "optional": true + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "optional": true + }, + "node_modules/@sinclair/typebox": { + "version": "0.32.20", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.32.20.tgz", + "integrity": "sha512-ziK497ILSIYMxD/thl496idIb03IZPlha04itLQu1xAFQbumWZ+Dj4PMMCkDRpAYhvVSdmRlTjGu2B2MA5RplQ==", + "optional": true + }, + "node_modules/@sodaru/yup-to-json-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@sodaru/yup-to-json-schema/-/yup-to-json-schema-2.0.1.tgz", + "integrity": "sha512-lWb0Wiz8KZ9ip/dY1eUqt7fhTPmL24p6Hmv5Fd9pzlzAdw/YNcWZr+tiCT4oZ4Zyxzi9+1X4zv82o7jYvcFxYA==", + "optional": true + }, "node_modules/@svelte-put/clickoutside": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@svelte-put/clickoutside/-/clickoutside-3.0.1.tgz", @@ -1600,7 +1652,6 @@ "version": "1.30.4", "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.30.4.tgz", "integrity": "sha512-JSQIQT6XvdchCRQEm7BABxPC56WP5RYVONAi+09S8tmzeP43fBsRlr95bFmsTQM2RHBldfgQk+jgdnsKI75daA==", - "dev": true, "hasInstallScript": true, "dependencies": { "@sveltejs/vite-plugin-svelte": "^2.5.0", @@ -1632,7 +1683,6 @@ "version": "2.5.3", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.5.3.tgz", "integrity": "sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w==", - "dev": true, "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^1.0.4", "debug": "^4.3.4", @@ -1654,7 +1704,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-1.0.4.tgz", "integrity": "sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -1678,8 +1727,7 @@ "node_modules/@types/cookie": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.4.tgz", - "integrity": "sha512-7z/eR6O859gyWIAjuvBWFzNURmf2oPBmJlfVWkwehU5nzIyjwBsTh7WMmEEV4JFnHuQ3ex4oyTvfKzcyJVDBNA==", - "dev": true + "integrity": "sha512-7z/eR6O859gyWIAjuvBWFzNURmf2oPBmJlfVWkwehU5nzIyjwBsTh7WMmEEV4JFnHuQ3ex4oyTvfKzcyJVDBNA==" }, "node_modules/@types/estree": { "version": "1.0.5", @@ -1698,7 +1746,7 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "devOptional": true }, "node_modules/@types/node": { "version": "20.11.30", @@ -1725,6 +1773,12 @@ "resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ==" }, + "node_modules/@types/validator": { + "version": "13.11.9", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", + "integrity": "sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==", + "optional": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz", @@ -1945,6 +1999,34 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vinejs/compiler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@vinejs/compiler/-/compiler-2.4.1.tgz", + "integrity": "sha512-WZqCZEQBvuPEghAxnpvNLclyyfqkmU+2V2K4zoZhOUJRD9KRJ+hCNQQ6LSzt7ZwSh+wwxq0r9FpAfeC3tswB8Q==", + "optional": true, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@vinejs/vine": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@vinejs/vine/-/vine-1.8.0.tgz", + "integrity": "sha512-Qq3XxbA26jzqS9ICifkqzT399lMQZ2fWtqeV3luI2as+UIK7qDifJFU2Q4W3q3IB5VXoWxgwAZSZEO0em9I/qQ==", + "optional": true, + "dependencies": { + "@poppinss/macroable": "^1.0.1", + "@types/validator": "^13.11.9", + "@vinejs/compiler": "^2.4.1", + "camelcase": "^8.0.0", + "dayjs": "^1.11.10", + "dlv": "^1.1.3", + "normalize-url": "^8.0.1", + "validator": "^13.11.0" + }, + "engines": { + "node": ">=18.16.0" + } + }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", @@ -2047,6 +2129,12 @@ "dequal": "^2.0.3" } }, + "node_modules/arktype": { + "version": "1.0.29-alpha", + "resolved": "https://registry.npmjs.org/arktype/-/arktype-1.0.29-alpha.tgz", + "integrity": "sha512-glMLgVhIQRSkR3tymiS+POAcWVJH09sfrgic0jHnyFL8BlhHAJZX2BzdImU9zYr1y9NBqy+U93ZNrRTHXsKRDw==", + "optional": true + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -2262,6 +2350,13 @@ "node": "*" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "optional": true, + "peer": true + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2271,6 +2366,18 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "optional": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -2424,7 +2531,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -2474,6 +2580,12 @@ "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "optional": true + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2500,7 +2612,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -2533,8 +2644,7 @@ "node_modules/devalue": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.3.2.tgz", - "integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==", - "dev": true + "integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==" }, "node_modules/didyoumean": { "version": "1.2.2", @@ -2615,7 +2725,6 @@ "version": "0.18.20", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -2648,6 +2757,30 @@ "@esbuild/win32-x64": "0.18.20" } }, + "node_modules/esbuild-runner": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/esbuild-runner/-/esbuild-runner-2.2.2.tgz", + "integrity": "sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==", + "optional": true, + "peer": true, + "dependencies": { + "source-map-support": "0.5.21", + "tslib": "2.4.0" + }, + "bin": { + "esr": "bin/esr.js" + }, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/esbuild-runner/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "optional": true, + "peer": true + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -2822,8 +2955,7 @@ "node_modules/esm-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz", - "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==", - "dev": true + "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==" }, "node_modules/espree": { "version": "9.6.1", @@ -3133,6 +3265,35 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/formsnap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/formsnap/-/formsnap-1.0.0.tgz", + "integrity": "sha512-NQEbkCS1tKGnn6gBojIuNutxImmq/9bUk9JQ5kW8WOY37QNFtJxYr/SbX8ONWuiVLaczSvGSWXIv3hNu19arqQ==", + "dependencies": { + "nanoid": "^5.0.5" + }, + "peerDependencies": { + "svelte": "^4.0.0", + "sveltekit-superforms": "^2.3.0" + } + }, + "node_modules/formsnap/node_modules/nanoid": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.6.tgz", + "integrity": "sha512-rRq0eMHoGZxlvaFOUdK1Ev83Bd1IgzzR+WJ3IbDJ7QOSdAxYjlurSPqFs9s4lJg29RT6nPwizFtJhQS6V5xgiA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -3284,8 +3445,7 @@ "node_modules/globalyzer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "dev": true + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==" }, "node_modules/globby": { "version": "11.1.0", @@ -3310,8 +3470,7 @@ "node_modules/globrex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" }, "node_modules/graceful-fs": { "version": "4.2.11", @@ -3367,7 +3526,6 @@ "version": "4.3.5", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", - "dev": true, "optional": true, "peer": true }, @@ -3558,6 +3716,19 @@ "jiti": "bin/jiti.js" } }, + "node_modules/joi": { + "version": "17.12.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.2.tgz", + "integrity": "sha512-RonXAIzCiHLc8ss3Ibuz45u28GOsWE1UpfDXLbN/9NKbL4tCJf8TWYVKsoYuuh+sAUt7fsSNpA+r2+TBA6Wjmw==", + "optional": true, + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3599,6 +3770,11 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/just-clone": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-6.2.0.tgz", + "integrity": "sha512-1IynUYEc/HAwxhi3WDpIpxJbZpMCvvrrmZVqvj9EhpvbH8lls7HhdhiByjL7DkAaWlLIzpC0Xc/VPvy/UxLNjA==" + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3708,6 +3884,11 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, + "node_modules/memoize-weak": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/memoize-weak/-/memoize-weak-1.0.2.tgz", + "integrity": "sha512-gj39xkrjEw7nCn4nJ1M5ms6+MyMlyiGmttzsqAUsAKn6bYKwuTHh/AO3cKPF8IBrTIYTxb0wWXFs3E//Y8VoWQ==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3805,7 +3986,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, "engines": { "node": ">=4" } @@ -3814,7 +3994,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", - "dev": true, "engines": { "node": ">=10" } @@ -3904,6 +4083,18 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "optional": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4378,6 +4569,12 @@ "node": ">=6" } }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "optional": true + }, "node_modules/protobufjs": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", @@ -4529,7 +4726,6 @@ "version": "3.29.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "dev": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -4567,7 +4763,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, "dependencies": { "mri": "^1.1.0" }, @@ -4642,7 +4837,6 @@ "version": "1.72.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.72.0.tgz", "integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==", - "dev": true, "optional": true, "peer": true, "dependencies": { @@ -4690,8 +4884,7 @@ "node_modules/set-cookie-parser": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", - "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", - "dev": true + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -4721,7 +4914,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", - "dev": true, "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", @@ -4735,7 +4927,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", - "dev": true, "engines": { "node": ">=10" } @@ -4785,6 +4976,16 @@ "sorcery": "bin/sorcery" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -4793,6 +4994,17 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "optional": true, + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -4963,6 +5175,15 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/superstruct": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5105,7 +5326,6 @@ "version": "0.15.3", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz", "integrity": "sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==", - "dev": true, "engines": { "node": "^12.20 || ^14.13.1 || >= 16" }, @@ -5181,6 +5401,82 @@ "resolved": "https://registry.npmjs.org/svelte-tiny-virtual-list/-/svelte-tiny-virtual-list-2.0.5.tgz", "integrity": "sha512-xg9ckb8UeeIme4/5qlwCrl2QNmUZ8SCQYZn3Ji83cUsoASqRNy3KWjpmNmzYvPDqCHSZjruBBsoB7t5hwuzw5g==" }, + "node_modules/sveltekit-superforms": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/sveltekit-superforms/-/sveltekit-superforms-2.11.0.tgz", + "integrity": "sha512-wRAznfYi9sOp4aQd2kb/SIafqHX4LROn5ojIXEbp2Pss9EPy69tmArQFm3JaiBC0hU72bAlUOTFSmVABTF9TEA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ciscoheat" + }, + { + "type": "ko-fi", + "url": "https://ko-fi.com/ciscoheat" + }, + { + "type": "paypal", + "url": "https://www.paypal.com/donate/?hosted_button_id=NY7F5ALHHSVQS" + } + ], + "dependencies": { + "devalue": "^4.3.2", + "just-clone": "^6.2.0", + "memoize-weak": "^1.0.2", + "ts-deepmerge": "^7.0.0" + }, + "optionalDependencies": { + "@gcornut/valibot-json-schema": "^0.0.26", + "@sinclair/typebox": "^0.32.15", + "@sodaru/yup-to-json-schema": "^2.0.1", + "@vinejs/vine": "^1.8.0", + "arktype": "1.0.29-alpha", + "joi": "^17.12.2", + "superstruct": "^1.0.4", + "valibot": "^0.30.0", + "yup": "^1.4.0", + "zod": "^3.22.4", + "zod-to-json-schema": "^3.22.4" + }, + "peerDependencies": { + "@sinclair/typebox": ">=0.32.13 <1", + "@sveltejs/kit": "1.x || 2.x", + "@vinejs/vine": "^1.7.1", + "arktype": "1.0.29-alpha", + "joi": "^17.12.1", + "superstruct": "^1.0.3", + "svelte": "3.x || 4.x || >=5.0.0-next.51", + "valibot": ">=0.28.1 <1", + "yup": "^1.3.3", + "zod": "^3.22.4" + }, + "peerDependenciesMeta": { + "@sinclair/typebox": { + "optional": true + }, + "@vinejs/vine": { + "optional": true + }, + "arktype": { + "optional": true + }, + "joi": { + "optional": true + }, + "superstruct": { + "optional": true + }, + "valibot": { + "optional": true + }, + "yup": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", @@ -5373,11 +5669,16 @@ "readable-stream": "3" } }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "optional": true + }, "node_modules/tiny-glob": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "dev": true, "dependencies": { "globalyzer": "0.1.0", "globrex": "^0.1.2" @@ -5394,11 +5695,16 @@ "node": ">=8.0" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "optional": true + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, "engines": { "node": ">=6" } @@ -5423,6 +5729,14 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-deepmerge": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ts-deepmerge/-/ts-deepmerge-7.0.0.tgz", + "integrity": "sha512-WZ/iAJrKDhdINv1WG6KZIGHrZDar6VfhftG1QJFpVbOYZMYJLJOvZOo1amictRXVdBXZIgBHKswMTXzElngprA==", + "engines": { + "node": ">=14.13.1" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -5546,11 +5860,25 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/valibot": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.30.0.tgz", + "integrity": "sha512-5POBdbSkM+3nvJ6ZlyQHsggisfRtyT4tVTo1EIIShs6qCdXJnyWU5TJ68vr8iTg5zpOLjXLRiBqNx+9zwZz/rA==", + "optional": true + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "optional": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vite": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", - "dev": true, "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", @@ -5605,7 +5933,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz", "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==", - "dev": true, "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" }, @@ -5784,6 +6111,47 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yup": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", + "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", + "optional": true, + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "optional": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.22.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.22.5.tgz", + "integrity": "sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==", + "optional": true, + "peerDependencies": { + "zod": "^3.22.4" + } } } } diff --git a/package.json b/package.json index 927c347..f6046f3 100644 --- a/package.json +++ b/package.json @@ -56,8 +56,11 @@ "clsx": "^2.1.0", "date-fns": "^3.3.1", "firebase": "^10.1.0", + "formsnap": "^1.0.0", "svelecte": "^3.17.2", + "sveltekit-superforms": "^2.11.0", "tailwind-merge": "^2.2.2", - "tailwind-variants": "^0.2.1" + "tailwind-variants": "^0.2.1", + "zod": "^3.22.4" } } diff --git a/src/components/entry/NewEntryForm.svelte b/src/components/entry/NewEntryForm.svelte new file mode 100644 index 0000000..5fa669f --- /dev/null +++ b/src/components/entry/NewEntryForm.svelte @@ -0,0 +1,92 @@ + + + + + + + + + + + +
+ + +
+ Amount +
+
+ + +
+ +
+
+
+ + + + + +
+ Submit + Reset +
+
diff --git a/src/components/entry/formSchema.ts b/src/components/entry/formSchema.ts new file mode 100644 index 0000000..05fbd48 --- /dev/null +++ b/src/components/entry/formSchema.ts @@ -0,0 +1,21 @@ +import { z } from "zod"; +import { initialDatetimeString } from "$lib/utils/DateUtils"; + +// refactor: rename this file + +export const initialFormValues = () => ({ + amount: 0, + // category: "", + // purchaseDatetime: initialDatetimeString(), + // description: "", +}); + +export const formSchema = z.object({ + amount: z.number().nonnegative(), + // category: z.string(), + // purchaseDatetime: z.string(), + // description: z.string(), +}); +// .required(); + +export type FormSchema = ReturnType; diff --git a/src/components/ui/form/form-button.svelte b/src/components/ui/form/form-button.svelte new file mode 100644 index 0000000..6773ec7 --- /dev/null +++ b/src/components/ui/form/form-button.svelte @@ -0,0 +1,10 @@ + + + + + diff --git a/src/components/ui/form/form-description.svelte b/src/components/ui/form/form-description.svelte new file mode 100644 index 0000000..20fa79d --- /dev/null +++ b/src/components/ui/form/form-description.svelte @@ -0,0 +1,17 @@ + + + + + diff --git a/src/components/ui/form/form-element-field.svelte b/src/components/ui/form/form-element-field.svelte new file mode 100644 index 0000000..eece7e1 --- /dev/null +++ b/src/components/ui/form/form-element-field.svelte @@ -0,0 +1,26 @@ + + + + + +
+ +
+
diff --git a/src/components/ui/form/form-field-errors.svelte b/src/components/ui/form/form-field-errors.svelte new file mode 100644 index 0000000..9395326 --- /dev/null +++ b/src/components/ui/form/form-field-errors.svelte @@ -0,0 +1,26 @@ + + + + + {#each errors as error} +
{error}
+ {/each} +
+
diff --git a/src/components/ui/form/form-field.svelte b/src/components/ui/form/form-field.svelte new file mode 100644 index 0000000..502280b --- /dev/null +++ b/src/components/ui/form/form-field.svelte @@ -0,0 +1,26 @@ + + + + + +
+ +
+
diff --git a/src/components/ui/form/form-fieldset.svelte b/src/components/ui/form/form-fieldset.svelte new file mode 100644 index 0000000..6ddcc5f --- /dev/null +++ b/src/components/ui/form/form-fieldset.svelte @@ -0,0 +1,31 @@ + + + + + + + diff --git a/src/components/ui/form/form-label.svelte b/src/components/ui/form/form-label.svelte new file mode 100644 index 0000000..f4ce3d2 --- /dev/null +++ b/src/components/ui/form/form-label.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/components/ui/form/form-legend.svelte b/src/components/ui/form/form-legend.svelte new file mode 100644 index 0000000..3b1387c --- /dev/null +++ b/src/components/ui/form/form-legend.svelte @@ -0,0 +1,17 @@ + + + + + diff --git a/src/components/ui/form/index.ts b/src/components/ui/form/index.ts new file mode 100644 index 0000000..0713927 --- /dev/null +++ b/src/components/ui/form/index.ts @@ -0,0 +1,33 @@ +import * as FormPrimitive from "formsnap"; +import Description from "./form-description.svelte"; +import Label from "./form-label.svelte"; +import FieldErrors from "./form-field-errors.svelte"; +import Field from "./form-field.svelte"; +import Fieldset from "./form-fieldset.svelte"; +import Legend from "./form-legend.svelte"; +import ElementField from "./form-element-field.svelte"; +import Button from "./form-button.svelte"; + +const Control = FormPrimitive.Control; + +export { + Field, + Control, + Label, + Button, + FieldErrors, + Description, + Fieldset, + Legend, + ElementField, + // + Field as FormField, + Control as FormControl, + Description as FormDescription, + Label as FormLabel, + FieldErrors as FormFieldErrors, + Fieldset as FormFieldset, + Legend as FormLegend, + ElementField as FormElementField, + Button as FormButton, +}; diff --git a/src/components/ui/input/index.ts b/src/components/ui/input/index.ts new file mode 100644 index 0000000..859f3b0 --- /dev/null +++ b/src/components/ui/input/index.ts @@ -0,0 +1,27 @@ +import Root from "./input.svelte"; + +export type FormInputEvent = T & { + currentTarget: EventTarget & HTMLInputElement; +}; +export type InputEvents = { + blur: FormInputEvent; + change: FormInputEvent; + click: FormInputEvent; + focus: FormInputEvent; + focusin: FormInputEvent; + focusout: FormInputEvent; + keydown: FormInputEvent; + keypress: FormInputEvent; + keyup: FormInputEvent; + mouseover: FormInputEvent; + mouseenter: FormInputEvent; + mouseleave: FormInputEvent; + paste: FormInputEvent; + input: FormInputEvent; +}; + +export { + Root, + // + Root as Input, +}; diff --git a/src/components/ui/input/input.svelte b/src/components/ui/input/input.svelte new file mode 100644 index 0000000..9a2fe0f --- /dev/null +++ b/src/components/ui/input/input.svelte @@ -0,0 +1,35 @@ + + + diff --git a/src/components/ui/label/index.ts b/src/components/ui/label/index.ts new file mode 100644 index 0000000..8bfca0b --- /dev/null +++ b/src/components/ui/label/index.ts @@ -0,0 +1,7 @@ +import Root from "./label.svelte"; + +export { + Root, + // + Root as Label, +}; diff --git a/src/components/ui/label/label.svelte b/src/components/ui/label/label.svelte new file mode 100644 index 0000000..2a7d479 --- /dev/null +++ b/src/components/ui/label/label.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/lib/Debug.ts b/src/lib/Debug.ts index 58822b0..f991011 100644 --- a/src/lib/Debug.ts +++ b/src/lib/Debug.ts @@ -2,7 +2,7 @@ import { Capacitor } from "@capacitor/core"; import { purchaseBeingEdited } from "$lib/Stores"; import { get } from "svelte/store"; import { Database } from "./Database"; -import { logInfo } from "./Logging"; +import { logDebug, logInfo } from "./Logging"; (window as any).toggleTestDB = () => { if (localStorage.getItem("useFBEmulator") == "true") { @@ -32,7 +32,7 @@ const showBuiltDebugMsg = (info: any) => { if (Capacitor.isNativePlatform()) { alert(JSON.stringify(info)); } else { - console.log("⚙️ DEBUG INFO:", info); + logDebug("DEBUG INFO:", info); } }; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 57796f7..f61272a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,10 +1,13 @@
@@ -12,7 +15,7 @@

💸

-
+
@@ -37,6 +40,7 @@ .emoji { cursor: default; user-select: none; - scale: 2; + scale: 3; + margin-bottom: 1.5em; } diff --git a/src/routes/+page.ts b/src/routes/+page.ts new file mode 100644 index 0000000..af69793 --- /dev/null +++ b/src/routes/+page.ts @@ -0,0 +1,12 @@ +import { superValidate } from "sveltekit-superforms"; +import { zod } from "sveltekit-superforms/adapters"; +import { z } from "zod"; +import { initialDatetimeString } from "../lib/utils/DateUtils"; +import { formSchema, initialFormValues } from "$components/entry/formSchema"; + +// https://github.com/huntabyte/shadcn-svelte/discussions/663#discussioncomment-8909677 +export const load = async () => { + const form = await superValidate(initialFormValues(), zod(formSchema)); + + return { form }; +}; diff --git a/tsconfig.json b/tsconfig.json index 6ae0c8c..b5ee43f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,18 @@ { - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true - } - // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias - // - // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes - // from the referenced tsconfig.json - TypeScript does not merge them in + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "importsNotUsedAsValues": "preserve" + } + // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias + // + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes + // from the referenced tsconfig.json - TypeScript does not merge them in } From d0e2dc4abfe3471da4afae0a8845f27784c74e39 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Sat, 30 Mar 2024 16:14:35 -0500 Subject: [PATCH 05/17] Nevermind lets not do grid --- src/components/entry/NewEntryForm.svelte | 45 ++++++++++++++---------- src/routes/+page.svelte | 2 +- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/components/entry/NewEntryForm.svelte b/src/components/entry/NewEntryForm.svelte index 5fa669f..09db61f 100644 --- a/src/components/entry/NewEntryForm.svelte +++ b/src/components/entry/NewEntryForm.svelte @@ -45,26 +45,27 @@ -
- Amount -
-
- - +
+
+ Amount +
+
+ +
-
-
+ +
+ @@ -85,8 +86,14 @@ --> -
+
Submit Reset
+ + diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index f61272a..19cf3b1 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -41,6 +41,6 @@ cursor: default; user-select: none; scale: 3; - margin-bottom: 1.5em; + margin-bottom: 2em; } From 8e49e86d3bbcb32d0d2c04fa8913781ceed01a05 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Sat, 30 Mar 2024 16:22:15 -0500 Subject: [PATCH 06/17] onSubmit with non amount hardcoded --- src/components/entry/NewEntryForm.svelte | 27 ++++++++++++++++++------ src/routes/+page.ts | 1 + 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/components/entry/NewEntryForm.svelte b/src/components/entry/NewEntryForm.svelte index 09db61f..21c9aa3 100644 --- a/src/components/entry/NewEntryForm.svelte +++ b/src/components/entry/NewEntryForm.svelte @@ -5,32 +5,45 @@ import * as Form from "$components/ui/form"; import Input from "$components/ui/input/input.svelte"; import type { FormInputEvent } from "$components/ui/input"; + import { purchaseBeingEdited } from "../../lib/Stores"; + import { Database } from "../../lib/Database"; + import type { Purchase } from "../../lib/DatabaseTypes"; + import { Timestamp } from "firebase/firestore"; export let superValidatedForm: SuperValidated; + // https://superforms.rocks/concepts/events const form = superForm(superValidatedForm, { SPA: true, validators: zod(formSchema), - // https://superforms.rocks/concepts/events#onresult onUpdate({ form }) { if (form.valid) { - console.log("Valid Data! ", form.data); + const entryTime = Timestamp.fromDate(new Date()); + const purchase: Purchase = { + amount: form.data.amount, + // shade-todo: form > hardcoded + category: "hardcoded", + purchaseDatetime: Timestamp.fromDate(new Date()), + description: "hardcoded", + entryDatetime: entryTime, + }; + if ($purchaseBeingEdited) { + // shade-todo: edit flow + } else { + Database.get().addPurchase(purchase).then(resetForm); + } } }, }); const { form: formData, enhance } = form; - formData.subscribe((data) => { - console.log("Data subscription:", data); - }); + const resetForm = () => ($formData = initialFormValues()); const inputEventToFloat = (e: FormInputEvent) => { const { value } = e?.target as HTMLInputElement; $formData.amount = parseFloat(value) || 0; }; - - const resetForm = () => ($formData = initialFormValues()); diff --git a/src/routes/+page.ts b/src/routes/+page.ts index af69793..eb4042c 100644 --- a/src/routes/+page.ts +++ b/src/routes/+page.ts @@ -4,6 +4,7 @@ import { z } from "zod"; import { initialDatetimeString } from "../lib/utils/DateUtils"; import { formSchema, initialFormValues } from "$components/entry/formSchema"; +// shade-todo: say thank you to this person + link // https://github.com/huntabyte/shadcn-svelte/discussions/663#discussioncomment-8909677 export const load = async () => { const form = await superValidate(initialFormValues(), zod(formSchema)); From cecf888c4cf5bd35bef6e80d184dcf41ead7154d Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Sat, 30 Mar 2024 16:36:32 -0500 Subject: [PATCH 07/17] Can edit ! --- src/components/entry/NewEntryForm.svelte | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/components/entry/NewEntryForm.svelte b/src/components/entry/NewEntryForm.svelte index 21c9aa3..ea83200 100644 --- a/src/components/entry/NewEntryForm.svelte +++ b/src/components/entry/NewEntryForm.svelte @@ -28,7 +28,12 @@ entryDatetime: entryTime, }; if ($purchaseBeingEdited) { - // shade-todo: edit flow + Database.get() + .updatePurchase($purchaseBeingEdited.ref, purchase) + .then(() => { + purchaseBeingEdited.set(undefined); + resetForm(); + }); } else { Database.get().addPurchase(purchase).then(resetForm); } @@ -40,6 +45,15 @@ const resetForm = () => ($formData = initialFormValues()); + purchaseBeingEdited.subscribe((purchase) => { + if (purchase) { + // note: reassigning formData completely broke. why? + $formData.amount = purchase.amount; + } else { + resetForm(); + } + }); + const inputEventToFloat = (e: FormInputEvent) => { const { value } = e?.target as HTMLInputElement; $formData.amount = parseFloat(value) || 0; From 299c68546d11df85d0cfc400ffee5a4438d5c9b2 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Wed, 10 Apr 2024 20:08:28 -0500 Subject: [PATCH 08/17] Save and Cancel edit buttons --- src/components/entry/NewEntryForm.svelte | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/entry/NewEntryForm.svelte b/src/components/entry/NewEntryForm.svelte index ea83200..b41f011 100644 --- a/src/components/entry/NewEntryForm.svelte +++ b/src/components/entry/NewEntryForm.svelte @@ -60,8 +60,6 @@ }; - - @@ -114,8 +112,20 @@ -->
- Submit - Reset + {#if $purchaseBeingEdited} + Save Edit + { + event.stopPropagation(); + resetForm(); + purchaseBeingEdited.set(undefined); + }}>Cancel Edit + {:else} + Submit + Reset + {/if}
From 86d1137a7747090ee65b14a98c37da6df782a54e Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Wed, 10 Apr 2024 20:29:37 -0500 Subject: [PATCH 09/17] Comments + add description block --- src/components/entry/NewEntryForm.svelte | 37 +++++++++++++++---- src/components/entry/formSchema.ts | 5 +-- src/components/purchases/PastPurchase.svelte | 2 + .../purchases/PastPurchasesList.svelte | 1 + src/lib/Database.ts | 3 +- src/routes/+page.ts | 2 +- tests/main-page.spec.ts | 15 +++----- 7 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/components/entry/NewEntryForm.svelte b/src/components/entry/NewEntryForm.svelte index b41f011..910327f 100644 --- a/src/components/entry/NewEntryForm.svelte +++ b/src/components/entry/NewEntryForm.svelte @@ -21,10 +21,9 @@ const entryTime = Timestamp.fromDate(new Date()); const purchase: Purchase = { amount: form.data.amount, - // shade-todo: form > hardcoded category: "hardcoded", purchaseDatetime: Timestamp.fromDate(new Date()), - description: "hardcoded", + description: form.data.description, entryDatetime: entryTime, }; if ($purchaseBeingEdited) { @@ -47,8 +46,8 @@ purchaseBeingEdited.subscribe((purchase) => { if (purchase) { - // note: reassigning formData completely broke. why? $formData.amount = purchase.amount; + $formData.description = purchase.description; } else { resetForm(); } @@ -60,17 +59,17 @@ }; - + - + - +
-
+
Amount
@@ -78,7 +77,7 @@ + + +
+
+ Description +
+
+ +
+
+
+
+ +
+
diff --git a/src/components/entry/formSchema.ts b/src/components/entry/formSchema.ts index 05fbd48..b6dccb5 100644 --- a/src/components/entry/formSchema.ts +++ b/src/components/entry/formSchema.ts @@ -7,15 +7,14 @@ export const initialFormValues = () => ({ amount: 0, // category: "", // purchaseDatetime: initialDatetimeString(), - // description: "", + description: "", }); export const formSchema = z.object({ amount: z.number().nonnegative(), // category: z.string(), // purchaseDatetime: z.string(), - // description: z.string(), + description: z.string(), }); -// .required(); export type FormSchema = ReturnType; diff --git a/src/components/purchases/PastPurchase.svelte b/src/components/purchases/PastPurchase.svelte index 3f80af0..53ce76d 100644 --- a/src/components/purchases/PastPurchase.svelte +++ b/src/components/purchases/PastPurchase.svelte @@ -24,6 +24,8 @@ }; + + {format(purchase.purchaseDatetime.toDate(), dateDisplayFormat)} +
{#if $purchases.data && !$purchases.error} diff --git a/src/lib/Database.ts b/src/lib/Database.ts index 6fa61f1..fe25df7 100644 --- a/src/lib/Database.ts +++ b/src/lib/Database.ts @@ -29,7 +29,7 @@ import type { import { get, writable, type Writable } from "svelte/store"; import { logInfo } from "./Logging"; -// refactor: after new collections are added this will be huge. +// smell: after new collections are added this will be huge. // How can I split up collections into their own respective classes? // generic operations? @@ -136,7 +136,6 @@ export class Database { } private initializePurchasesSubscription() { - // todo-postshadcn: get all within timespan from UI, instead of limiting to 15 const q = query( collection(this.db, "purchases"), orderBy("purchaseDatetime", "desc"), diff --git a/src/routes/+page.ts b/src/routes/+page.ts index eb4042c..92a03c0 100644 --- a/src/routes/+page.ts +++ b/src/routes/+page.ts @@ -4,7 +4,7 @@ import { z } from "zod"; import { initialDatetimeString } from "../lib/utils/DateUtils"; import { formSchema, initialFormValues } from "$components/entry/formSchema"; -// shade-todo: say thank you to this person + link +// note: say thank you to this person + link // https://github.com/huntabyte/shadcn-svelte/discussions/663#discussioncomment-8909677 export const load = async () => { const form = await superValidate(initialFormValues(), zod(formSchema)); diff --git a/tests/main-page.spec.ts b/tests/main-page.spec.ts index f7dff3e..e3de52f 100644 --- a/tests/main-page.spec.ts +++ b/tests/main-page.spec.ts @@ -19,8 +19,6 @@ import { } from "./CommonTestOperations"; import { add, format } from "date-fns"; -// TODO: Use shadcn/ui - test.beforeEach(async ({ page }) => { // https://github.com/microsoft/playwright/issues/6347#issuecomment-1085850728 const fakeNow = mockedClockDate.valueOf(); @@ -81,8 +79,6 @@ test.describe("Entry form", () => { ); }); - // todo-postshadcn: add clear button to form - test("Defaults to the current datetime", async ({ page }) => { await advanceTimeOneMinute(page); await advanceTimeOneMinute(page); @@ -126,7 +122,7 @@ test.describe("Adding", () => { ); }); - // todo-postshadcn: validation for each field (right now you can just do category) + // feature: validation for each field (right now you can just do category) }); test.describe("Editing", () => { @@ -268,15 +264,16 @@ test.describe("Reset", () => { }); }); -// todo: enable some of these tests to run in offline mode -// as well? +// enable some of these tests to run in offline mode? // - add purchase, block FB, add 2nd purchase, refresh page (FB Still blocked), are both purchases there? // - same but with delete as the operation instead of add // - ^ that was the core of why I wanted to use firebase so .... hope those work? // https://github.com/microsoft/playwright/issues/27599#issuecomment-1761787734 -// todo: firebase rules to require login? +// feature: firebase rules to require login? +// feature: ditch firebase and use verdant? +// https://github.com/a-type/verdant -// idea: sort toggle (sort purchases by entry date or purchase date) +// feature: sort toggle (sort purchases by entry date or purchase date) // idea: dark theme From f0873d85441c19928d25fe116d4d2746f8ffd57d Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Sun, 2 Jun 2024 22:09:55 -0500 Subject: [PATCH 10/17] todo list --- README.md | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index be2bb0c..4e6810f 100644 --- a/README.md +++ b/README.md @@ -9,21 +9,25 @@ categorization. ## Why Don't give up your all your financial data just to see a inaccurate -auto-generated categorization table. +auto-generated categorization table. No login required. ## Links: -- Package init: https://ionic.io/blog/cross-platform-sveltekit-capacitor-application-yes-its-possible +- Boilerplate guide used to start repo: https://ionic.io/blog/cross-platform-sveltekit-capacitor-application-yes-its-possible - Svelte Forms Lib (Like Formik) https://svelte-forms-lib-sapper-docs.vercel.app/basic - Firebase offline syncing: https://firebase.google.com/docs/firestore/manage-data/enable-offline ## Testing +- Required: `npm i -g firebase-cli` + + - Then: `node run firebase` to start emu. + - Playwright high level e2e tests - Tests reuse some application code to modify database for scenarios - Tests spin up a local firebase emulator to use - Setting a key of "useFBEmulator" in your localstorage will enable emulator - usage over a remove firestore instance. + usage over a remote firestore instance. - Clicking the money emoji 3 times will display debug information in your console log, or fire an alert dialog if on mobile @@ -32,11 +36,27 @@ auto-generated categorization table. - SPA, no ssr-rendering, all pre-rendered to work with Capacitor - Details in +layout.ts -### Revisited 3/8 - -- Still want to track spending within a paycheck (date range + budget) + categorize + track account + export csv for date range - ### Next Up -- Blog post about time mock -- Need shadcn before adding more features +- In Progress: Need shadcn before adding more features +- Replace firebase w tinybase (because firebase can't be offline only) + - Use tinybase to store in sqlite + - Encrypt entries at the store level with device id + - [uuid](https://forum.ionicframework.com/t/inconsistent-getid-uuid-with-capacitor-device-on-ios/233122/2) + - Sync enrolled users w PowerSync to postgres (anything going to postgres is + encrypted) + - supabase free tier for cloud postgres + - projects are paused after 1 week of inactivity? caffeine cron? + - powersync free cloud tier, potentially self hosted in future. + - using both in combo - [link](https://docs.powersync.com/integration-guides/supabase-+-powersync) + - linking tinybase to powersync - [link](https://tinybase.org/api/persister-powersync/) + - Oh look that's validating [blog](https://bndkt.com/blog/2024/the-easiest-way-to-build-reactive-local-first-apps-with-tinybase-and-powersync) +- Track spending within a paycheck (date range + target, "X left") +- Pie graph of categories + - Choosing sub topic shows most expensive sub categories / or purchases +- Category initialization +- Export data as CSV + +## Future Ideas: + +- Woah [siri support?](https://github.com/lovetodream/capacitor-plugin-siri-shortcuts). Would have to parse the text in JS? From 75b2c5f14fc253e68acb8a4f38108e58c9e91bee Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Tue, 4 Jun 2024 21:29:04 -0500 Subject: [PATCH 11/17] Working category field --- README.md | 6 ++ ios/App/Podfile.lock | 12 +-- package-lock.json | 84 +++++++++++++++++++ package.json | 2 + src/components/entry/NewCategorySelect.svelte | 80 ++++++++++++++++++ src/components/entry/NewEntryForm.svelte | 29 +++++-- src/components/entry/formSchema.ts | 4 +- src/components/ui/button/button.svelte | 34 ++++---- .../ui/command/command-dialog.svelte | 23 +++++ .../ui/command/command-empty.svelte | 15 ++++ .../ui/command/command-group.svelte | 18 ++++ .../ui/command/command-input.svelte | 23 +++++ src/components/ui/command/command-item.svelte | 24 ++++++ src/components/ui/command/command-list.svelte | 15 ++++ .../ui/command/command-separator.svelte | 13 +++ .../ui/command/command-shortcut.svelte | 16 ++++ src/components/ui/command/command.svelte | 22 +++++ src/components/ui/command/index.ts | 37 ++++++++ .../ui/dialog/dialog-content.svelte | 36 ++++++++ .../ui/dialog/dialog-description.svelte | 16 ++++ src/components/ui/dialog/dialog-footer.svelte | 19 +++++ src/components/ui/dialog/dialog-header.svelte | 16 ++++ .../ui/dialog/dialog-overlay.svelte | 21 +++++ src/components/ui/dialog/dialog-portal.svelte | 8 ++ src/components/ui/dialog/dialog-title.svelte | 16 ++++ src/components/ui/dialog/index.ts | 34 ++++++++ .../ui/form/form-description.svelte | 20 ++--- .../ui/form/form-element-field.svelte | 45 ++++++---- .../ui/form/form-field-errors.svelte | 36 ++++---- src/components/ui/form/form-field.svelte | 44 ++++++---- src/components/ui/form/form-fieldset.svelte | 43 +++++----- src/components/ui/form/form-label.svelte | 24 +++--- src/components/ui/form/form-legend.svelte | 21 +++-- src/components/ui/input/input.svelte | 56 ++++++------- src/components/ui/label/label.svelte | 26 +++--- src/components/ui/popover/index.ts | 17 ++++ .../ui/popover/popover-content.svelte | 22 +++++ src/lib/Debug.ts | 2 +- src/lib/{utils.ts => utils/shadecnUtils.ts} | 0 tests/main-page.spec.ts | 2 + 40 files changed, 808 insertions(+), 173 deletions(-) create mode 100644 src/components/entry/NewCategorySelect.svelte create mode 100644 src/components/ui/command/command-dialog.svelte create mode 100644 src/components/ui/command/command-empty.svelte create mode 100644 src/components/ui/command/command-group.svelte create mode 100644 src/components/ui/command/command-input.svelte create mode 100644 src/components/ui/command/command-item.svelte create mode 100644 src/components/ui/command/command-list.svelte create mode 100644 src/components/ui/command/command-separator.svelte create mode 100644 src/components/ui/command/command-shortcut.svelte create mode 100644 src/components/ui/command/command.svelte create mode 100644 src/components/ui/command/index.ts create mode 100644 src/components/ui/dialog/dialog-content.svelte create mode 100644 src/components/ui/dialog/dialog-description.svelte create mode 100644 src/components/ui/dialog/dialog-footer.svelte create mode 100644 src/components/ui/dialog/dialog-header.svelte create mode 100644 src/components/ui/dialog/dialog-overlay.svelte create mode 100644 src/components/ui/dialog/dialog-portal.svelte create mode 100644 src/components/ui/dialog/dialog-title.svelte create mode 100644 src/components/ui/dialog/index.ts create mode 100644 src/components/ui/popover/index.ts create mode 100644 src/components/ui/popover/popover-content.svelte rename src/lib/{utils.ts => utils/shadecnUtils.ts} (100%) diff --git a/README.md b/README.md index 4e6810f..4a83d6b 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,11 @@ categorization. Don't give up your all your financial data just to see a inaccurate auto-generated categorization table. No login required. +## This idea made me stumble into the "local first" community + +- [maggie appleton loficonf talk](https://maggieappleton.com/home-cooked-software) +- revisited annually: [robin sloan](https://www.robinsloan.com/notes/home-cooked-app/) + ## Links: - Boilerplate guide used to start repo: https://ionic.io/blog/cross-platform-sveltekit-capacitor-application-yes-its-possible @@ -39,6 +44,7 @@ auto-generated categorization table. No login required. ### Next Up - In Progress: Need shadcn before adding more features +- Try bun - Replace firebase w tinybase (because firebase can't be offline only) - Use tinybase to store in sqlite - Encrypt entries at the store level with device id diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock index db84247..8e1748f 100644 --- a/ios/App/Podfile.lock +++ b/ios/App/Podfile.lock @@ -1,9 +1,9 @@ PODS: - - Capacitor (5.0.5): + - Capacitor (5.7.4): - CapacitorCordova - - CapacitorApp (5.0.3): + - CapacitorApp (5.0.7): - Capacitor - - CapacitorCordova (5.0.5) + - CapacitorCordova (5.7.4) DEPENDENCIES: - "Capacitor (from `../../node_modules/@capacitor/ios`)" @@ -19,9 +19,9 @@ EXTERNAL SOURCES: :path: "../../node_modules/@capacitor/ios" SPEC CHECKSUMS: - Capacitor: b1248915663add1bd6567e2b67c1c1fa3abcf5e8 - CapacitorApp: 7a5dec8b33573707164b293475d5c89ba684364a - CapacitorCordova: f8c06b897c74ee8f7701fe10e6443b40822bc83a + Capacitor: 4fe9adf012caceb4c71ffea2f1f4d005cdcbeea7 + CapacitorApp: 17fecd0e6cb23feafac7eb0939417389038b0979 + CapacitorCordova: a6e87fccc0307dee7aec1560ec9398485f2b0ce7 PODFILE CHECKSUM: ff93f75dfd87608d4250c18084881dce75dc9690 diff --git a/package-lock.json b/package-lock.json index cb47409..432d332 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,9 +15,11 @@ "@svelte-put/clickoutside": "^3.0.1", "bits-ui": "^0.20.1", "clsx": "^2.1.0", + "cmdk-sv": "^0.0.17", "date-fns": "^3.3.1", "firebase": "^10.1.0", "formsnap": "^1.0.0", + "lucide-svelte": "^0.383.0", "svelecte": "^3.17.2", "sveltekit-superforms": "^2.11.0", "tailwind-merge": "^2.2.2", @@ -2485,6 +2487,80 @@ "node": ">=6" } }, + "node_modules/cmdk-sv": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/cmdk-sv/-/cmdk-sv-0.0.17.tgz", + "integrity": "sha512-28QTrK1tT1TSNoGq9MVnzjeLNNjCgjmsM8c2HJfDpRt9t+GD+9m3wX/WdAPaP9jdoNYU0SSdZVdgsGgpaSQOYQ==", + "dependencies": { + "bits-ui": "^0.9.0", + "nanoid": "^5.0.2" + }, + "peerDependencies": { + "svelte": "^4.0.0" + } + }, + "node_modules/cmdk-sv/node_modules/@melt-ui/svelte": { + "version": "0.61.2", + "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.61.2.tgz", + "integrity": "sha512-BHkD9G31zQBToA4euDRBgTQRvWxT9scufOVCXgDO6HKTvyxFspbWT2bgiSFqAK4BbAGDn9Ao36Q8F9O71KN4OQ==", + "dependencies": { + "@floating-ui/core": "^1.3.1", + "@floating-ui/dom": "^1.4.5", + "@internationalized/date": "^3.5.0", + "dequal": "^2.0.3", + "focus-trap": "^7.5.2", + "nanoid": "^4.0.2" + }, + "peerDependencies": { + "svelte": ">=3 <5" + } + }, + "node_modules/cmdk-sv/node_modules/@melt-ui/svelte/node_modules/nanoid": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz", + "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/cmdk-sv/node_modules/bits-ui": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.9.9.tgz", + "integrity": "sha512-LkdkyTtpXdkjBzPZJVJgpcre4fut6DONoprMfadHFo82HNUhph+02CxDjYEcZcThb5z4YjSxMlCYvQPZm+YtfQ==", + "dependencies": { + "@melt-ui/svelte": "0.61.2", + "nanoid": "^5.0.3" + }, + "peerDependencies": { + "svelte": "^4.0.0" + } + }, + "node_modules/cmdk-sv/node_modules/nanoid": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/code-red": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", @@ -3868,6 +3944,14 @@ "node": "14 || >=16.14" } }, + "node_modules/lucide-svelte": { + "version": "0.383.0", + "resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.383.0.tgz", + "integrity": "sha512-jA4fd9v1gLuE/iNszC7VyIexDnWX06bYpFFTPfBwk0FKh3Paf7FULgotQ8UUY1Lsr6JIMWASh7zKhI2f1bePFw==", + "peerDependencies": { + "svelte": "^3 || ^4 || ^5.0.0-next.42" + } + }, "node_modules/magic-string": { "version": "0.30.8", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", diff --git a/package.json b/package.json index f6046f3..49b135f 100644 --- a/package.json +++ b/package.json @@ -54,9 +54,11 @@ "@svelte-put/clickoutside": "^3.0.1", "bits-ui": "^0.20.1", "clsx": "^2.1.0", + "cmdk-sv": "^0.0.17", "date-fns": "^3.3.1", "firebase": "^10.1.0", "formsnap": "^1.0.0", + "lucide-svelte": "^0.383.0", "svelecte": "^3.17.2", "sveltekit-superforms": "^2.11.0", "tailwind-merge": "^2.2.2", diff --git a/src/components/entry/NewCategorySelect.svelte b/src/components/entry/NewCategorySelect.svelte new file mode 100644 index 0000000..5d49891 --- /dev/null +++ b/src/components/entry/NewCategorySelect.svelte @@ -0,0 +1,80 @@ + + + + + + + + + + No Category found. + + {#each categories as category} + { + value = currentValue; + closeAndFocusTrigger(ids.trigger); + }} + > + + {category.label} + + {/each} + + + + diff --git a/src/components/entry/NewEntryForm.svelte b/src/components/entry/NewEntryForm.svelte index 910327f..ac7b5b9 100644 --- a/src/components/entry/NewEntryForm.svelte +++ b/src/components/entry/NewEntryForm.svelte @@ -9,9 +9,15 @@ import { Database } from "../../lib/Database"; import type { Purchase } from "../../lib/DatabaseTypes"; import { Timestamp } from "firebase/firestore"; + import NewCategorySelect from "./NewCategorySelect.svelte"; export let superValidatedForm: SuperValidated; + // todo: add auto open amount back to UI + // App.addListener("appStateChange", ({ isActive }) => { + // isActive && document.getElementById("amount")?.focus(); + // }); + // https://superforms.rocks/concepts/events const form = superForm(superValidatedForm, { SPA: true, @@ -21,7 +27,7 @@ const entryTime = Timestamp.fromDate(new Date()); const purchase: Purchase = { amount: form.data.amount, - category: "hardcoded", + category: form.data.category, purchaseDatetime: Timestamp.fromDate(new Date()), description: form.data.description, entryDatetime: entryTime, @@ -48,6 +54,7 @@ if (purchase) { $formData.amount = purchase.amount; $formData.description = purchase.description; + $formData.category = purchase.category; } else { resetForm(); } @@ -70,7 +77,8 @@
-
+ +
Amount
@@ -87,14 +95,14 @@
-
-
+ +
Description
@@ -110,9 +118,20 @@
- + + +
+ Category + +
+
+
+ + + + diff --git a/src/components/entry/formSchema.ts b/src/components/entry/formSchema.ts index b6dccb5..4ec84aa 100644 --- a/src/components/entry/formSchema.ts +++ b/src/components/entry/formSchema.ts @@ -5,14 +5,14 @@ import { initialDatetimeString } from "$lib/utils/DateUtils"; export const initialFormValues = () => ({ amount: 0, - // category: "", + category: "", // purchaseDatetime: initialDatetimeString(), description: "", }); export const formSchema = z.object({ amount: z.number().nonnegative(), - // category: z.string(), + category: z.string(), // purchaseDatetime: z.string(), description: z.string(), }); diff --git a/src/components/ui/button/button.svelte b/src/components/ui/button/button.svelte index 0634d48..c6492ef 100644 --- a/src/components/ui/button/button.svelte +++ b/src/components/ui/button/button.svelte @@ -1,25 +1,25 @@ - + diff --git a/src/components/ui/command/command-dialog.svelte b/src/components/ui/command/command-dialog.svelte new file mode 100644 index 0000000..fde7ed1 --- /dev/null +++ b/src/components/ui/command/command-dialog.svelte @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/src/components/ui/command/command-empty.svelte b/src/components/ui/command/command-empty.svelte new file mode 100644 index 0000000..330538e --- /dev/null +++ b/src/components/ui/command/command-empty.svelte @@ -0,0 +1,15 @@ + + + + + diff --git a/src/components/ui/command/command-group.svelte b/src/components/ui/command/command-group.svelte new file mode 100644 index 0000000..9f2efb2 --- /dev/null +++ b/src/components/ui/command/command-group.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/src/components/ui/command/command-input.svelte b/src/components/ui/command/command-input.svelte new file mode 100644 index 0000000..81af6f5 --- /dev/null +++ b/src/components/ui/command/command-input.svelte @@ -0,0 +1,23 @@ + + +
+ + +
diff --git a/src/components/ui/command/command-item.svelte b/src/components/ui/command/command-item.svelte new file mode 100644 index 0000000..be41118 --- /dev/null +++ b/src/components/ui/command/command-item.svelte @@ -0,0 +1,24 @@ + + + + + diff --git a/src/components/ui/command/command-list.svelte b/src/components/ui/command/command-list.svelte new file mode 100644 index 0000000..ce12da6 --- /dev/null +++ b/src/components/ui/command/command-list.svelte @@ -0,0 +1,15 @@ + + + + + diff --git a/src/components/ui/command/command-separator.svelte b/src/components/ui/command/command-separator.svelte new file mode 100644 index 0000000..84c17f5 --- /dev/null +++ b/src/components/ui/command/command-separator.svelte @@ -0,0 +1,13 @@ + + + diff --git a/src/components/ui/command/command-shortcut.svelte b/src/components/ui/command/command-shortcut.svelte new file mode 100644 index 0000000..194d9f1 --- /dev/null +++ b/src/components/ui/command/command-shortcut.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/components/ui/command/command.svelte b/src/components/ui/command/command.svelte new file mode 100644 index 0000000..9cb5144 --- /dev/null +++ b/src/components/ui/command/command.svelte @@ -0,0 +1,22 @@ + + + + + diff --git a/src/components/ui/command/index.ts b/src/components/ui/command/index.ts new file mode 100644 index 0000000..d8a2e7c --- /dev/null +++ b/src/components/ui/command/index.ts @@ -0,0 +1,37 @@ +import { Command as CommandPrimitive } from "cmdk-sv"; + +import Root from "./command.svelte"; +import Dialog from "./command-dialog.svelte"; +import Empty from "./command-empty.svelte"; +import Group from "./command-group.svelte"; +import Item from "./command-item.svelte"; +import Input from "./command-input.svelte"; +import List from "./command-list.svelte"; +import Separator from "./command-separator.svelte"; +import Shortcut from "./command-shortcut.svelte"; + +const Loading = CommandPrimitive.Loading; + +export { + Root, + Dialog, + Empty, + Group, + Item, + Input, + List, + Separator, + Shortcut, + Loading, + // + Root as Command, + Dialog as CommandDialog, + Empty as CommandEmpty, + Group as CommandGroup, + Item as CommandItem, + Input as CommandInput, + List as CommandList, + Separator as CommandSeparator, + Shortcut as CommandShortcut, + Loading as CommandLoading, +}; diff --git a/src/components/ui/dialog/dialog-content.svelte b/src/components/ui/dialog/dialog-content.svelte new file mode 100644 index 0000000..da2b6f2 --- /dev/null +++ b/src/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,36 @@ + + + + + + + + + Close + + + diff --git a/src/components/ui/dialog/dialog-description.svelte b/src/components/ui/dialog/dialog-description.svelte new file mode 100644 index 0000000..68292e6 --- /dev/null +++ b/src/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/components/ui/dialog/dialog-footer.svelte b/src/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 0000000..84b66b7 --- /dev/null +++ b/src/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,19 @@ + + +
+ +
diff --git a/src/components/ui/dialog/dialog-header.svelte b/src/components/ui/dialog/dialog-header.svelte new file mode 100644 index 0000000..b641583 --- /dev/null +++ b/src/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,16 @@ + + +
+ +
diff --git a/src/components/ui/dialog/dialog-overlay.svelte b/src/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 0000000..d66c644 --- /dev/null +++ b/src/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/components/ui/dialog/dialog-portal.svelte b/src/components/ui/dialog/dialog-portal.svelte new file mode 100644 index 0000000..eb5d0a5 --- /dev/null +++ b/src/components/ui/dialog/dialog-portal.svelte @@ -0,0 +1,8 @@ + + + + + diff --git a/src/components/ui/dialog/dialog-title.svelte b/src/components/ui/dialog/dialog-title.svelte new file mode 100644 index 0000000..6993081 --- /dev/null +++ b/src/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/components/ui/dialog/index.ts b/src/components/ui/dialog/index.ts new file mode 100644 index 0000000..5c54cf5 --- /dev/null +++ b/src/components/ui/dialog/index.ts @@ -0,0 +1,34 @@ +import { Dialog as DialogPrimitive } from "bits-ui"; + +import Title from "./dialog-title.svelte"; +import Portal from "./dialog-portal.svelte"; +import Footer from "./dialog-footer.svelte"; +import Header from "./dialog-header.svelte"; +import Overlay from "./dialog-overlay.svelte"; +import Content from "./dialog-content.svelte"; +import Description from "./dialog-description.svelte"; + +const Root = DialogPrimitive.Root; +const Trigger = DialogPrimitive.Trigger; + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, +}; diff --git a/src/components/ui/form/form-description.svelte b/src/components/ui/form/form-description.svelte index 20fa79d..e6ff67b 100644 --- a/src/components/ui/form/form-description.svelte +++ b/src/components/ui/form/form-description.svelte @@ -1,17 +1,17 @@ - + diff --git a/src/components/ui/form/form-element-field.svelte b/src/components/ui/form/form-element-field.svelte index eece7e1..342ec65 100644 --- a/src/components/ui/form/form-element-field.svelte +++ b/src/components/ui/form/form-element-field.svelte @@ -1,26 +1,37 @@ - - -
- -
+ +
+ +
diff --git a/src/components/ui/form/form-field-errors.svelte b/src/components/ui/form/form-field-errors.svelte index 9395326..ad7630b 100644 --- a/src/components/ui/form/form-field-errors.svelte +++ b/src/components/ui/form/form-field-errors.svelte @@ -1,26 +1,26 @@ - - {#each errors as error} -
{error}
- {/each} -
+ + {#each errors as error} +
{error}
+ {/each} +
diff --git a/src/components/ui/form/form-field.svelte b/src/components/ui/form/form-field.svelte index 502280b..abb73cd 100644 --- a/src/components/ui/form/form-field.svelte +++ b/src/components/ui/form/form-field.svelte @@ -1,26 +1,36 @@ - - -
- -
+ +
+ +
diff --git a/src/components/ui/form/form-fieldset.svelte b/src/components/ui/form/form-fieldset.svelte index 6ddcc5f..834b069 100644 --- a/src/components/ui/form/form-fieldset.svelte +++ b/src/components/ui/form/form-fieldset.svelte @@ -1,31 +1,34 @@ - - + diff --git a/src/components/ui/form/form-label.svelte b/src/components/ui/form/form-label.svelte index f4ce3d2..8741256 100644 --- a/src/components/ui/form/form-label.svelte +++ b/src/components/ui/form/form-label.svelte @@ -1,17 +1,21 @@ -
diff --git a/tests/main-page.spec.ts b/tests/main-page.spec.ts index e2f967f..82a23c9 100644 --- a/tests/main-page.spec.ts +++ b/tests/main-page.spec.ts @@ -59,10 +59,6 @@ test("Past purchases are loaded and shown in order", async ({ page }) => { }); test.describe("Entry form", () => { - test("Auto focuses on page load", async ({ page }) => { - await expect(page.getByLabel("Amount")).toBeFocused(); - }); - test("Clocks is set to the mocked playwright time", async ({ page }) => { await expect(page.getByTestId("datetime-input")).toHaveValue( new RegExp(mockedClockDatetimeString) From 6016a04f4aff1e06c27a68ab4c23bc9be3598658 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Sun, 25 Aug 2024 19:37:34 -0500 Subject: [PATCH 16/17] Note updates --- README.md | 7 ++++--- tests/main-page.spec.ts | 14 -------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 4a83d6b..6824178 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ auto-generated categorization table. No login required. - [maggie appleton loficonf talk](https://maggieappleton.com/home-cooked-software) - revisited annually: [robin sloan](https://www.robinsloan.com/notes/home-cooked-app/) +- https://biscuits.club/about built with https://github.com/a-type/verdant ## Links: @@ -43,8 +44,6 @@ auto-generated categorization table. No login required. ### Next Up -- In Progress: Need shadcn before adding more features -- Try bun - Replace firebase w tinybase (because firebase can't be offline only) - Use tinybase to store in sqlite - Encrypt entries at the store level with device id @@ -58,11 +57,13 @@ auto-generated categorization table. No login required. - linking tinybase to powersync - [link](https://tinybase.org/api/persister-powersync/) - Oh look that's validating [blog](https://bndkt.com/blog/2024/the-easiest-way-to-build-reactive-local-first-apps-with-tinybase-and-powersync) - Track spending within a paycheck (date range + target, "X left") + - Log these spending goals - Pie graph of categories - Choosing sub topic shows most expensive sub categories / or purchases - Category initialization - Export data as CSV +- Spending timeline checklist ## Future Ideas: -- Woah [siri support?](https://github.com/lovetodream/capacitor-plugin-siri-shortcuts). Would have to parse the text in JS? +- Woah [siri support?](https://github.com/lovetodream/capacitor-plugin-siri-shortcuts) diff --git a/tests/main-page.spec.ts b/tests/main-page.spec.ts index 82a23c9..eed293c 100644 --- a/tests/main-page.spec.ts +++ b/tests/main-page.spec.ts @@ -261,17 +261,3 @@ test.describe("Reset", () => { ); }); }); - -// enable some of these tests to run in offline mode? -// - add purchase, block FB, add 2nd purchase, refresh page (FB Still blocked), are both purchases there? -// - same but with delete as the operation instead of add -// - ^ that was the core of why I wanted to use firebase so .... hope those work? -// https://github.com/microsoft/playwright/issues/27599#issuecomment-1761787734 - -// feature: firebase rules to require login? -// feature: ditch firebase and use verdant? -// https://github.com/a-type/verdant - -// feature: sort toggle (sort purchases by entry date or purchase date) - -// idea: dark theme From 26e2462d912588c1bafdad7c6bb762f525acff4a Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 2 Sep 2024 13:07:55 -0500 Subject: [PATCH 17/17] more note updates --- README.md | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 6824178..d3a78fe 100644 --- a/README.md +++ b/README.md @@ -46,16 +46,10 @@ auto-generated categorization table. No login required. - Replace firebase w tinybase (because firebase can't be offline only) - Use tinybase to store in sqlite - - Encrypt entries at the store level with device id - - [uuid](https://forum.ionicframework.com/t/inconsistent-getid-uuid-with-capacitor-device-on-ios/233122/2) - - Sync enrolled users w PowerSync to postgres (anything going to postgres is - encrypted) - - supabase free tier for cloud postgres - - projects are paused after 1 week of inactivity? caffeine cron? - - powersync free cloud tier, potentially self hosted in future. - - using both in combo - [link](https://docs.powersync.com/integration-guides/supabase-+-powersync) - - linking tinybase to powersync - [link](https://tinybase.org/api/persister-powersync/) - - Oh look that's validating [blog](https://bndkt.com/blog/2024/the-easiest-way-to-build-reactive-local-first-apps-with-tinybase-and-powersync) + - Add sqlite backup / restore +- TestFlight +- CI/CD +- Linting / formatting - Track spending within a paycheck (date range + target, "X left") - Log these spending goals - Pie graph of categories @@ -63,7 +57,3 @@ auto-generated categorization table. No login required. - Category initialization - Export data as CSV - Spending timeline checklist - -## Future Ideas: - -- Woah [siri support?](https://github.com/lovetodream/capacitor-plugin-siri-shortcuts)