From 8b181087c392a92d907d62b687b138ad53a36ec8 Mon Sep 17 00:00:00 2001 From: mohamad Date: Sat, 28 Jun 2025 14:15:03 +0200 Subject: [PATCH] phase 2 - ui refactor --- fe/eslint.config.ts | 7 +- fe/package-lock.json | 1615 +++++++-------- fe/package.json | 20 +- fe/postcss.config.cjs | 6 + fe/src/App.vue | 20 +- fe/src/assets/base.css | 9 + fe/src/assets/main.scss | 96 - fe/src/assets/valerie-ui.scss | 1750 ----------------- fe/src/assets/variables.scss | 21 - fe/src/components/BaseIcon.vue | 13 + fe/src/components/ChoreItem.vue | 12 +- fe/src/components/ui/Button.vue | 73 + fe/src/components/ui/Dialog.vue | 36 + fe/src/components/ui/Listbox.vue | 27 + fe/src/components/ui/Menu.vue | 17 + fe/src/components/ui/Switch.vue | 27 + fe/src/components/ui/Tabs.vue | 14 + fe/src/components/ui/TransitionExpand.vue | 11 + fe/src/components/ui/__tests__/Button.spec.ts | 35 + fe/src/components/ui/__tests__/Dialog.spec.ts | 22 + .../components/ui/__tests__/Listbox.spec.ts | 23 + fe/src/components/ui/__tests__/Menu.spec.ts | 20 + fe/src/components/ui/__tests__/Switch.spec.ts | 14 + fe/src/components/ui/__tests__/Tabs.spec.ts | 16 + .../ui/__tests__/TransitionExpand.spec.ts | 14 + fe/src/components/ui/index.ts | 7 + fe/src/main.ts | 2 +- fe/src/pages/ChoresPage.vue | 26 +- fe/tailwind.config.ts | 49 + fe/tsconfig.vitest.json | 14 +- package-lock.json | 6 + 31 files changed, 1147 insertions(+), 2875 deletions(-) create mode 100644 fe/postcss.config.cjs create mode 100644 fe/src/assets/base.css delete mode 100644 fe/src/assets/main.scss delete mode 100644 fe/src/assets/valerie-ui.scss delete mode 100644 fe/src/assets/variables.scss create mode 100644 fe/src/components/BaseIcon.vue create mode 100644 fe/src/components/ui/Button.vue create mode 100644 fe/src/components/ui/Dialog.vue create mode 100644 fe/src/components/ui/Listbox.vue create mode 100644 fe/src/components/ui/Menu.vue create mode 100644 fe/src/components/ui/Switch.vue create mode 100644 fe/src/components/ui/Tabs.vue create mode 100644 fe/src/components/ui/TransitionExpand.vue create mode 100644 fe/src/components/ui/__tests__/Button.spec.ts create mode 100644 fe/src/components/ui/__tests__/Dialog.spec.ts create mode 100644 fe/src/components/ui/__tests__/Listbox.spec.ts create mode 100644 fe/src/components/ui/__tests__/Menu.spec.ts create mode 100644 fe/src/components/ui/__tests__/Switch.spec.ts create mode 100644 fe/src/components/ui/__tests__/Tabs.spec.ts create mode 100644 fe/src/components/ui/__tests__/TransitionExpand.spec.ts create mode 100644 fe/src/components/ui/index.ts create mode 100644 fe/tailwind.config.ts create mode 100644 package-lock.json diff --git a/fe/eslint.config.ts b/fe/eslint.config.ts index 6d5fe2f..8c3034e 100644 --- a/fe/eslint.config.ts +++ b/fe/eslint.config.ts @@ -1,9 +1,11 @@ +// @ts-nocheck // For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format import storybook from "eslint-plugin-storybook"; import { globalIgnores } from 'eslint/config' import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript' import pluginVue from 'eslint-plugin-vue' +import pluginTailwindcss from 'eslint-plugin-tailwindcss' import pluginVitest from '@vitest/eslint-plugin' import pluginPlaywright from 'eslint-plugin-playwright' import pluginOxlint from 'eslint-plugin-oxlint' @@ -24,16 +26,17 @@ export default defineConfigWithVueTs( pluginVue.configs['flat/essential'], vueTsConfigs.recommended, - + { ...pluginVitest.configs.recommended, files: ['src/**/__tests__/*'], }, - + { ...pluginPlaywright.configs['flat/recommended'], files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'], }, ...pluginOxlint.configs['flat/recommended'], skipFormatting, + pluginTailwindcss.configs.recommended, ) diff --git a/fe/package-lock.json b/fe/package-lock.json index 4c5bbac..128d942 100644 --- a/fe/package-lock.json +++ b/fe/package-lock.json @@ -8,18 +8,15 @@ "name": "fe", "version": "0.0.0", "dependencies": { + "@headlessui/vue": "^1.7.23", + "@iconify/vue": "^4.1.1", "@sentry/tracing": "^7.120.3", "@sentry/vue": "^7.120.3", - "@supabase/auth-js": "^2.69.1", - "@supabase/supabase-js": "^2.49.4", "@vueuse/core": "^13.1.0", "axios": "^1.9.0", "date-fns": "^4.1.0", - "framer-motion": "^12.16.0", - "motion": "^12.15.0", "pinia": "^3.0.2", "qs": "^6.14.0", - "reka-ui": "^2.3.1", "vue": "^3.5.13", "vue-i18n": "^9.9.1", "vue-router": "^4.5.1", @@ -27,11 +24,11 @@ "workbox-background-sync": "^7.3.0" }, "devDependencies": { + "@headlessui/tailwindcss": "^0.2.2", "@intlify/unplugin-vue-i18n": "^4.0.0", "@playwright/test": "^1.51.1", - "@storybook/addon-docs": "^9.0.2", - "@storybook/addon-onboarding": "^9.0.2", - "@storybook/vue3-vite": "^9.0.2", + "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/typography": "^0.5.10", "@tsconfig/node22": "^22.0.1", "@types/date-fns": "^2.5.3", "@types/jsdom": "^21.1.7", @@ -43,18 +40,21 @@ "@vue/eslint-config-typescript": "^14.5.0", "@vue/test-utils": "^2.4.6", "@vue/tsconfig": "^0.7.0", + "autoprefixer": "^10.4.16", "eslint": "^9.26.0", "eslint-plugin-oxlint": "^0.16.0", "eslint-plugin-playwright": "^2.2.0", "eslint-plugin-storybook": "^9.0.2", + "eslint-plugin-tailwindcss": "^3.13.0", "eslint-plugin-vue": "~10.0.0", "jiti": "^2.4.2", "jsdom": "^26.0.0", "npm-run-all2": "^7.0.2", "oxlint": "^0.16.0", + "postcss": "^8.4.34", "prettier": "^3.5.3", "sass": "^1.88.0", - "storybook": "^9.0.2", + "tailwindcss": "^3.4.4", "typescript": "~5.8.0", "vite": "^6.2.4", "vite-plugin-pwa": "^1.0.0", @@ -74,7 +74,21 @@ "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.3.tgz", "integrity": "sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/@ampproject/remapping": { "version": "2.3.0", @@ -2496,66 +2510,32 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@floating-ui/core": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz", - "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", + "node_modules/@headlessui/tailwindcss": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@headlessui/tailwindcss/-/tailwindcss-0.2.2.tgz", + "integrity": "sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw==", + "dev": true, "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz", - "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.2", - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", - "license": "MIT" - }, - "node_modules/@floating-ui/vue": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@floating-ui/vue/-/vue-1.1.7.tgz", - "integrity": "sha512-idmAtbAIigGXN2SI5gItiXYBYtNfDTP9yIiObxgu13dgtG7ARCHlNfnR29GxP4LI4o13oiwsJ8wVgghj1lNqcw==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.7.2", - "@floating-ui/utils": "^0.2.10", - "vue-demi": ">=0.13.0" - } - }, - "node_modules/@floating-ui/vue/node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "node": ">=10" }, "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" + "tailwindcss": "^3.0 || ^4.0" + } + }, + "node_modules/@headlessui/vue": { + "version": "1.7.23", + "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.7.23.tgz", + "integrity": "sha512-JzdCNqurrtuu0YW6QaDtR2PIYCKPUWq28csDyMvN4zmGccmE7lz40Is6hc3LA4HFeCI7sekZ/PQMTNmn9I/4Wg==", + "license": "MIT", + "dependencies": { + "@tanstack/vue-virtual": "^3.0.0-beta.60" }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "vue": "^3.2.0" } }, "node_modules/@humanfs/core": { @@ -2624,22 +2604,25 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@internationalized/date": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.2.tgz", - "integrity": "sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" - } + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" }, - "node_modules/@internationalized/number": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.3.tgz", - "integrity": "sha512-p+Zh1sb6EfrfVaS86jlHGQ9HA66fJhV9x5LiE5vCbZtXEHAuhcmUZUdZ4WrFpUBfNalr2OkAJI5AcKEQF+Lebw==", - "license": "Apache-2.0", + "node_modules/@iconify/vue": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@iconify/vue/-/vue-4.3.0.tgz", + "integrity": "sha512-Xq0h6zMrHBbrW8jXJ9fISi+x8oDQllg5hTDkDuxnWiskJ63rpJu9CvJshj8VniHVTbsxCg9fVoPAaNp3RQI5OQ==", + "license": "MIT", "dependencies": { - "@swc/helpers": "^0.5.0" + "@iconify/types": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/cyberalien" + }, + "peerDependencies": { + "vue": ">=3" } }, "node_modules/@intlify/bundle-utils": { @@ -2841,24 +2824,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@mdx-js/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", - "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" - } - }, "node_modules/@modelcontextprotocol/sdk": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz", @@ -3935,274 +3900,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@storybook/addon-docs": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.0.2.tgz", - "integrity": "sha512-u5k1em9e8RAO5tiH6pD7AGsPw3m1pm8sQPlZksVDrpH9pDjpbZ5qUTr106yIRd7ftpWbYYdQDUBtSvdnv93BNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@mdx-js/react": "^3.0.0", - "@storybook/csf-plugin": "9.0.2", - "@storybook/icons": "^1.2.12", - "@storybook/react-dom-shim": "9.0.2", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^9.0.2" - } - }, - "node_modules/@storybook/addon-onboarding": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-9.0.2.tgz", - "integrity": "sha512-Uk5EQ+dpkw+4lEtoYRTqG9KXWsClFykYnTd+a3iEVZ49VT+TrD6d2xpIFesZ7BwZ2IeAzPmVU0LiWmzp/Jkt0A==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^9.0.2" - } - }, - "node_modules/@storybook/builder-vite": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-9.0.2.tgz", - "integrity": "sha512-SFLMKqVnLHNtbgI0ACnyNdrY6pgveVxQ8uf2AdHcUBav5wsGRTaC8Q09lSG/4TfNW5EZxZeoTiJB0AmPGm5tLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@storybook/csf-plugin": "9.0.2", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^9.0.2", - "vite": "^5.0.0 || ^6.0.0" - } - }, - "node_modules/@storybook/csf-plugin": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.0.2.tgz", - "integrity": "sha512-Bsq0nnixy9q5vdoQ2O1HkdBZyUhrdkBElooH7a8g9Fy4DOBg+/Sv62o9liAfb4i++NVsd4WAnLKqNqilCoEsAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "unplugin": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^9.0.2" - } - }, "node_modules/@storybook/global": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", "dev": true, - "license": "MIT" - }, - "node_modules/@storybook/icons": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.4.0.tgz", - "integrity": "sha512-Td73IeJxOyalzvjQL+JXx72jlIYHgs+REaHiREOqfpo3A2AYYG71AUbcv+lg7mEDIweKVCxsMQ0UKo634c8XeA==", - "dev": true, "license": "MIT", - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" - } - }, - "node_modules/@storybook/react-dom-shim": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.0.2.tgz", - "integrity": "sha512-DvhHKwMgbkDbDsdU9gZApu2oicrxupqLw6mpOX5PRwVRiWD5g+D9HSIngqFQxfVq5L3ygAQu/HquSUhNuym7yw==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^9.0.2" - } - }, - "node_modules/@storybook/vue3": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@storybook/vue3/-/vue3-9.0.2.tgz", - "integrity": "sha512-FtZQePbZqQMeTfK/mlfBWu3VHFgTabinNmlc5rCqA/nA6rYrVV/bQ5zWt07si6KdREyZ/HCNoAKxgCbqZ0Bacw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@storybook/global": "^5.0.0", - "type-fest": "~2.19", - "vue-component-type-helpers": "latest" - }, - "engines": { - "node": ">=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^9.0.2", - "vue": "^3.0.0" - } - }, - "node_modules/@storybook/vue3-vite": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@storybook/vue3-vite/-/vue3-vite-9.0.2.tgz", - "integrity": "sha512-6TPbZsaI9x1/gfif/UjezGEGqJW6M7vsV8EBtZ276UQ2klwoyeDIzMF1tC0kNZyMh57JjwlL5e+/w/5PlciQFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@storybook/builder-vite": "9.0.2", - "@storybook/vue3": "9.0.2", - "find-package-json": "^1.2.0", - "magic-string": "^0.30.0", - "typescript": "^5.8.3", - "vue-component-meta": "^2.0.0", - "vue-docgen-api": "^4.75.1" - }, - "engines": { - "node": ">=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^9.0.2", - "vite": "^5.0.0 || ^6.0.0" - } - }, - "node_modules/@storybook/vue3/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==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@supabase/auth-js": { - "version": "2.69.1", - "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.69.1.tgz", - "integrity": "sha512-FILtt5WjCNzmReeRLq5wRs3iShwmnWgBvxHfqapC/VoljJl+W8hDAyFmf1NVw3zH+ZjZ05AKxiKxVeb0HNWRMQ==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "^2.6.14" - } - }, - "node_modules/@supabase/functions-js": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.4.tgz", - "integrity": "sha512-WL2p6r4AXNGwop7iwvul2BvOtuJ1YQy8EbOd0dhG1oN1q8el/BIRSFCFnWAMM/vJJlHWLi4ad22sKbKr9mvjoA==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "^2.6.14" - } - }, - "node_modules/@supabase/node-fetch": { - "version": "2.6.15", - "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", - "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/@supabase/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/@supabase/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/@supabase/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/@supabase/postgrest-js": { - "version": "1.19.4", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.19.4.tgz", - "integrity": "sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "^2.6.14" - } - }, - "node_modules/@supabase/realtime-js": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.11.2.tgz", - "integrity": "sha512-u/XeuL2Y0QEhXSoIPZZwR6wMXgB+RQbJzG9VErA3VghVt7uRfSVsjeqd7m5GhX3JR6dM/WRmLbVR8URpDWG4+w==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "^2.6.14", - "@types/phoenix": "^1.5.4", - "@types/ws": "^8.5.10", - "ws": "^8.18.0" - } - }, - "node_modules/@supabase/storage-js": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.7.1.tgz", - "integrity": "sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "^2.6.14" - } - }, - "node_modules/@supabase/supabase-js": { - "version": "2.49.4", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.49.4.tgz", - "integrity": "sha512-jUF0uRUmS8BKt37t01qaZ88H9yV1mbGYnqLeuFWLcdV+x1P4fl0yP9DGtaEhFPZcwSom7u16GkLEH9QJZOqOkw==", - "license": "MIT", - "dependencies": { - "@supabase/auth-js": "2.69.1", - "@supabase/functions-js": "2.4.4", - "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "1.19.4", - "@supabase/realtime-js": "2.11.2", - "@supabase/storage-js": "2.7.1" - } + "peer": true }, "node_modules/@surma/rollup-plugin-off-main-thread": { "version": "2.2.3", @@ -4227,13 +3931,47 @@ "sourcemap-codec": "^1.4.8" } }, - "node_modules/@swc/helpers": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", - "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", - "license": "Apache-2.0", + "node_modules/@tailwindcss/forms": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz", + "integrity": "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.8.0" + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", + "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" } }, "node_modules/@tanstack/virtual-core": { @@ -4289,6 +4027,7 @@ "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", @@ -4310,6 +4049,7 @@ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4323,7 +4063,8 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@testing-library/user-event": { "version": "14.6.1", @@ -4331,6 +4072,7 @@ "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12", "npm": ">=6" @@ -4387,28 +4129,16 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "22.15.17", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, - "node_modules/@types/phoenix": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", - "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==", - "license": "MIT" - }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -4416,17 +4146,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/react": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz", - "integrity": "sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "csstype": "^3.0.2" - } - }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -4454,15 +4173,6 @@ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", "license": "MIT" }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.32.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", @@ -5343,6 +5053,34 @@ "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, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "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, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -5350,24 +5088,13 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/aria-hidden": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", - "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "dequal": "^2.0.3" } @@ -5411,20 +5138,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true, - "license": "MIT" - }, - "node_modules/assert-never": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.4.0.tgz", - "integrity": "sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==", - "dev": true, - "license": "MIT" - }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -5441,6 +5154,7 @@ "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.0.1" }, @@ -5481,6 +5195,44 @@ "node": ">= 4.0.0" } }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -5560,19 +5312,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-walk": { - "version": "3.0.0-canary-5", - "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", - "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.9.6" - }, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -5586,6 +5325,7 @@ "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "open": "^8.0.4" }, @@ -5599,6 +5339,7 @@ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -5609,6 +5350,7 @@ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "is-docker": "cli.js" }, @@ -5625,6 +5367,7 @@ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -5638,6 +5381,7 @@ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -5650,6 +5394,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/birpc": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.3.0.tgz", @@ -5844,6 +5601,16 @@ "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, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001718", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", @@ -5899,16 +5666,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/character-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", - "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-regex": "^1.0.3" - } - }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", @@ -6011,17 +5768,6 @@ "proto-list": "~1.2.1" } }, - "node_modules/constantinople": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", - "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.1" - } - }, "node_modules/content-disposition": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", @@ -6145,7 +5891,8 @@ "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/cssesc": { "version": "3.0.0", @@ -6396,12 +6143,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "license": "MIT" - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -6427,6 +6168,7 @@ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -6445,10 +6187,17 @@ "node": ">=0.10" } }, - "node_modules/doctypes": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", - "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "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, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "dev": true, "license": "MIT" }, @@ -6769,6 +6518,7 @@ "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "debug": "^4.3.4" }, @@ -6999,6 +6749,23 @@ "storybook": "^9.0.2" } }, + "node_modules/eslint-plugin-tailwindcss": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.18.0.tgz", + "integrity": "sha512-PQDU4ZMzFH0eb2DrfHPpbgo87Zgg2EXSMOj1NSfzdZm+aJzpuwGerfowMIaVehSREEa0idbf/eoNYAOHSJoDAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.5", + "postcss": "^8.4.4" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "tailwindcss": "^3.4.0" + } + }, "node_modules/eslint-plugin-vue": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.0.1.tgz", @@ -7088,13 +6855,6 @@ "node": "*" } }, - "node_modules/esm-resolve": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/esm-resolve/-/esm-resolve-1.0.11.tgz", - "integrity": "sha512-LxF0wfUQm3ldUDHkkV2MIbvvY0TgzIpJ420jHSV1Dm+IlplBEWiJTKWM61GtxUfvjV6iD4OtTYFGAGM2uuIUWg==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/espree": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", @@ -7489,13 +7249,6 @@ "node": ">= 0.8" } }, - "node_modules/find-package-json": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/find-package-json/-/find-package-json-1.2.0.tgz", - "integrity": "sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==", - "dev": true, - "license": "MIT" - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -7633,31 +7386,18 @@ "node": ">= 0.6" } }, - "node_modules/framer-motion": { - "version": "12.16.0", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.16.0.tgz", - "integrity": "sha512-xryrmD4jSBQrS2IkMdcTmiS4aSKckbS7kLDCuhUn9110SQKG1w3zlq1RTqCblewg+ZYe+m3sdtzQA6cRwo5g8Q==", + "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, "license": "MIT", - "dependencies": { - "motion-dom": "^12.16.0", - "motion-utils": "^12.12.1", - "tslib": "^2.4.0" + "engines": { + "node": "*" }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" } }, "node_modules/fresh": { @@ -8005,13 +7745,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hash-sum": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", - "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", - "dev": true, - "license": "MIT" - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -8183,6 +7916,7 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -8292,6 +8026,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", @@ -8389,30 +8136,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-expression": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", - "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^7.1.1", - "object-assign": "^4.1.1" - } - }, - "node_modules/is-expression/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -8908,13 +8631,6 @@ "node": ">=14" } }, - "node_modules/js-stringify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", - "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", - "dev": true, - "license": "MIT" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9114,24 +8830,6 @@ "node": ">=0.10.0" } }, - "node_modules/jstransformer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", - "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-promise": "^2.0.0", - "promise": "^7.0.1" - } - }, - "node_modules/jstransformer/node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, - "license": "MIT" - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -9182,6 +8880,26 @@ "immediate": "~3.0.5" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "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, + "license": "MIT" + }, "node_modules/localforage": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", @@ -9214,6 +8932,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -9221,6 +8946,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -9363,10 +9095,21 @@ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=4" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "license": "MIT", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -9411,47 +9154,6 @@ "ufo": "^1.5.4" } }, - "node_modules/motion": { - "version": "12.15.0", - "resolved": "https://registry.npmjs.org/motion/-/motion-12.15.0.tgz", - "integrity": "sha512-HLouXyIb1uQFiZgJTYGrtEzbatPc6vK+HP+Qt6afLQjaudiGiLLVsoy71CwzD/Stlh06FUd5OpyiXqn6XvqjqQ==", - "license": "MIT", - "dependencies": { - "framer-motion": "^12.15.0", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/motion-dom": { - "version": "12.16.0", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.16.0.tgz", - "integrity": "sha512-Z2nGwWrrdH4egLEtgYMCEN4V2qQt1qxlKy/uV7w691ztyA41Q5Rbn0KNGbsNVDZr9E8PD2IOQ3hSccRnB6xWzw==", - "license": "MIT", - "dependencies": { - "motion-utils": "^12.12.1" - } - }, - "node_modules/motion-utils": { - "version": "12.12.1", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.12.1.tgz", - "integrity": "sha512-f9qiqUHm7hWSLlNW8gS9pisnsN7CRFRD58vNjptKdsqFLpkVnX00TNeD6Q0d27V9KzT7ySFyK1TZ/DShfVOv6w==", - "license": "MIT" - }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -9476,6 +9178,18 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -9542,6 +9256,26 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-normalize-package-bin": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", @@ -9678,6 +9412,16 @@ "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, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -9721,12 +9465,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "license": "MIT" - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -10046,6 +9784,16 @@ "node": ">=0.10" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pinia": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.2.tgz", @@ -10067,6 +9815,16 @@ } } }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/pkce-challenge": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", @@ -10158,6 +9916,106 @@ "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, + "license": "MIT", + "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, + "license": "MIT", + "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": "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" + } + ], + "license": "MIT", + "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/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, "node_modules/postcss-selector-parser": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", @@ -10172,6 +10030,13 @@ "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, + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -10281,16 +10146,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "asap": "~2.0.3" - } - }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -10318,142 +10173,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, - "node_modules/pug": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", - "integrity": "sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pug-code-gen": "^3.0.3", - "pug-filters": "^4.0.0", - "pug-lexer": "^5.0.1", - "pug-linker": "^4.0.0", - "pug-load": "^3.0.0", - "pug-parser": "^6.0.0", - "pug-runtime": "^3.0.1", - "pug-strip-comments": "^2.0.0" - } - }, - "node_modules/pug-attrs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", - "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", - "dev": true, - "license": "MIT", - "dependencies": { - "constantinople": "^4.0.1", - "js-stringify": "^1.0.2", - "pug-runtime": "^3.0.0" - } - }, - "node_modules/pug-code-gen": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.3.tgz", - "integrity": "sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==", - "dev": true, - "license": "MIT", - "dependencies": { - "constantinople": "^4.0.1", - "doctypes": "^1.1.0", - "js-stringify": "^1.0.2", - "pug-attrs": "^3.0.0", - "pug-error": "^2.1.0", - "pug-runtime": "^3.0.1", - "void-elements": "^3.1.0", - "with": "^7.0.0" - } - }, - "node_modules/pug-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz", - "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==", - "dev": true, - "license": "MIT" - }, - "node_modules/pug-filters": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", - "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "constantinople": "^4.0.1", - "jstransformer": "1.0.0", - "pug-error": "^2.0.0", - "pug-walk": "^2.0.0", - "resolve": "^1.15.1" - } - }, - "node_modules/pug-lexer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", - "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", - "dev": true, - "license": "MIT", - "dependencies": { - "character-parser": "^2.2.0", - "is-expression": "^4.0.0", - "pug-error": "^2.0.0" - } - }, - "node_modules/pug-linker": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", - "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pug-error": "^2.0.0", - "pug-walk": "^2.0.0" - } - }, - "node_modules/pug-load": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", - "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4.1.1", - "pug-walk": "^2.0.0" - } - }, - "node_modules/pug-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", - "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pug-error": "^2.0.0", - "token-stream": "1.0.0" - } - }, - "node_modules/pug-runtime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", - "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", - "dev": true, - "license": "MIT" - }, - "node_modules/pug-strip-comments": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", - "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "pug-error": "^2.0.0" - } - }, - "node_modules/pug-walk": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", - "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", - "dev": true, - "license": "MIT" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -10536,29 +10255,6 @@ "node": ">= 0.8" } }, - "node_modules/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "scheduler": "^0.26.0" - }, - "peerDependencies": { - "react": "^19.1.0" - } - }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -10567,6 +10263,16 @@ "license": "MIT", "peer": true }, + "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, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, "node_modules/read-package-json-fast": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", @@ -10601,6 +10307,7 @@ "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", @@ -10618,6 +10325,7 @@ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" @@ -10741,63 +10449,6 @@ "node": ">=6" } }, - "node_modules/reka-ui": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.3.1.tgz", - "integrity": "sha512-2SjGeybd7jvD8EQUkzjgg7GdOQdf4cTwdVMq/lDNTMqneUFNnryGO43dg8WaM/jaG9QpSCZBvstfBFWlDdb2Zg==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.6.13", - "@floating-ui/vue": "^1.1.6", - "@internationalized/date": "^3.5.0", - "@internationalized/number": "^3.5.0", - "@tanstack/vue-virtual": "^3.12.0", - "@vueuse/core": "^12.5.0", - "@vueuse/shared": "^12.5.0", - "aria-hidden": "^1.2.4", - "defu": "^6.1.4", - "ohash": "^2.0.11" - }, - "peerDependencies": { - "vue": ">= 3.2.0" - } - }, - "node_modules/reka-ui/node_modules/@vueuse/core": { - "version": "12.8.2", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz", - "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", - "license": "MIT", - "dependencies": { - "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "12.8.2", - "@vueuse/shared": "12.8.2", - "vue": "^3.5.13" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/reka-ui/node_modules/@vueuse/metadata": { - "version": "12.8.2", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz", - "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/reka-ui/node_modules/@vueuse/shared": { - "version": "12.8.2", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz", - "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", - "license": "MIT", - "dependencies": { - "vue": "^3.5.13" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -11074,13 +10725,6 @@ "node": ">=v12.22.7" } }, - "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "devOptional": true, - "license": "MIT" - }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", @@ -11432,6 +11076,7 @@ "integrity": "sha512-SSAg3WABHua4n0w4cCVZ0VDVDJrliAZ4zluRH6e4prpp7BjfPwBm6qtJjeDvXKG92WrOlkeU3DQiY+sBhdEQMA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@storybook/global": "^5.0.0", "@testing-library/jest-dom": "^6.6.3", @@ -11467,6 +11112,7 @@ "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/spy": "3.0.9", "@vitest/utils": "3.0.9", @@ -11483,6 +11129,7 @@ "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tinyrainbow": "^2.0.0" }, @@ -11496,6 +11143,7 @@ "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tinyspy": "^3.0.2" }, @@ -11509,6 +11157,7 @@ "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/pretty-format": "3.0.9", "loupe": "^3.1.3", @@ -11753,6 +11402,7 @@ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "min-indent": "^1.0.0" }, @@ -11773,6 +11423,39 @@ "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, + "license": "MIT", + "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/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/superjson": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", @@ -11835,6 +11518,105 @@ "url": "https://opencollective.com/synckit" } }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tailwindcss/node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwindcss/node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/tailwindcss/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -11916,12 +11698,36 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tinybench": { "version": "2.9.0", @@ -12055,13 +11861,6 @@ "node": ">=0.6" } }, - "node_modules/token-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", - "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", - "dev": true, - "license": "MIT" - }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -12111,27 +11910,18 @@ "typescript": ">=4.8.4" } }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "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, - "license": "MIT", - "engines": { - "node": ">=6.10" - } - }, - "node_modules/ts-map": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-map/-/ts-map-1.0.3.tgz", - "integrity": "sha512-vDWbsl26LIcPGmDpoVzjEP6+hvHZkBkLW7JpvwbCv/5IYPJlsbzCVXY3wsCeAxAUeTclNOUZxnLdGh3VBD/J6w==", - "dev": true, - "license": "MIT" + "license": "Apache-2.0" }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, "license": "0BSD" }, "node_modules/type-check": { @@ -12319,6 +12109,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -12825,16 +12616,6 @@ } } }, - "node_modules/void-elements": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/vscode-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", @@ -12863,27 +12644,6 @@ } } }, - "node_modules/vue-component-meta": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/vue-component-meta/-/vue-component-meta-2.2.10.tgz", - "integrity": "sha512-awylfiFFx/RFJKnu424R+btiGBEJgHa1RdJqb7SrbF5OKNYrL4VWkq49Fgvs/YbCsGSwVOjSl4em/mwOlrQ8/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/typescript": "~2.4.11", - "@vue/language-core": "2.2.10", - "path-browserify": "^1.0.1", - "vue-component-type-helpers": "2.2.10" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/vue-component-type-helpers": { "version": "2.2.10", "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.2.10.tgz", @@ -12891,40 +12651,6 @@ "dev": true, "license": "MIT" }, - "node_modules/vue-docgen-api": { - "version": "4.79.2", - "resolved": "https://registry.npmjs.org/vue-docgen-api/-/vue-docgen-api-4.79.2.tgz", - "integrity": "sha512-n9ENAcs+40awPZMsas7STqjkZiVlIjxIKgiJr5rSohDP0/JCrD9VtlzNojafsA1MChm/hz2h3PDtUedx3lbgfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", - "@vue/compiler-dom": "^3.2.0", - "@vue/compiler-sfc": "^3.2.0", - "ast-types": "^0.16.1", - "esm-resolve": "^1.0.8", - "hash-sum": "^2.0.0", - "lru-cache": "^8.0.3", - "pug": "^3.0.2", - "recast": "^0.23.1", - "ts-map": "^1.0.3", - "vue-inbrowser-compiler-independent-utils": "^4.69.0" - }, - "peerDependencies": { - "vue": ">=2" - } - }, - "node_modules/vue-docgen-api/node_modules/lru-cache": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16.14" - } - }, "node_modules/vue-eslint-parser": { "version": "10.1.3", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.3.tgz", @@ -12989,16 +12715,6 @@ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "license": "MIT" }, - "node_modules/vue-inbrowser-compiler-independent-utils": { - "version": "4.71.1", - "resolved": "https://registry.npmjs.org/vue-inbrowser-compiler-independent-utils/-/vue-inbrowser-compiler-independent-utils-4.71.1.tgz", - "integrity": "sha512-K3wt3iVmNGaFEOUR4JIThQRWfqokxLfnPslD41FDZB2ajXp789+wCqJyGYlIFsvEQ2P61PInw6/ph5iiqg51gg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "vue": ">=2" - } - }, "node_modules/vue-router": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", @@ -13248,22 +12964,6 @@ "node": ">=8" } }, - "node_modules/with": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", - "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.9.6", - "@babel/types": "^7.9.6", - "assert-never": "^1.2.1", - "babel-walk": "3.0.0-canary-5" - }, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -13840,6 +13540,7 @@ "version": "8.18.2", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/fe/package.json b/fe/package.json index 2e57d57..5bb2ad3 100644 --- a/fe/package.json +++ b/fe/package.json @@ -10,7 +10,7 @@ "test:unit": "vitest", "test:e2e": "playwright test", "build-only": "vite build", - "type-check": "vue-tsc --build", + "type-check": "vue-tsc --noEmit", "lint:oxlint": "oxlint . --fix -D correctness --ignore-path .gitignore", "lint:eslint": "eslint . --fix", "lint": "run-s lint:*", @@ -19,18 +19,15 @@ "build-storybook": "storybook build" }, "dependencies": { + "@headlessui/vue": "^1.7.23", + "@iconify/vue": "^4.1.1", "@sentry/tracing": "^7.120.3", "@sentry/vue": "^7.120.3", - "@supabase/auth-js": "^2.69.1", - "@supabase/supabase-js": "^2.49.4", "@vueuse/core": "^13.1.0", "axios": "^1.9.0", "date-fns": "^4.1.0", - "framer-motion": "^12.16.0", - "motion": "^12.15.0", "pinia": "^3.0.2", "qs": "^6.14.0", - "reka-ui": "^2.3.1", "vue": "^3.5.13", "vue-i18n": "^9.9.1", "vue-router": "^4.5.1", @@ -38,11 +35,11 @@ "workbox-background-sync": "^7.3.0" }, "devDependencies": { + "@headlessui/tailwindcss": "^0.2.2", "@intlify/unplugin-vue-i18n": "^4.0.0", "@playwright/test": "^1.51.1", - "@storybook/addon-docs": "^9.0.2", - "@storybook/addon-onboarding": "^9.0.2", - "@storybook/vue3-vite": "^9.0.2", + "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/typography": "^0.5.10", "@tsconfig/node22": "^22.0.1", "@types/date-fns": "^2.5.3", "@types/jsdom": "^21.1.7", @@ -54,18 +51,21 @@ "@vue/eslint-config-typescript": "^14.5.0", "@vue/test-utils": "^2.4.6", "@vue/tsconfig": "^0.7.0", + "autoprefixer": "^10.4.16", "eslint": "^9.26.0", "eslint-plugin-oxlint": "^0.16.0", "eslint-plugin-playwright": "^2.2.0", "eslint-plugin-storybook": "^9.0.2", + "eslint-plugin-tailwindcss": "^3.13.0", "eslint-plugin-vue": "~10.0.0", "jiti": "^2.4.2", "jsdom": "^26.0.0", "npm-run-all2": "^7.0.2", "oxlint": "^0.16.0", + "postcss": "^8.4.34", "prettier": "^3.5.3", "sass": "^1.88.0", - "storybook": "^9.0.2", + "tailwindcss": "^3.4.4", "typescript": "~5.8.0", "vite": "^6.2.4", "vite-plugin-pwa": "^1.0.0", diff --git a/fe/postcss.config.cjs b/fe/postcss.config.cjs new file mode 100644 index 0000000..37fa4f2 --- /dev/null +++ b/fe/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; \ No newline at end of file diff --git a/fe/src/App.vue b/fe/src/App.vue index b343612..03562d1 100644 --- a/fe/src/App.vue +++ b/fe/src/App.vue @@ -9,22 +9,4 @@ import NotificationDisplay from '@/components/global/NotificationDisplay.vue'; // import { useOfflineStore } from './stores/offline'; // const offlineStore = useOfflineStore(); // offlineStore.init(); // If you move init logic here - - - \ No newline at end of file + \ No newline at end of file diff --git a/fe/src/assets/base.css b/fe/src/assets/base.css new file mode 100644 index 0000000..598f8d8 --- /dev/null +++ b/fe/src/assets/base.css @@ -0,0 +1,9 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + body { + @apply bg-light text-dark font-hand antialiased; + } +} \ No newline at end of file diff --git a/fe/src/assets/main.scss b/fe/src/assets/main.scss deleted file mode 100644 index 893a981..0000000 --- a/fe/src/assets/main.scss +++ /dev/null @@ -1,96 +0,0 @@ -// src/assets/main.scss -// @import './variables.scss'; // Your custom variables -@use './valerie-ui.scss'; - -// Example global styles -body { - font-family: sans-serif; - margin: 0; - background-color: var(--bg-color-page, #f4f4f8); - color: var(--text-color, #333); -} - -a { - color: var(--primary-color); - text-decoration: none; - - &:hover { - text-decoration: underline; - } -} - -.container { - max-width: 1200px; - margin: 0 auto; - padding: 1rem; -} - -// Offline UI styles -.offline-item { - position: relative; - opacity: 0.8; - transition: opacity 0.3s ease; - - &::after { - content: ''; - position: absolute; - top: 0.5rem; - right: 0.5rem; - width: 1rem; - height: 1rem; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8'/%3E%3Cpath d='M3 3v5h5'/%3E%3Cpath d='M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16'/%3E%3Cpath d='M16 21h5v-5'/%3E%3C/svg%3E"); - background-size: contain; - background-repeat: no-repeat; - animation: spin 1s linear infinite; - } - - &.synced { - opacity: 1; - - &::after { - display: none; - } - } -} - -@keyframes spin { - from { - transform: rotate(0deg); - } - - to { - transform: rotate(360deg); - } -} - -// Disabled offline features -.feature-offline-disabled { - position: relative; - cursor: not-allowed; - opacity: 0.6; - - &::before { - content: attr(data-tooltip); - position: absolute; - bottom: 100%; - left: 50%; - transform: translateX(-50%); - padding: 0.5rem; - background-color: var(--bg-color-tooltip, #333); - color: white; - border-radius: 0.25rem; - font-size: 0.875rem; - white-space: nowrap; - opacity: 0; - visibility: hidden; - transition: all 0.2s ease; - z-index: 1000; - } - - &:hover::before { - opacity: 1; - visibility: visible; - } -} - -// Add more global utility classes or base styles \ No newline at end of file diff --git a/fe/src/assets/valerie-ui.scss b/fe/src/assets/valerie-ui.scss deleted file mode 100644 index b2d5539..0000000 --- a/fe/src/assets/valerie-ui.scss +++ /dev/null @@ -1,1750 +0,0 @@ -:root { - /* Colors */ - --primary: #ff7b54; - --secondary: #ffb26b; - --accent: #ffd56b; - /* Yellow - for sticky notes */ - --secondary-accent: #54c7ff; - /* Light Blue - for contrast */ - --danger: #ff4d4d; - --success: #a0e7a0; - --warning: var(--accent); - --dark: #393e46; - --light: #fff8f0; - --black: #000000; - - /* Shadows & Borders */ - --shadow-lg: 8px 8px 0px var(--black); - --shadow-md: 6px 6px 0px var(--black); - --shadow-sm: 3px 3px 0px var(--black); - --shadow-inset: inset 2px 2px 1px rgba(0, 0, 0, 0.15); - --border-width: 3px; - --border-style: solid; - --border-color: var(--black); - --border: var(--border-width) var(--border-style) var(--border-color); - - /* Transitions */ - --transition-speed: 0.25s; - --transition-speed-fast: 0.1s; - --transition-ease-out: ease-out; - --transition-press: cubic-bezier(0.34, 1.56, 0.64, 1); - - /* Focus */ - --focus-outline-color: var(--secondary-accent); - --focus-outline-width: 3px; - --focus-outline-offset: 2px; - --focus-outline: var(--focus-outline-width) solid var(--focus-outline-color); - - /* Textures */ - --paper-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23a59a8a' fill-opacity='0.15'%3E%3Cpath opacity='.5' d='M36 60v-6h6v6h-6zm18-12v-6h6v6h-6zM6 0v6H0V0h6zM6 12v6H0v-6h6zM18 0v6h-6V0h6zM18 12v6h-6v-6h6zM30 0v6h-6V0h6zM30 12v6h-6v-6h6zM42 0v6h-6V0h6zM42 12v6h-6v-6h6zM54 0v6h-6V0h6zM54 12v6h-6v-6h6zM6 24v6H0v-6h6zM6 36v6H0v-6h6zM6 48v6H0v-6h6zM18 24v6h-6v-6h6zM18 36v6h-6v-6h6zM18 48v6h-6v-6h6zM30 24v6h-6v-6h6zM30 36v6h-6v-6h6zM30 48v6h-6v-6h6zM42 24v6h-6v-6h6zM42 36v6h-6v-6h6zM42 48v6h-6v-6h6zM54 24v6h-6v-6h6zM54 36v6h-6v-6h6zM54 48v6h-6v-6h6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); - --progress-texture: repeating-linear-gradient(45deg, - rgba(0, 0, 0, 0.05), - rgba(0, 0, 0, 0.05) 5px, - transparent 5px, - transparent 10px); -} - -/* Accessibility Helpers */ -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; -} - -/* Reduced Motion Preference */ -@media (prefers-reduced-motion: reduce) { - - *, - *::before, - *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - scroll-behavior: auto !important; - transition-delay: 0ms !important; - } -} - -/* Basic Reset & Body */ -*, -*::before, -*::after { - box-sizing: border-box; -} - -body { - font-family: 'Patrick Hand', cursive; - background-color: var(--light); - // background-image: var(--paper-texture); - // background-image: url('@/assets/11.webp'); - // padding: 2rem 1rem;s - color: var(--dark); - font-size: 1.1rem; - line-height: 1.6; - overflow-x: hidden; - /* Prevent horizontal scroll */ - margin: 0; -} - -.container { - max-width: 1000px; - margin: 0 auto; -} - -/* Focus Visible Styles */ -:is(a, button, input, select, textarea, [tabindex]):not([tabindex='-1']):focus-visible { - outline: var(--focus-outline); - outline-offset: var(--focus-outline-offset); - box-shadow: - 0 0 0 var(--focus-outline-width) var(--focus-outline-color), - var(--shadow-md); - z-index: 10; - /* Bring focused element forward */ -} - -.btn:focus-visible { - box-shadow: - 0 0 0 var(--focus-outline-width) var(--focus-outline-color), - var(--shadow-lg); -} - -.form-input:focus-visible { - box-shadow: - var(--shadow-inset), - 0 0 0 var(--focus-outline-width) var(--focus-outline-color), - var(--shadow-sm); -} - -.list-item:focus-visible { - /* Focus on list item might need adjustment if using swipe */ - outline-offset: -var(--border-width); - z-index: 10; -} - -.tab-item:focus-visible { - outline-offset: 4px; - z-index: 5; - /* Higher than non-focused tabs */ -} - -.checkbox-label input:focus-visible~.checkmark, -.radio-label input:focus-visible~.checkmark { - outline: var(--focus-outline); - outline-offset: var(--focus-outline-offset); - box-shadow: - var(--shadow-sm), - 0 0 0 var(--focus-outline-width) var(--focus-outline-color); -} - -.switch-container input:focus-visible+.switch { - outline: var(--focus-outline); - outline-offset: var(--focus-outline-offset); -} - -.avatar:focus-visible { - box-shadow: - 0 0 0 var(--focus-outline-width) var(--focus-outline-color), - var(--shadow-sm); -} - -.tooltip .tooltip-trigger:focus-visible { - outline: var(--focus-outline); - outline-offset: var(--focus-outline-offset); -} - -/* Headings */ -h1, -h2, -h3 { - font-weight: bold; - color: var(--dark); - text-transform: uppercase; - letter-spacing: 1.5px; - position: relative; - display: inline-block; - margin-bottom: 1.5rem; - padding-bottom: 8px; -} - -h1::after, -h2::after, -h3::after { - content: ''; - position: absolute; - bottom: 0; - left: 0; - width: 100%; - height: var(--border-width); - background-color: var(--primary); - box-shadow: var(--shadow-sm); -} - -h1 { - font-size: clamp(2rem, 5vw, 2.5rem); -} - -h2 { - font-size: clamp(1.6rem, 4vw, 2rem); -} - -h3 { - font-size: clamp(1.3rem, 3.5vw, 1.5rem); -} - -/* Icon Base Style */ -.icon { - display: inline-block; - width: 1.1em; - height: 1.1em; - vertical-align: -0.15em; - margin-right: 0.4em; - fill: currentColor; -} - -.btn .icon { - margin-right: 0.5em; -} - -button>.icon:last-child { - margin-right: 0; -} - -.icon-sm { - width: 0.9em; - height: 0.9em; -} - -.icon-lg { - width: 1.5em; - height: 1.5em; -} - -/* Buttons */ -.btn { - background-color: var(--primary); - color: var(--dark); - border: var(--border); - font-family: inherit; - font-size: 1rem; - font-weight: bold; - padding: 0.8rem 1.6rem; - cursor: pointer; - box-shadow: var(--shadow-md); - transition: - transform var(--transition-speed) var(--transition-ease-out), - box-shadow var(--transition-speed) var(--transition-ease-out), - background-color var(--transition-speed) var(--transition-ease-out); - position: relative; - text-transform: uppercase; - letter-spacing: 1px; - margin: 0.5rem; - display: inline-flex; - align-items: center; - justify-content: center; - text-decoration: none; - text-align: center; - touch-action: manipulation; - overflow: hidden; -} - -.btn:hover:not(:disabled) { - transform: translate(-3px, -3px); - box-shadow: var(--shadow-lg); -} - -.btn:active:not(:disabled) { - transform: translate(2px, 2px) scale(0.98); - box-shadow: var(--shadow-sm); - transition-duration: var(--transition-speed-fast); - transition-timing-function: var(--transition-press); - animation: jiggle-subtle 0.3s ease-out forwards; -} - -.btn:disabled { - opacity: 0.6; - cursor: not-allowed; - box-shadow: var(--shadow-sm); -} - -.btn-secondary { - background-color: var(--secondary); -} - -.btn-neutral { - background-color: var(--light); - color: var(--dark); -} - -.btn-danger { - background-color: var(--danger); - color: var(--light); -} - -.btn-sm { - padding: 0.5rem 1rem; - font-size: 0.9rem; -} - -.btn-icon-only { - padding: 0.6rem; -} - -.btn-icon-only .icon { - margin-right: 0; -} - -@keyframes jiggle-subtle { - - 0%, - 100% { - transform: translate(2px, 2px) scale(0.98) rotate(0deg); - } - - 25% { - transform: translate(2px, 2px) scale(0.98) rotate(-0.5deg); - } - - 75% { - transform: translate(2px, 2px) scale(0.98) rotate(0.5deg); - } -} - -/* Cards */ -.card { - background-color: var(--light); - border: var(--border); - padding: 1.5rem; - box-shadow: var(--shadow-md); - margin-bottom: 2rem; - position: relative; - /* overflow: hidden; */ - /* REMOVED overflow: hidden which can clip tooltips */ - /* Add transition back if subtle hover is desired, but not transform */ - transition: box-shadow var(--transition-speed) var(--transition-ease-out); -} - -/* Removed .card:hover transform/shadow increase */ -.card::before { - content: ''; - position: absolute; - inset: 0; - background-image: var(--paper-texture); - opacity: 0.6; - z-index: 0; - pointer-events: none; - /* Prevent texture from interfering */ -} - -.card>* { - position: relative; - z-index: 1; - /* Ensure content is above texture */ -} - -.card-header { - margin: -1.5rem -1.5rem 1.5rem -1.5rem; - padding: 1rem 1.5rem; - border-bottom: var(--border); - font-weight: bold; - background-color: rgba(255, 255, 255, 0.5); -} - -.card-body { - margin-bottom: 1rem; -} - -.card-footer { - display: flex; - justify-content: flex-end; - align-items: center; - margin: 1.5rem -1.5rem -1.5rem -1.5rem; - padding: 1rem 1.5rem; - border-top: var(--border); - background-color: rgba(255, 255, 255, 0.5); -} - -/* Empty State Card */ -.empty-state-card { - text-align: center; - padding: 3rem 1.5rem; -} - -.empty-state-card .icon-lg { - display: block; - margin: 0 auto 1rem auto; - width: 50px; - height: 50px; - opacity: 0.5; -} - -.empty-state-card h3 { - border: none; - padding: 0; - margin-bottom: 0.5rem; -} - -.empty-state-card h3::after { - display: none; -} - -.empty-state-card p { - margin-bottom: 1.5rem; - opacity: 0.8; -} - -/* Forms */ -.form-group { - margin-bottom: 1.5rem; -} - -.form-label { - display: block; - margin-bottom: 0.5rem; - font-weight: bold; - color: var(--dark); - text-transform: uppercase; - font-size: 0.9rem; - letter-spacing: 0.5px; -} - -.form-input, -select.form-input, -textarea.form-input { - width: 100%; - padding: 0.75rem; - border: var(--border); - background-color: var(--light); - font-family: inherit; - font-size: 1rem; - box-shadow: var(--shadow-inset), var(--shadow-sm); - transition: - transform var(--transition-speed) var(--transition-ease-out), - box-shadow var(--transition-speed) var(--transition-ease-out), - border-color var(--transition-speed) var(--transition-ease-out); - box-sizing: border-box; - appearance: none; - border-radius: 0; -} - -textarea.form-input { - line-height: 1.5; - min-height: 80px; -} - -select.form-input { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23393e46'%3E%3Cpath d='M7 10l5 5 5-5H7z'/%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: right 0.75rem center; - background-size: 1.5em; - padding-right: 2.5rem; -} - -.form-input:focus { - outline: none; - /* Use focus-visible */ - transform: translate(1px, 1px); - border-color: var(--primary); -} - -.form-input.error { - border-color: var(--danger); - background-color: #ffeeee; -} - -.form-input:disabled { - background-color: rgba(0, 0, 0, 0.05); - opacity: 0.7; - cursor: not-allowed; - box-shadow: var(--shadow-inset); -} - -/* Checkbox & Radio */ -.checkbox-group, -.radio-group { - margin-bottom: 1rem; - background: rgba(0, 0, 0, 0.02); - padding: 0.5rem; - border: 1px solid rgba(0, 0, 0, 0.1); -} - -.checkbox-label, -.radio-label { - position: relative; - padding-left: 2.8rem; - margin-bottom: 0.75rem; - cursor: pointer; - display: flex; - align-items: center; - min-height: 30px; -} - -.checkbox-label input, -.radio-label input { - position: absolute; - opacity: 0; - cursor: pointer; - height: 100%; - width: 100%; - top: 0; - left: 0; - margin: 0; -} - -.checkmark { - position: absolute; - top: 50%; - transform: translateY(-50%); - left: 0.5rem; - height: 28px; - width: 28px; - background-color: var(--light); - border: var(--border); - box-shadow: var(--shadow-sm); - transition: background-color var(--transition-speed) var(--transition-ease-out); - pointer-events: none; -} - -.radio-mark { - border-radius: 50%; -} - -.checkbox-label input:checked~.checkmark:after, -.radio-label input:checked~.checkmark:after { - content: ''; - position: absolute; - display: block; - transform-origin: center center; -} - -.checkbox-label .checkmark:after { - left: 8px; - top: 3px; - width: 7px; - height: 14px; - border: solid var(--black); - border-width: 0 4px 4px 0; - transform: rotate(45deg) scale(0); - animation: checkmark-appear var(--transition-speed) var(--transition-ease-out) forwards; -} - -.radio-label .checkmark:after { - top: 5px; - left: 5px; - width: 12px; - height: 12px; - background-color: var(--black); - border-radius: 50%; - transform: scale(0); - animation: radio-appear var(--transition-speed) var(--transition-ease-out) forwards; -} - -@keyframes checkmark-appear { - 0% { - transform: scale(0) rotate(45deg); - opacity: 0; - } - - 70% { - transform: scale(1.1) rotate(45deg); - opacity: 1; - } - - 100% { - transform: scale(1) rotate(45deg); - opacity: 1; - } -} - -@keyframes radio-appear { - 0% { - transform: scale(0); - opacity: 0; - } - - 70% { - transform: scale(1.1); - opacity: 1; - } - - 100% { - transform: scale(1); - opacity: 1; - } -} - -/* Lists */ -.item-list { - list-style: none; - padding: 0; - margin: 0; -} - -.list-item { - border: var(--border); - padding: 0; - /* Remove padding here, add to content */ - margin-bottom: 1rem; - background-color: var(--light); - box-shadow: var(--shadow-md); - display: flex; - /* Use flex on the outer item */ - align-items: stretch; - /* Stretch children vertically */ - transition: box-shadow var(--transition-speed) var(--transition-ease-out); - position: relative; - overflow: hidden; - /* Needed for swipe actions reveal */ -} - -.list-item::before { - content: ''; - position: absolute; - inset: 0; - background-image: var(--paper-texture); - opacity: 0.4; - z-index: 0; - pointer-events: none; -} - -.list-item.completed .item-text { - text-decoration: line-through; - text-decoration-thickness: 2px; - text-decoration-color: var(--dark); -} - -.list-item.completed { - opacity: 0.7; -} - -/* --- Swipe Functionality Structure --- */ -.list-item-content { - display: flex; - flex-wrap: wrap; - /* Allow wrapping inside content area */ - align-items: center; - padding: 1rem; - /* Add padding here */ - flex-grow: 1; - /* Take available space */ - background-color: var(--light); - /* Ensure bg covers area */ - position: relative; - /* To stay above ::before */ - z-index: 1; - /* Above texture */ - transition: transform 0.3s ease-out; - /* Swipe animation */ - width: 100%; - /* Ensure it takes full width initially */ -} - -.swipe-actions { - position: absolute; - top: 0; - right: 0; - height: 100%; - display: flex; - align-items: stretch; - /* Make buttons fill height */ - z-index: 0; - /* Below content initially */ - transform: translateX(100%); - /* Initially hidden off-screen */ - transition: transform 0.3s ease-out; -} - -.swipe-actions .btn { - height: 100%; - margin: 0; - border-radius: 0; - border-left: var(--border); - /* Separator */ - border-top: none; - border-bottom: none; - border-right: none; - box-shadow: none; - font-size: 0.9rem; - min-width: 80px; - /* Ensure button has width */ -} - -/* State when swiped (JS adds/removes this class) */ -.list-item.is-swiped .list-item-content { - /* Adjust translateX based on desired swipe distance/action width */ - transform: translateX(-160px); - /* Example: width of two buttons */ -} - -.list-item.is-swiped .swipe-actions { - transform: translateX(0); - /* Reveal actions */ -} - -/* -------------------------------------- */ -/* Content layout inside .list-item-content */ -.list-item-main { - /* Wrapper for checkbox and text */ - display: flex; - align-items: center; - flex-grow: 1; - /* Takes up space, pushing details right */ - margin-right: 1rem; - /* Space before details */ - min-width: 150px; - /* Prevent excessive shrinking */ -} - -.list-item .checkbox-label { - flex-shrink: 0; - margin-bottom: 0; -} - -.item-text { - margin-left: 1rem; - flex-grow: 1; - min-width: 50px; -} - -/* Allow text to grow */ -.list-item-details { - /* Wrapper for avatar, badges, actions (non-swipe) */ - display: flex; - align-items: center; - flex-wrap: nowrap; - /* Prevent wrapping of these items */ - flex-shrink: 0; - /* Don't shrink this container */ - margin-left: auto; - /* Push to the right on larger screens */ -} - -.list-item-details>* { - margin-left: 0.5rem; -} - -/* Spacing between items in details */ -.list-item-details> :first-child { - margin-left: 0; -} - -.list-item-details .avatar { - margin: 0; -} - -/* Reset avatar margin */ -.list-item-actions { - /* Non-swipe actions styling */ - display: flex; - align-items: center; - padding-left: 0.5rem; - /* Space before non-swipe actions */ -} - -.list-item-actions .btn { - padding: 0.4rem 0.8rem; - font-size: 0.9rem; - margin: 0 0 0 0.25rem; -} - -/* Badges & Avatars */ -.item-badge { - display: inline-block; - padding: 0.25rem 0.6rem; - background-color: var(--secondary); - border: 2px solid var(--black); - margin: 0.25rem 0; - font-weight: bold; - box-shadow: var(--shadow-sm); - font-size: 0.85rem; - text-transform: uppercase; - flex-shrink: 0; - position: relative; -} - -.badge-accent { - background-color: var(--accent); -} - -.badge-accent.badge-sticky::after { - content: ''; - position: absolute; - bottom: -1px; - right: -1px; - width: 50%; - height: 50%; - background: linear-gradient(135deg, transparent 50%, rgba(0, 0, 0, 0.15) 50%); - transform: skew(-15deg, -15deg) translate(2px, 2px); - filter: blur(1px); - border-bottom-right-radius: 3px; - z-index: -1; - box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.2); -} - -.badge-settled { - background-color: var(--secondary-accent); - color: var(--dark); -} - -.badge-pending { - background-color: var(--warning); - color: var(--dark); -} - -.avatar { - display: inline-flex; - align-items: center; - justify-content: center; - width: 36px; - height: 36px; - border-radius: 50%; - background-color: var(--secondary); - color: var(--dark); - border: 2px solid var(--black); - box-shadow: var(--shadow-sm); - font-weight: bold; - font-size: 1rem; - text-transform: uppercase; - margin: 0.25rem; - flex-shrink: 0; - overflow: hidden; - cursor: default; -} - -.avatar img { - width: 100%; - height: 100%; - object-fit: cover; -} - -/* Tabs */ -.tabs { - // margin-bottom: 2rem; -} - -.tab-list { - display: flex; - flex-wrap: wrap; - list-style: none; - padding: 0; - margin: 0 0 -3px 0; - /* Overlap border */ - position: relative; - z-index: 1; - /* Above content by default */ -} - -.tab-item { - padding: 0.75rem 1.5rem; - background-color: var(--light); - border: var(--border); - border-bottom-color: var(--border-color); - margin-right: 0.5rem; - margin-bottom: 0; - /* Remove bottom margin */ - cursor: pointer; - font-weight: bold; - position: relative; - box-shadow: var(--shadow-sm); - transition: - transform var(--transition-speed) var(--transition-ease-out), - box-shadow var(--transition-speed) var(--transition-ease-out), - background-color var(--transition-speed) var(--transition-ease-out), - color var(--transition-speed) var(--transition-ease-out), - border-color var(--transition-speed) var(--transition-ease-out); - text-transform: uppercase; - letter-spacing: 0.5px; - flex-grow: 0; -} - -.tab-item[aria-selected='true'] { - background-color: var(--primary) !important; - color: var(--dark); - border-color: var(--black); - /* Ensure all borders are black */ - border-bottom-color: var(--primary); - /* Match background to hide border */ - box-shadow: var(--shadow-md); - z-index: 2; - /* Bring active tab forward */ - /* transform: translateY(-3px); REMOVED */ -} - -.tab-item:not([aria-selected='true']):hover { - background-color: var(--secondary) !important; - transform: translateY(-2px); - box-shadow: var(--shadow-md); -} - -.tab-content { - padding: 1.5rem; - border: var(--border); - background-color: var(--light); - box-shadow: var(--shadow-md); - position: relative; - overflow: hidden; - /* Keep hidden for content flow */ - margin-top: -3px; - /* Pull up behind active tab */ - z-index: 0; - /* Ensure content is behind tab list */ -} - -.tab-content[hidden] { - display: none; -} - -.tab-content::before { - content: ''; - position: absolute; - inset: 0; - background-image: var(--paper-texture); - opacity: 0.6; - z-index: 0; - pointer-events: none; -} - -.tab-content>* { - position: relative; - z-index: 1; -} - -/* Modal */ -.modal-backdrop { - position: fixed; - inset: 0; - background-color: rgba(57, 62, 70, 0.9); - /* Increased opacity for better visibility */ - display: flex; - align-items: center; - justify-content: center; - z-index: 9999; - /* Increased z-index to ensure it's above other elements */ - opacity: 0; - visibility: hidden; - transition: - opacity var(--transition-speed) var(--transition-ease-out), - visibility 0s linear var(--transition-speed); -} - -.modal-backdrop.open { - opacity: 1; - visibility: visible; - transition: - opacity var(--transition-speed) var(--transition-ease-out), - visibility 0s linear 0s; -} - -.modal-container { - background-color: var(--light); - border: var(--border); - width: 90%; - max-width: 850px; - box-shadow: var(--shadow-lg); - position: relative; - overflow-y: auto; - /* Changed from scroll to auto */ - transform: scale(0.95) translateY(-20px); - transition: transform var(--transition-speed) var(--transition-ease-out); - max-height: 90vh; - display: flex; - flex-direction: column; - z-index: 10000; - /* Ensure modal content is above backdrop */ -} - -.modal-container::before { - content: ''; - position: absolute; - inset: 0; - background-image: var(--paper-texture); - opacity: 0.6; - z-index: 0; - pointer-events: none; -} - -.modal-backdrop.open .modal-container { - transform: scale(1) translateY(0); -} - -.modal-header { - padding: 1rem 1.5rem; - border-bottom: var(--border); - display: flex; - justify-content: space-between; - align-items: center; - background-color: rgba(255, 255, 255, 0.5); - flex-shrink: 0; - position: relative; - z-index: 1; -} - -.modal-header h3 { - margin-bottom: 0; - padding-bottom: 0; -} - -.modal-header h3::after { - display: none; -} - -.modal-body { - padding: 1.5rem; - overflow-y: auto; - position: relative; - z-index: 1; - flex-grow: 1; -} - -.modal-footer { - padding: 1rem 1.5rem; - border-top: var(--border); - display: flex; - justify-content: flex-end; - background-color: rgba(255, 255, 255, 0.5); - flex-shrink: 0; - position: relative; - z-index: 1; -} - -.close-button { - background: none; - border: none; - font-size: 2rem; - font-weight: bold; - cursor: pointer; - padding: 0; - line-height: 1; - color: var(--dark); - transition: - color var(--transition-speed) var(--transition-ease-out), - transform var(--transition-speed-fast) ease-out; -} - -.close-button .icon { - margin: 0; -} - -.close-button:hover { - color: var(--danger); - transform: scale(1.1); -} - -.modal-container.confirm-modal .modal-body { - text-align: center; -} - -.modal-container.confirm-modal .modal-footer { - justify-content: center; -} - -.modal-container.confirm-modal .icon-lg { - color: var(--danger); - margin-bottom: 1rem; - display: inline-block; -} - -/* Alerts */ -.alert { - padding: 1rem 1.5rem; - margin-bottom: 1.5rem; - border: var(--border); - border-left-width: 6px; - /* Thicker left border */ - box-shadow: var(--shadow-md); - font-weight: bold; - position: relative; - overflow: hidden; - /* Keep overflow for ::before */ - letter-spacing: 0.5px; - display: flex; - align-items: center; - justify-content: space-between; - /* Space out content and close button */ -} - -.alert::before { - content: ''; - position: absolute; - inset: 0; - background-image: var(--paper-texture); - opacity: 0.6; - z-index: 0; - pointer-events: none; -} - -.alert>.alert-content { - /* Wrap main content */ - display: flex; - align-items: center; - flex-grow: 1; - /* Take available space */ - margin-right: 1rem; - /* Space before close button */ - position: relative; - z-index: 1; -} - -.alert .icon { - margin-right: 0.8em; - flex-shrink: 0; -} - -.alert-close-btn { - background: none; - border: none; - color: inherit; - /* Inherit color from alert text */ - opacity: 0.7; - font-size: 1.5rem; - line-height: 1; - padding: 0 0.25rem; - cursor: pointer; - transition: opacity 0.2s ease-out; - flex-shrink: 0; - /* Prevent shrinking */ - position: relative; - z-index: 1; -} - -.alert-close-btn:hover { - opacity: 1; -} - -.alert-close-btn .icon { - margin: 0; -} - -.alert-success { - background-color: var(--success); - color: var(--dark); - border-left-color: hsl(120, 60%, 45%); -} - -/* Darker green border */ -.alert-warning { - background-color: var(--warning); - color: var(--dark); - border-left-color: hsl(45, 100%, 45%); -} - -/* Darker yellow/orange border */ -.alert-error { - background-color: #ffcccc; - border-color: var(--danger); - color: var(--dark); - border-left-color: var(--danger); -} - -.alert-info { - background-color: var(--secondary-accent); - color: var(--dark); - border-left-color: hsl(200, 100%, 45%); -} - -/* Darker blue border */ - -/* Progress Bar */ -.progress-container { - width: 100%; - height: 35px; - background-color: var(--light); - border: var(--border); - box-shadow: var(--shadow-md); - margin-bottom: 1.5rem; - position: relative; - overflow: hidden; -} - -.progress-bar { - height: 100%; - background-color: var(--primary); - position: relative; - transition: width 0.5s var(--transition-ease-out); - background-image: var(--progress-texture); - display: flex; - align-items: center; - justify-content: center; -} - -.progress-text { - position: absolute; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - color: var(--dark); - font-weight: bold; - z-index: 1; - text-shadow: 1px 1px 0px rgba(255, 255, 255, 0.7); - font-size: 0.9rem; - white-space: nowrap; -} - -/* Toggle Switch - Refined */ -.switch-container { - position: relative; - display: inline-block; - width: 64px; - /* Slightly smaller */ - height: 34px; - /* Slightly smaller */ - margin-bottom: 1rem; - vertical-align: middle; -} - -.switch-container input { - position: absolute; - opacity: 0; - width: 100%; - height: 100%; - top: 0; - left: 0; - margin: 0; - cursor: pointer; - z-index: 2; -} - -.switch { - position: absolute; - cursor: pointer; - inset: 0; - background-color: var(--light); - border: var(--border); - /* box-shadow: var(--shadow-inset), var(--shadow-sm); REMOVED - potential conflict */ - box-shadow: var(--shadow-inset); - /* Keep inset shadow only */ - transition: background-color 0.4s var(--transition-ease-out); - pointer-events: none; - z-index: 1; -} - -.switch:before { - position: absolute; - content: ''; - height: 24px; - /* Adjusted size */ - width: 24px; - /* Adjusted size */ - left: 2px; - /* Adjusted position */ - top: 50%; - /* Center vertically */ - background-color: var(--dark); - border: 2px solid var(--light); - box-shadow: var(--shadow-sm); - transition: - transform 0.4s var(--transition-ease-out), - background-color 0.4s var(--transition-ease-out), - border-color 0.4s var(--transition-ease-out); - transform: translateY(-50%); - /* Vertical centering */ -} - -.switch-container input:checked+.switch { - background-color: var(--secondary-accent); -} - -.switch-container input:checked+.switch:before { - background-color: var(--light); - border-color: var(--dark); - /* Width (64) - border*2 (6) - left (2) - width (24) = 32 */ - transform: translate(30px, -50%); - /* Adjusted translation */ -} - -/* Tables */ -.table-container { - overflow-x: auto; - margin-bottom: 1.5rem; - border: var(--border); - box-shadow: var(--shadow-md); - background-color: var(--light); - position: relative; - /* overflow: hidden; */ - /* Can clip tooltips */ -} - -.table-container::before { - content: ''; - position: absolute; - inset: 0; - background-image: var(--paper-texture); - opacity: 0.6; - z-index: 0; - pointer-events: none; -} - -.table { - width: 100%; - border-collapse: collapse; - border-spacing: 0; - position: relative; - z-index: 1; - min-width: 600px; -} - -.table th, -.table td { - padding: 0.8rem 1rem; - text-align: left; - border-bottom: var(--border-width) var(--border-style) var(--border-color); - border-right: 1px dashed rgba(0, 0, 0, 0.1); - white-space: nowrap; - vertical-align: middle; -} - -.table th:last-child, -.table td:last-child { - border-right: none; -} - -.table thead th { - background-color: var(--primary); - color: var(--dark); - text-transform: uppercase; - letter-spacing: 1px; - font-weight: bold; - border-top: none; - border-bottom-width: var(--border-width); - position: sticky; - top: -1px; - z-index: 2; -} - -.table tbody tr:last-child td { - border-bottom: none; -} - -.table tbody tr:hover { - background-color: rgba(255, 178, 107, 0.2); -} - -.table tfoot td { - border-top: var(--border); - font-weight: bold; - background-color: rgba(255, 255, 255, 0.5); - position: sticky; - bottom: -1px; - z-index: 2; -} - -.table .wrap-text { - white-space: normal; -} - -.table .avatar { - width: 30px; - height: 30px; - font-size: 0.9rem; - margin-right: 0.5rem; -} - -/* Utilities */ -.mb-1 { - margin-bottom: 0.5rem !important; -} - -.mb-2 { - margin-bottom: 1rem !important; -} - -.mb-3 { - margin-bottom: 1.5rem !important; -} - -.mb-4 { - margin-bottom: 2rem !important; -} - -.mt-1 { - margin-top: 0.5rem !important; -} - -.mt-2 { - margin-top: 1rem !important; -} - -.mt-3 { - margin-top: 1.5rem !important; -} - -.mt-4 { - margin-top: 2rem !important; -} - -.ml-1 { - margin-left: 0.5rem !important; -} - -.ml-2 { - margin-left: 1rem !important; -} - -.mr-1 { - margin-right: 0.5rem !important; -} - -.mr-2 { - margin-right: 1rem !important; -} - -.text-center { - text-align: center; -} - -.text-right { - text-align: right; -} - -.flex { - display: flex; -} - -.justify-between { - justify-content: space-between; -} - -.justify-end { - justify-content: flex-end; -} - -.justify-center { - justify-content: center; -} - -.items-center { - align-items: center; -} - -.flex-wrap { - flex-wrap: wrap; -} - -.flex-nowrap { - flex-wrap: nowrap; -} - -.flex-grow { - flex-grow: 1; -} - -.flex-shrink-0 { - flex-shrink: 0; -} - -.w-full { - width: 100%; -} - -/* Tooltip */ -.tooltip { - position: relative; - display: inline-block; -} - -.tooltip-trigger { - cursor: help; - border-bottom: 1px dashed var(--dark); -} - -.btn.tooltip-trigger { - border-bottom: none; -} - -.tooltip-text { - visibility: hidden; - opacity: 0; - min-width: 150px; - max-width: 250px; - background-color: var(--dark); - color: var(--light); - text-align: center; - border: 2px solid var(--black); - padding: 0.75rem; - position: absolute; - z-index: 1500; - /* Increased Z-index significantly */ - bottom: 130%; - left: 50%; - transform: translateX(-50%) scale(0.95); - transform-origin: bottom center; - transition: - opacity var(--transition-speed) var(--transition-ease-out), - visibility 0s linear var(--transition-speed), - transform var(--transition-speed) var(--transition-ease-out); - box-shadow: var(--shadow-md); - font-size: 0.9rem; - line-height: 1.4; - pointer-events: none; -} - -/* NOTE on Tooltip Clipping: Tooltips use position:absolute and high z-index. - However, if a PARENT element (like .card, .modal-container, .table-container) - has `overflow: hidden` or `overflow: auto/scroll`, the tooltip WILL BE CLIPPED - by that parent's boundaries, regardless of z-index. - The most reliable fix involves JavaScript to append the tooltip to the document body - when shown, removing it from the parent's clipping context. - This CSS provides structure but cannot overcome parent overflow clipping. */ -.tooltip-text::after { - content: ''; - position: absolute; - top: 100%; - left: 50%; - margin-left: -8px; - border-width: 8px; - border-style: solid; - border-color: var(--dark) transparent transparent transparent; -} - -.tooltip .tooltip-trigger:hover+.tooltip-text, -.tooltip .tooltip-trigger:focus-visible+.tooltip-text, -.tooltip-text.visible { - visibility: visible; - opacity: 1; - transform: translateX(-50%) scale(1); - transition-delay: 0s, 0s, 0s; -} - -/* Spinner - Pulsing Dots */ -.spinner-dots { - display: inline-flex; - /* Use flex for alignment */ - align-items: center; - /* Vertically center dots */ - justify-content: center; - width: auto; - /* Adjust width based on content */ - height: 50px; - /* Match old spinner height or adjust */ -} - -.spinner-dots span { - display: inline-block; - width: 12px; - height: 12px; - margin: 0 4px; - /* Spacing between dots */ - background-color: var(--primary); - border-radius: 50%; - box-shadow: var(--shadow-sm); - animation: pulse-dot 1.2s infinite ease-in-out both; -} - -.spinner-dots span:nth-child(1) { - animation-delay: -0.32s; -} - -.spinner-dots span:nth-child(2) { - animation-delay: -0.16s; -} - -.spinner-dots span:nth-child(3) { - animation-delay: 0s; -} - -@keyframes pulse-dot { - - 0%, - 80%, - 100% { - transform: scale(0.8); - opacity: 0.5; - } - - 40% { - transform: scale(1.1); - opacity: 1; - } -} - -/* Small spinner dots */ -.spinner-dots-sm { - height: 30px; -} - -/* Adjust height */ -.spinner-dots-sm span { - width: 8px; - height: 8px; - margin: 0 3px; - box-shadow: var(--shadow-sm); -} - -.btn .spinner-dots-sm { - height: auto; - vertical-align: middle; - margin: 0 0.5em; -} - -/* Spinner inside button */ -.btn .spinner-dots-sm span { - background-color: currentColor; -} - -/* Match button text color */ - -/* Responsive */ -@media (max-width: 768px) { - body { - padding: 1rem; - font-size: 1rem; - } - - .card, - .modal-container, - .tab-content { - padding: 1rem; - } - - .card-header, - .card-footer, - .modal-header, - .modal-footer { - padding: 0.75rem 1rem; - margin-left: -1rem; - margin-right: -1rem; - } - - .card-header { - margin-top: -1rem; - margin-bottom: 1rem; - } - - .card-footer { - margin-bottom: -1rem; - margin-top: 1rem; - } - - .modal-header { - margin-top: -1rem; - margin-bottom: 1rem; - } - - .modal-footer { - margin-bottom: -1rem; - margin-top: 1rem; - } - - .modal-footer .btn { - margin: 0.25rem; - } - - /* Tabs on mobile */ - .tab-list { - margin-bottom: -3px; - /* Adjust for border width */ - } - - .tab-item { - flex-grow: 1; - margin-right: 0; - text-align: center; - border-left: none; - border-right: none; - border-bottom-width: var(--border-width); - } - - .tab-item:not(:last-child) { - border-right: var(--border); - } - - .tab-item[aria-selected='true'] { - border-bottom-color: var(--primary); - margin-bottom: 0; - /* No longer needs negative margin */ - z-index: 2; - } - - .tab-content { - margin-top: -3px; - } - - /* List items on mobile */ - .list-item-content { - flex-direction: column; - align-items: flex-start; - } - - .list-item-main { - margin-right: 0; - width: 100%; - margin-bottom: 0.5rem; - } - - .list-item-details { - margin-left: 0; - margin-top: 0.5rem; - flex-wrap: wrap; - /* Allow badges/avatar wrap on mobile */ - } - - .list-item-details>* { - margin-left: 0; - margin-right: 0.5rem; - margin-bottom: 0.25rem; - } - - /* Adjust spacing for wrap */ - .list-item-actions { - /* Non-swipe actions */ - width: 100%; - justify-content: flex-end; - margin-top: 0.5rem; - padding-left: 0; - } - - /* Adjust swipe reveal distance if needed for mobile */ - .list-item.is-swiped .list-item-content { - transform: translateX(-120px); - } - - /* Example smaller distance */ - - .table { - min-width: unset; - } - - .table thead th { - top: -1px; - } - - .table tfoot td { - bottom: -1px; - } - - .table th, - .table td { - padding: 0.6rem 0.5rem; - font-size: 0.9rem; - white-space: normal; - } - - .flex-layout-stack-mobile { - flex-direction: column; - } - - .flex-layout-stack-mobile>.card { - width: 100% !important; - margin: 0 0 1.5rem 0 !important; - flex-basis: auto !important; - } - - .form-row-wrap-mobile { - flex-direction: column; - } - - .form-row-wrap-mobile>.form-group { - margin-right: 0 !important; - width: 100%; - } - - .form-row-wrap-mobile>.form-group:not(:last-child) { - margin-bottom: 1.5rem; - } -} \ No newline at end of file diff --git a/fe/src/assets/variables.scss b/fe/src/assets/variables.scss deleted file mode 100644 index ec3c3f3..0000000 --- a/fe/src/assets/variables.scss +++ /dev/null @@ -1,21 +0,0 @@ -// src/assets/variables.scss -:root { - --primary-color: #1976D2; - --secondary-color: #26A69A; - --accent-color: #9C27B0; - - --dark-color: #1D1D1D; - --dark-page-color: #121212; - - --positive-color: #21BA45; - --negative-color: #C10015; - --info-color: #31CCEC; - --warning-color: #F2C037; - - --text-color: #333; - --bg-color: #fff; - --bg-color-page: #f0f2f5; - - --header-height: 56px; - --footer-height: 56px; -} \ No newline at end of file diff --git a/fe/src/components/BaseIcon.vue b/fe/src/components/BaseIcon.vue new file mode 100644 index 0000000..3fcb16e --- /dev/null +++ b/fe/src/components/BaseIcon.vue @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/fe/src/components/ChoreItem.vue b/fe/src/components/ChoreItem.vue index 783bc0e..f78f8ec 100644 --- a/fe/src/components/ChoreItem.vue +++ b/fe/src/components/ChoreItem.vue @@ -29,19 +29,20 @@
@@ -62,6 +63,7 @@ import { formatDistanceToNow, parseISO, isToday, isPast } from 'date-fns'; import type { ChoreWithCompletion } from '../types/chore'; import type { TimeEntry } from '../stores/timeEntryStore'; import { formatDuration } from '../utils/formatters'; +import BaseIcon from './BaseIcon.vue'; const props = defineProps<{ chore: ChoreWithCompletion; diff --git a/fe/src/components/ui/Button.vue b/fe/src/components/ui/Button.vue new file mode 100644 index 0000000..c8b4af0 --- /dev/null +++ b/fe/src/components/ui/Button.vue @@ -0,0 +1,73 @@ + + + \ No newline at end of file diff --git a/fe/src/components/ui/Dialog.vue b/fe/src/components/ui/Dialog.vue new file mode 100644 index 0000000..d1cd4e4 --- /dev/null +++ b/fe/src/components/ui/Dialog.vue @@ -0,0 +1,36 @@ + + + \ No newline at end of file diff --git a/fe/src/components/ui/Listbox.vue b/fe/src/components/ui/Listbox.vue new file mode 100644 index 0000000..e51bb18 --- /dev/null +++ b/fe/src/components/ui/Listbox.vue @@ -0,0 +1,27 @@ + + + \ No newline at end of file diff --git a/fe/src/components/ui/Menu.vue b/fe/src/components/ui/Menu.vue new file mode 100644 index 0000000..bc48b25 --- /dev/null +++ b/fe/src/components/ui/Menu.vue @@ -0,0 +1,17 @@ + + + \ No newline at end of file diff --git a/fe/src/components/ui/Switch.vue b/fe/src/components/ui/Switch.vue new file mode 100644 index 0000000..39ddd3e --- /dev/null +++ b/fe/src/components/ui/Switch.vue @@ -0,0 +1,27 @@ + + + \ No newline at end of file diff --git a/fe/src/components/ui/Tabs.vue b/fe/src/components/ui/Tabs.vue new file mode 100644 index 0000000..0d13ec1 --- /dev/null +++ b/fe/src/components/ui/Tabs.vue @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/fe/src/components/ui/TransitionExpand.vue b/fe/src/components/ui/TransitionExpand.vue new file mode 100644 index 0000000..c5965c6 --- /dev/null +++ b/fe/src/components/ui/TransitionExpand.vue @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/fe/src/components/ui/__tests__/Button.spec.ts b/fe/src/components/ui/__tests__/Button.spec.ts new file mode 100644 index 0000000..f5d8fc8 --- /dev/null +++ b/fe/src/components/ui/__tests__/Button.spec.ts @@ -0,0 +1,35 @@ +import { mount } from '@vue/test-utils' +import Button from '../Button.vue' +import { describe, it, expect } from 'vitest' + +describe('Button.vue', () => { + it('renders default (solid primary md) styles', () => { + const wrapper = mount(Button, { + slots: { default: 'Click Me' }, + }) + expect(wrapper.text()).toBe('Click Me') + const cls = wrapper.attributes('class') + expect(cls).toContain('bg-primary') + expect(cls).toContain('px-4') // md size padding + }) + + it('renders outline success variant', () => { + const wrapper = mount(Button, { + props: { variant: 'outline', color: 'success' }, + slots: { default: 'Save' }, + }) + const cls = wrapper.attributes('class') + expect(cls).toContain('border-success') + expect(cls).toContain('text-success') + }) + + it('renders ghost danger lg size', () => { + const wrapper = mount(Button, { + props: { variant: 'ghost', color: 'danger', size: 'lg' }, + slots: { default: 'Delete' }, + }) + const cls = wrapper.attributes('class') + expect(cls).toContain('text-danger') + expect(cls).toContain('px-6') // lg size padding + }) +}) \ No newline at end of file diff --git a/fe/src/components/ui/__tests__/Dialog.spec.ts b/fe/src/components/ui/__tests__/Dialog.spec.ts new file mode 100644 index 0000000..30716d7 --- /dev/null +++ b/fe/src/components/ui/__tests__/Dialog.spec.ts @@ -0,0 +1,22 @@ +import { mount } from '@vue/test-utils' +import Dialog from '../Dialog.vue' +import { describe, it, expect } from 'vitest' + +describe('Dialog.vue', () => { + it('renders slot content when open', () => { + const wrapper = mount(Dialog, { + props: { modelValue: true }, + slots: { default: '

Hello

' }, + }) + expect(wrapper.find('[data-test="content"]').exists()).toBe(true) + }) + + it('does not render when closed', () => { + const wrapper = mount(Dialog, { + props: { modelValue: false }, + slots: { default: '

Hidden

' }, + }) + // Should not render content + expect(wrapper.html()).toBe('') + }) +}) \ No newline at end of file diff --git a/fe/src/components/ui/__tests__/Listbox.spec.ts b/fe/src/components/ui/__tests__/Listbox.spec.ts new file mode 100644 index 0000000..f6e282b --- /dev/null +++ b/fe/src/components/ui/__tests__/Listbox.spec.ts @@ -0,0 +1,23 @@ +import { mount } from '@vue/test-utils' +import { describe, it, expect } from 'vitest' +import Listbox from '../Listbox.vue' + +const Option = { + template: '
{{ value }}
', + props: ['value'], +} + +describe('Listbox.vue', () => { + it('emits update when option selected', async () => { + const wrapper = mount(Listbox, { + props: { modelValue: 'one' }, + slots: { + button: '', + default: '
one
', + }, + }) + await wrapper.find('[data-test="toggle"]').trigger('click') + // The selection event is internal; basic mount test + expect(wrapper.find('[data-test="toggle"]').exists()).toBe(true) + }) +}) \ No newline at end of file diff --git a/fe/src/components/ui/__tests__/Menu.spec.ts b/fe/src/components/ui/__tests__/Menu.spec.ts new file mode 100644 index 0000000..f5b0c21 --- /dev/null +++ b/fe/src/components/ui/__tests__/Menu.spec.ts @@ -0,0 +1,20 @@ +import { mount } from '@vue/test-utils' +import { describe, it, expect } from 'vitest' +import Menu from '../Menu.vue' + +// Provide a minimal menu item component for slot +const MenuItemStub = { + template: '
Item
', +} + +describe('Menu.vue', () => { + it('renders menu button slot', () => { + const wrapper = mount(Menu, { + slots: { + button: '', + default: MenuItemStub, + }, + }) + expect(wrapper.find('[data-test="trigger"]').exists()).toBe(true) + }) +}) \ No newline at end of file diff --git a/fe/src/components/ui/__tests__/Switch.spec.ts b/fe/src/components/ui/__tests__/Switch.spec.ts new file mode 100644 index 0000000..2c434e5 --- /dev/null +++ b/fe/src/components/ui/__tests__/Switch.spec.ts @@ -0,0 +1,14 @@ +import { mount } from '@vue/test-utils' +import UISwitch from '../Switch.vue' +import { describe, it, expect } from 'vitest' + +describe('Switch.vue', () => { + it('emits update:modelValue when toggled', async () => { + const wrapper = mount(UISwitch, { + props: { modelValue: false }, + }) + // the headlessui switch renders a button element + await wrapper.find('button').trigger('click') + expect(wrapper.emitted()['update:modelValue']).toBeTruthy() + }) +}) \ No newline at end of file diff --git a/fe/src/components/ui/__tests__/Tabs.spec.ts b/fe/src/components/ui/__tests__/Tabs.spec.ts new file mode 100644 index 0000000..6fdd707 --- /dev/null +++ b/fe/src/components/ui/__tests__/Tabs.spec.ts @@ -0,0 +1,16 @@ +import { mount } from '@vue/test-utils' +import { describe, it, expect } from 'vitest' +import Tabs from '../Tabs.vue' + +describe('Tabs.vue', () => { + it('renders tabs and panels', () => { + const wrapper = mount(Tabs, { + slots: { + tabs: '', + default: '
Panel 1
', + }, + }) + expect(wrapper.text()).toContain('Tab 1') + expect(wrapper.text()).toContain('Panel 1') + }) +}) \ No newline at end of file diff --git a/fe/src/components/ui/__tests__/TransitionExpand.spec.ts b/fe/src/components/ui/__tests__/TransitionExpand.spec.ts new file mode 100644 index 0000000..3713bbb --- /dev/null +++ b/fe/src/components/ui/__tests__/TransitionExpand.spec.ts @@ -0,0 +1,14 @@ +import { mount } from '@vue/test-utils' +import { describe, it, expect } from 'vitest' +import TransitionExpand from '../TransitionExpand.vue' + +describe('TransitionExpand.vue', () => { + it('renders slot content', () => { + const wrapper = mount(TransitionExpand, { + slots: { + default: '

Hello

', + }, + }) + expect(wrapper.find('[data-test="content"]').exists()).toBe(true) + }) +}) \ No newline at end of file diff --git a/fe/src/components/ui/index.ts b/fe/src/components/ui/index.ts new file mode 100644 index 0000000..ac1cf7a --- /dev/null +++ b/fe/src/components/ui/index.ts @@ -0,0 +1,7 @@ +export { default as Button } from './Button.vue' +export { default as Dialog } from './Dialog.vue' +export { default as Menu } from './Menu.vue' +export { default as Listbox } from './Listbox.vue' +export { default as Tabs } from './Tabs.vue' +export { default as Switch } from './Switch.vue' +export { default as TransitionExpand } from './TransitionExpand.vue' \ No newline at end of file diff --git a/fe/src/main.ts b/fe/src/main.ts index b8f6b2b..4b4f4df 100644 --- a/fe/src/main.ts +++ b/fe/src/main.ts @@ -10,7 +10,7 @@ import deMessages from './i18n/de.json' import frMessages from './i18n/fr.json' import esMessages from './i18n/es.json' import nlMessages from './i18n/nl.json' -import './assets/main.scss' +import './assets/base.css' import { api, globalAxios } from '@/services/api' import { useAuthStore } from '@/stores/auth' diff --git a/fe/src/pages/ChoresPage.vue b/fe/src/pages/ChoresPage.vue index ae6cb7e..c0f7b35 100644 --- a/fe/src/pages/ChoresPage.vue +++ b/fe/src/pages/ChoresPage.vue @@ -12,6 +12,7 @@ import { useTimeEntryStore, type TimeEntry } from '../stores/timeEntryStore'; import { storeToRefs } from 'pinia'; import { useAuthStore } from '@/stores/auth'; import type { UserPublic } from '@/types/user'; +import BaseIcon from '@/components/BaseIcon.vue'; const { t } = useI18n() @@ -679,7 +680,7 @@ const getAssignmentIdForUser = (userId: number): number | null => {
+ }}
@@ -700,14 +701,14 @@ const getAssignmentIdForUser = (userId: number): number | null => {
+ }}
+ }}
Loading members...
@@ -780,7 +781,7 @@ const getAssignmentIdForUser = (userId: number): number | null => {
Created by: {{ selectedChore.creator?.name || selectedChore.creator?.email || 'Unknown' - }} + }}
Due date: @@ -812,9 +813,14 @@ const getAssignmentIdForUser = (userId: number): number | null => {
{{ assignment.assigned_user?.name || assignment.assigned_user?.email - }} - - {{ assignment.is_complete ? 'βœ… Completed' : '⏳ Pending' }} + }} + + +
diff --git a/fe/tailwind.config.ts b/fe/tailwind.config.ts new file mode 100644 index 0000000..0fde93d --- /dev/null +++ b/fe/tailwind.config.ts @@ -0,0 +1,49 @@ +// @ts-nocheck +import type { Config } from 'tailwindcss' +import forms from '@tailwindcss/forms' +import typography from '@tailwindcss/typography' +import headlessui from '@headlessui/tailwindcss' + +const config: Config = { + darkMode: 'class', + content: [ + './index.html', + './src/**/*.{vue,js,ts,jsx,tsx}', + ], + theme: { + extend: { + colors: { + primary: '#FF7B54', + secondary: '#FFB26B', + accent: '#FFD56B', + info: '#54C7FF', + success: '#A0E7A0', + warning: '#FFD56B', + danger: '#FF4D4D', + dark: '#393E46', + light: '#FFF8F0', + black: '#000000', + neutral: '#64748B', + }, + spacing: { + 1: '4px', + 4: '16px', + 6: '24px', + 8: '32px', + 12: '48px', + 16: '64px', + }, + fontFamily: { + hand: ['"Patrick Hand"', 'cursive'], + sans: ['Inter', 'ui-sans-serif', 'system-ui'], + }, + }, + }, + plugins: [ + forms, + typography, + headlessui({ prefix: 'ui' }), + ], +} + +export default config \ No newline at end of file diff --git a/fe/tsconfig.vitest.json b/fe/tsconfig.vitest.json index 7d1d8ce..c659d05 100644 --- a/fe/tsconfig.vitest.json +++ b/fe/tsconfig.vitest.json @@ -1,11 +1,17 @@ { "extends": "./tsconfig.app.json", - "include": ["src/**/__tests__/*", "env.d.ts"], + "include": [ + "src/**/__tests__/*", + "env.d.ts" + ], "exclude": [], "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", - "lib": [], - "types": ["node", "jsdom"] + "types": [ + "node", + "jsdom", + "vitest" + ] } -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..eac072c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "doe", + "lockfileVersion": 3, + "requires": true, + "packages": {} +}