-
-
{{ v }}
+
+
+
+
+
+
+ Page de demo introuvable: .playground/pages/composant/{{ selectedDemoFileName }}.vue
+
+
+
Playground composants
+
+ Selectionne un composant dans la liste pour afficher sa page de demo.
+
+
+
+type LoadedModule = {
+ default: unknown
+}
+type Item = {
+ name: string
+ label: string
+ demoComponent?: unknown
+}
+
+const componentModules = import.meta.glob('../../app/components/malio/*.vue', { eager: true }) as Record
+const demoModules = import.meta.glob('./composant/*.vue', { eager: true }) as Record
+
+const demoByName = Object.fromEntries(
+ Object.entries(demoModules).map(([file, mod]) => {
+ const name = file.split('/').pop()?.replace('.vue', '') ?? ''
+ return [name.toLowerCase(), mod.default]
+ }),
+)
+
+const items = computed(() =>
+ Object.entries(componentModules).map(([file]) => {
+ const name = file.split('/').pop()?.replace('.vue', '') ?? ''
+
+ return {
+ name,
+ label: name,
+ demoComponent: demoByName[name.toLowerCase()],
+ }
+ }) as Item[],
+)
+
+const selectedName = ref('')
+const hasInitializedSelection = ref(false)
+
+watchEffect(() => {
+ if (!hasInitializedSelection.value && items.value.length > 0) {
+ selectedName.value = items.value[0].name
+ hasInitializedSelection.value = true
+ }
+})
+
+function selectOrToggle(name: string) {
+ selectedName.value = selectedName.value === name ? '' : name
+}
+
+function clearSelection() {
+ selectedName.value = ''
+}
+
+const selectedDemoComponent = computed(() =>
+ items.value.find((item) => item.name === selectedName.value)?.demoComponent,
+)
+
+const selectedDemoFileName = computed(() => {
+ const name = selectedName.value
+ if (!name) return ''
+ return name.charAt(0).toLowerCase() + name.slice(1)
+})
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f230edc..4b688f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ Liste des évolutions de la librairie Malio layer UI
### Parameters
### Added
+* [#333] Création d'un composant text
### Changed
diff --git a/app/assets/css/malio.css b/app/assets/css/malio.css
new file mode 100644
index 0000000..0fa1352
--- /dev/null
+++ b/app/assets/css/malio.css
@@ -0,0 +1,19 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ /* Couleurs en RGB “space separated” pour Tailwind */
+ --m-primary: 34 39 131; /* Couleur principal*/
+ --m-secondary: 48 73 152; /* Couleur secondaire */
+ --m-tertiary: 243 244 248; /* Couleur tertiaire (background) */
+ --m-border: 203 213 225; /* Couleur des bordures */
+ --m-text: 15 23 42; /* Couleur du texte */
+ --m-muted: 100 116 139; /* Couleur pour les éléments désactivés ou secondaires */
+ --m-bg: 243 244 248; /* Couleur de fond générale */
+
+ --m-error: 155 17 30; /* rouge pour les erreurs */
+ --m-success: 15 149 70; /* vert pour les succès */
+ }
+}
diff --git a/app/components/malio/Input.test.ts b/app/components/malio/Input.test.ts
index aefc9fb..ccb7ba1 100644
--- a/app/components/malio/Input.test.ts
+++ b/app/components/malio/Input.test.ts
@@ -1,23 +1,319 @@
-import { describe, expect, it } from 'vitest'
-import { mount } from '@vue/test-utils'
-import Input from './Input.vue'
+import {describe, expect, it} from 'vitest'
+import {config, mount} from '@vue/test-utils'
+import type {DefineComponent} from 'vue'
+import Input from './InputText.vue'
+
+
+type InputProps = {
+ id?: string
+ label?: string
+ name?: string
+ autocomplete?: string
+ modelValue?: string | null
+ textSize?: string
+ labelClass?: string
+ required?: boolean
+ maxLength?: number | string
+ minLength?: number | string
+ disabled?: boolean
+ readonly?: boolean
+ hint?: string
+ error?: string
+ success?: string
+ iconName?: string
+ iconSize?: string | number
+ iconColor?: string
+}
+
+const InputForTest = Input as DefineComponent
+const iconStub = {
+ template: '',
+}
+config.global.stubs = {
+ ...(config.global.stubs ?? {}),
+ Icon: iconStub,
+}
describe('MalioInput', () => {
- it('affiche la valeur initiale', () => {
- const wrapper = mount(Input, {
- props: { modelValue: 'hello' },
+ // Props de base: valeur, label, name, id, autocomplete
+ it('renders the initial input value', () => {
+ const wrapper = mount(InputForTest, {
+ props: {modelValue: 'initialValueTest'},
})
-
- expect(wrapper.get('input').element.value).toBe('hello')
+ expect(wrapper.get('input').element.value).toBe('initialValueTest')
})
- it('emet update:modelValue au changement', async () => {
- const wrapper = mount(Input, {
- props: { modelValue: '' },
+ it('renders the label text', () => {
+ const wrapper = mount(InputForTest, {
+ props: {label: 'labelTest'},
})
+ expect(wrapper.get('label').text()).toBe('labelTest')
+ })
+ it('applies the name attribute', () => {
+ const wrapper = mount(InputForTest, {
+ props: {name: 'nameTest'},
+ })
+ expect(wrapper.get('input').attributes('name')).toBe('nameTest')
+ })
+
+ it('uses provided id on input and label', () => {
+ const wrapper = mount(InputForTest, {
+ props: {id: 'custom-id', label: 'Label'},
+ })
+ expect(wrapper.get('input').attributes('id')).toBe('custom-id')
+ expect(wrapper.get('label').attributes('for')).toBe('custom-id')
+ })
+
+ it('applies a different size of rounded', () => {
+ const wrapper = mount(InputForTest, {
+ props: {rounded: 'rounded-md'},
+ })
+ expect(wrapper.get('input').classes()).toContain('rounded-md')
+ })
+
+ it('generates an id when missing and reuses it on label', () => {
+ const wrapper = mount(InputForTest, {
+ props: {label: 'Label'},
+ })
+ const inputId = wrapper.get('input').attributes('id')
+ expect(inputId).toBeDefined()
+ expect(inputId?.startsWith('malio-input-text-')).toBe(true)
+ expect(wrapper.get('label').attributes('for')).toBe(inputId)
+ })
+
+ it('applies the autocomplete attribute', () => {
+ const wrapper = mount(InputForTest, {
+ props: {autocomplete: 'autocompleteTest'},
+ })
+ expect(wrapper.get('input').attributes('autocomplete')).toBe('autocompleteTest')
+ })
+
+ // États HTML: required, readonly, disabled
+ it('does not set required when false', () => {
+ const wrapper = mount(InputForTest, {
+ props: {required: false},
+ })
+ expect(wrapper.get('input').attributes('required')).toBeUndefined()
+ })
+
+ it('sets required when true', () => {
+ const wrapper = mount(InputForTest, {
+ props: {required: true},
+ })
+ expect(wrapper.get('input').attributes('required')).toBeDefined()
+ })
+
+ it('does not set readonly when false', () => {
+ const wrapper = mount(InputForTest, {
+ props: {readonly: false},
+ })
+ expect(wrapper.get('input').attributes('readonly')).toBeUndefined()
+ })
+
+ it('sets readonly when true', () => {
+ const wrapper = mount(InputForTest, {
+ props: {readonly: true},
+ })
+ expect(wrapper.get('input').attributes('readonly')).toBeDefined()
+ })
+
+ it('does not set disabled and keeps text cursor when false', () => {
+ const wrapper = mount(InputForTest, {
+ props: {disabled: false},
+ })
+ expect(wrapper.get('input').attributes('disabled')).toBeUndefined()
+ expect(wrapper.get('input').classes()).toContain('cursor-text')
+ })
+
+ it('sets disabled styles when true', () => {
+ const wrapper = mount(InputForTest, {
+ props: {disabled: true},
+ })
+ expect(wrapper.get('input').attributes('disabled')).toBeDefined()
+ expect(wrapper.get('input').classes()).toContain('cursor-not-allowed')
+ expect(wrapper.get('input').classes()).toContain('text-black/60')
+ })
+
+ // Émission d'événements
+ it('emits update:modelValue on input change', async () => {
+ const wrapper = mount(InputForTest, {
+ props: {modelValue: ''},
+ })
await wrapper.get('input').setValue('new value')
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['new value'])
})
+
+ // Contraintes et classes de texte
+ it('applies maxLength to input', () => {
+ const wrapper = mount(InputForTest, {
+ props: {maxLength: 25},
+ })
+ expect(wrapper.get('input').attributes('maxlength')).toBe('25')
+ })
+
+ it('applies minLength to input', () => {
+ const wrapper = mount(InputForTest, {
+ props: {minLength: 25},
+ })
+ expect(wrapper.get('input').attributes('minlength')).toBe('25')
+ })
+
+ it('applies textSize class on label', () => {
+ const wrapper = mount(InputForTest, {
+ props: {label: 'Label', textLabel: 'text-sm'},
+ })
+ expect(wrapper.get('label').classes()).toContain('text-sm')
+ })
+
+ // États visuels: erreur et succès
+ it('shows error message without label and icon', () => {
+ const wrapper = mount(InputForTest, {
+ props: {error: 'Error message test'},
+ })
+ expect(wrapper.get('p.text-m-error').text()).toBe('Error message test')
+ expect(wrapper.get('input').classes()).toContain('border-m-error')
+ expect(wrapper.get('p').classes()).toContain('text-m-error')
+ })
+
+ it('shows error message with label and without icon', () => {
+ const wrapper = mount(InputForTest, {
+ props: {error: 'Error message test', label: 'Error message'},
+ })
+ expect(wrapper.get('p.text-m-error').text()).toBe('Error message test')
+ expect(wrapper.get('input').classes()).toContain('border-m-error')
+ expect(wrapper.get('label').classes()).toContain('text-m-error')
+ expect(wrapper.get('label').classes()).toContain('text-m-error')
+ expect(wrapper.get('label').classes()).toContain('text-m-error')
+ expect(wrapper.get('p').classes()).toContain('text-m-error')
+
+ })
+
+ it('shows error message with label and icon', () => {
+ const wrapper = mount(InputForTest, {
+ props: {error: 'Error message test', label: 'Error message', iconName: 'mdi:key-outline'},
+ })
+ expect(wrapper.get('p.text-m-error').text()).toBe('Error message test')
+ expect(wrapper.get('input').classes()).toContain('border-m-error')
+ expect(wrapper.get('label').classes()).toContain('text-m-error')
+ expect(wrapper.get('label').classes()).toContain('text-m-error')
+ expect(wrapper.get('label').classes()).toContain('text-m-error')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-m-error')
+ expect(wrapper.get('p').classes()).toContain('text-m-error')
+
+ })
+
+ it('shows error message with icon and without label', () => {
+ const wrapper = mount(InputForTest, {
+ props: {error: 'Error message test', iconName: 'mdi:key-outline'},
+ })
+ expect(wrapper.get('p.text-m-error').text()).toBe('Error message test')
+ expect(wrapper.get('input').classes()).toContain('border-m-error')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-m-error')
+ })
+
+ it('shows success message without label and icon', () => {
+ const wrapper = mount(InputForTest, {
+ props: {success: 'Success message test'},
+ })
+ expect(wrapper.get('p.text-m-success').text()).toBe('Success message test')
+ expect(wrapper.get('input').classes()).toContain('border-m-success')
+ })
+
+ it('shows success message with label and without icon', () => {
+ const wrapper = mount(InputForTest, {
+ props: {success: 'Success message test', label: 'Success message'},
+ })
+ expect(wrapper.get('p.text-m-success').text()).toBe('Success message test')
+ expect(wrapper.get('input').classes()).toContain('border-m-success')
+ expect(wrapper.get('label').classes()).toContain('text-m-success')
+ expect(wrapper.get('label').classes()).toContain('text-m-success')
+ expect(wrapper.get('label').classes()).toContain('text-m-success')
+ })
+
+ it('shows success message with label and icon', () => {
+ const wrapper = mount(InputForTest, {
+ props: {success: 'Success message test', label: 'Success message', iconName: 'mdi:key-outline'},
+ })
+ expect(wrapper.get('p.text-m-success').text()).toBe('Success message test')
+ expect(wrapper.get('input').classes()).toContain('border-m-success')
+ expect(wrapper.get('label').classes()).toContain('text-m-success')
+ expect(wrapper.get('label').classes()).toContain('text-m-success')
+ expect(wrapper.get('label').classes()).toContain('text-m-success')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-m-success')
+ })
+
+ it('shows success message with icon and without label', () => {
+ const wrapper = mount(InputForTest, {
+ props: {success: 'Success message test', iconName: 'mdi:key-outline'},
+ })
+ expect(wrapper.get('p.text-m-success').text()).toBe('Success message test')
+ expect(wrapper.get('input').classes()).toContain('border-m-success')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-m-success')
+ })
+
+ it('prioritizes error over success when both are provided', () => {
+ const wrapper = mount(InputForTest, {
+ props: {
+ error: 'Error message test',
+ success: 'Success message test',
+ },
+ })
+ expect(wrapper.find('p.text-m-error').exists()).toBe(true)
+ expect(wrapper.get('p.text-m-error').text()).toBe('Error message test')
+ expect(wrapper.find('p.text-m-success').exists()).toBe(false)
+ expect(wrapper.get('input').classes()).toContain('border-m-error')
+ expect(wrapper.get('input').classes()).not.toContain('border-m-success')
+ })
+
+ // Aide et classes de label
+ it('shows hint message', () => {
+ const wrapper = mount(InputForTest, {
+ props: {hint: 'Hint message test'},
+ })
+ expect(wrapper.get('p.text-m-muted').text()).toBe('Hint message test')
+ })
+
+ it('applies labelClass on label', () => {
+ const wrapper = mount(InputForTest, {
+ props: {label: 'Label', labelClass: 'text-red-500'},
+ })
+ expect(wrapper.get('label').classes()).toContain('text-red-500')
+ })
+
+ it('does not render label when label prop is missing', () => {
+ const wrapper = mount(InputForTest, {
+ props: {labelClass: 'text-red-500'},
+ })
+
+ expect(wrapper.find('label').exists()).toBe(false)
+ })
+
+ // Icône : rendu et options
+ it('renders icon with default positioning and muted color', () => {
+ const wrapper = mount(InputForTest, {
+ props: {iconName: 'mdi:key-outline'},
+ })
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-m-muted')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('pointer-events-none')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('absolute')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('right-2')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('top-1/2')
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('-translate-y-1/2')
+ })
+
+ it('passes icon size prop to icon component', () => {
+ const wrapper = mount(InputForTest, {
+ props: {iconName: 'mdi:key-outline', iconSize: '24'},
+ })
+ expect(wrapper.get('[data-test="icon"]').attributes('height')).toBe('24')
+ })
+
+ it('applies icon color class', () => {
+ const wrapper = mount(InputForTest, {
+ props: {iconName: 'mdi:key-outline', iconColor: 'text-m-primary'},
+ })
+ expect(wrapper.get('[data-test="icon"]').classes()).toContain('text-m-primary')
+ })
})
diff --git a/app/components/malio/Input.vue b/app/components/malio/Input.vue
deleted file mode 100644
index 17119af..0000000
--- a/app/components/malio/Input.vue
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/components/malio/InputText.vue b/app/components/malio/InputText.vue
new file mode 100644
index 0000000..c6e4da2
--- /dev/null
+++ b/app/components/malio/InputText.vue
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+ {{ hint || error || success }}
+
+
+
+
+
+
diff --git a/nuxt.config.ts b/nuxt.config.ts
index daa8552..a9302c3 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -1,9 +1,34 @@
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
-const currentDir = dirname(fileURLToPath(import.meta.url))
+const dir = dirname(fileURLToPath(import.meta.url))
export default defineNuxtConfig({
- modules: ['@nuxtjs/tailwindcss'],
- css: [join(currentDir, './app/assets/css/tailwind.css')],
+ modules: ['@nuxtjs/tailwindcss','@nuxt/icon'],
+ css: [join(dir, 'app/assets/css/malio.css')],
+
+ tailwindcss: {
+ config: {
+ theme: {
+ extend: {
+ borderRadius: {
+ malio: 'var(--m-radius)',
+ },
+ colors: {
+ m: {
+ primary: 'rgb(var(--m-primary) / )',
+ secondary: 'rgb(var(--m-secondary) / )',
+ tertiary: 'rgb(var(--m-tertiary) / )',
+ border: 'rgb(var(--m-border) / )',
+ text: 'rgb(var(--m-text) / )',
+ muted: 'rgb(var(--m-muted) / )',
+ bg: 'rgb(var(--m-bg) / )',
+ error: 'rgb(var(--m-error) / )',
+ success: 'rgb(var(--m-success) / )',
+ }
+ }
+ }
+ }
+ }
+ }
})
diff --git a/package-lock.json b/package-lock.json
index b6bae17..80f38b4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,7 +8,9 @@
"name": "@malio/layer-ui",
"version": "0.0.1",
"dependencies": {
- "@nuxtjs/tailwindcss": "^6.14.0"
+ "@nuxt/icon": "^2.2.1",
+ "@nuxtjs/tailwindcss": "^6.14.0",
+ "maska": "^3.2.0"
},
"devDependencies": {
"@nuxt/eslint": "latest",
@@ -49,7 +51,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz",
"integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"package-manager-detector": "^1.3.0",
@@ -403,7 +404,6 @@
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
- "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -413,7 +413,6 @@
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
- "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -447,7 +446,6 @@
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
"integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.29.0"
@@ -549,7 +547,6 @@
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
"integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@@ -883,7 +880,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -900,7 +896,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -917,7 +912,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -934,7 +928,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -951,7 +944,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -968,7 +960,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -985,7 +976,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1002,7 +992,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1019,7 +1008,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1036,7 +1024,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1053,7 +1040,6 @@
"cpu": [
"ia32"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1070,7 +1056,6 @@
"cpu": [
"loong64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1087,7 +1072,6 @@
"cpu": [
"mips64el"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1104,7 +1088,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1121,7 +1104,6 @@
"cpu": [
"riscv64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1138,7 +1120,6 @@
"cpu": [
"s390x"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1155,7 +1136,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1172,7 +1152,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1189,7 +1168,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1206,7 +1184,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1223,7 +1200,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1240,7 +1216,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1257,7 +1232,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1274,7 +1248,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1291,7 +1264,6 @@
"cpu": [
"ia32"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1308,7 +1280,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1534,6 +1505,47 @@
"url": "https://github.com/sponsors/nzakas"
}
},
+ "node_modules/@iconify/collections": {
+ "version": "1.0.652",
+ "resolved": "https://registry.npmjs.org/@iconify/collections/-/collections-1.0.652.tgz",
+ "integrity": "sha512-RJhGvFA27VPidZPewkSPHncr1NgAo7qnaO+aUA2vEfFTnYvAfVoZGn1CPIK1y2J+N+3w/KHpEHAEf1pQAHiNDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@iconify/types": "*"
+ }
+ },
+ "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/@iconify/utils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz",
+ "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==",
+ "license": "MIT",
+ "dependencies": {
+ "@antfu/install-pkg": "^1.1.0",
+ "@iconify/types": "^2.0.0",
+ "mlly": "^1.8.0"
+ }
+ },
+ "node_modules/@iconify/vue": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/vue/-/vue-5.0.0.tgz",
+ "integrity": "sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg==",
+ "license": "MIT",
+ "dependencies": {
+ "@iconify/types": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/cyberalien"
+ },
+ "peerDependencies": {
+ "vue": ">=3"
+ }
+ },
"node_modules/@ioredis/commands": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.0.tgz",
@@ -1690,7 +1702,7 @@
"version": "0.3.11",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
"integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@@ -1956,7 +1968,6 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-3.2.1.tgz",
"integrity": "sha512-lwCtTgqH2izU/d+mAmddnPG3mBaia9BsknxYkMFAPbxtph/ex5tPkmQjKACPQU5q4Tl5bTgWgZWo9pa3oz4LMQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@nuxt/kit": "^4.3.1",
@@ -2297,11 +2308,32 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/@nuxt/icon": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@nuxt/icon/-/icon-2.2.1.tgz",
+ "integrity": "sha512-GI840yYGuvHI0BGDQ63d6rAxGzG96jQcWrnaWIQKlyQo/7sx9PjXkSHckXUXyX1MCr9zY6U25Td6OatfY6Hklw==",
+ "license": "MIT",
+ "dependencies": {
+ "@iconify/collections": "^1.0.641",
+ "@iconify/types": "^2.0.0",
+ "@iconify/utils": "^3.1.0",
+ "@iconify/vue": "^5.0.0",
+ "@nuxt/devtools-kit": "^3.1.1",
+ "@nuxt/kit": "^4.2.2",
+ "consola": "^3.4.2",
+ "local-pkg": "^1.1.2",
+ "mlly": "^1.8.0",
+ "ohash": "^2.0.11",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.3",
+ "std-env": "^3.10.0",
+ "tinyglobby": "^0.2.15"
+ }
+ },
"node_modules/@nuxt/kit": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.3.1.tgz",
"integrity": "sha512-UjBFt72dnpc+83BV3OIbCT0YHLevJtgJCHpxMX0YRKWLDhhbcDdUse87GtsQBrjvOzK7WUNUYLDS/hQLYev5rA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"c12": "^3.3.3",
@@ -4185,7 +4217,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4199,7 +4230,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4213,7 +4243,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4227,7 +4256,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4241,7 +4269,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4255,7 +4282,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4269,7 +4295,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4283,7 +4308,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4297,7 +4321,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4311,7 +4334,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4325,7 +4347,6 @@
"cpu": [
"loong64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4339,7 +4360,6 @@
"cpu": [
"loong64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4353,7 +4373,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4367,7 +4386,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4381,7 +4399,6 @@
"cpu": [
"riscv64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4395,7 +4412,6 @@
"cpu": [
"riscv64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4409,7 +4425,6 @@
"cpu": [
"s390x"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4423,7 +4438,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4437,7 +4451,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4451,7 +4464,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4465,7 +4477,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4479,7 +4490,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4493,7 +4503,6 @@
"cpu": [
"ia32"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4507,7 +4516,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4521,7 +4529,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -4679,7 +4686,7 @@
"version": "24.10.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.13.tgz",
"integrity": "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
@@ -5540,7 +5547,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.28.tgz",
"integrity": "sha512-kviccYxTgoE8n6OCw96BNdYlBg2GOWfBuOW4Vqwrt7mSKWKwFVvI8egdTltqRgITGPsTFYtKYfxIG8ptX2PJHQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.0",
@@ -5554,7 +5560,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.28.tgz",
"integrity": "sha512-/1ZepxAb159jKR1btkefDP+J2xuWL5V3WtleRmxaT+K2Aqiek/Ab/+Ebrw2pPj0sdHO8ViAyyJWfhXXOP/+LQA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.28",
@@ -5565,7 +5570,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.28.tgz",
"integrity": "sha512-6TnKMiNkd6u6VeVDhZn/07KhEZuBSn43Wd2No5zaP5s3xm8IqFTHBj84HJah4UepSUJTro5SoqqlOY22FKY96g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.0",
@@ -5583,7 +5587,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.28.tgz",
"integrity": "sha512-JCq//9w1qmC6UGLWJX7RXzrGpKkroubey/ZFqTpvEIDJEKGgntuDMqkuWiZvzTzTA5h2qZvFBFHY7fAAa9475g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.28",
@@ -5671,7 +5674,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.28.tgz",
"integrity": "sha512-gr5hEsxvn+RNyu9/9o1WtdYdwDjg5FgjUSBEkZWqgTKlo/fvwZ2+8W6AfKsc9YN2k/+iHYdS9vZYAhpi10kNaw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/shared": "3.5.28"
@@ -5681,7 +5683,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.28.tgz",
"integrity": "sha512-POVHTdbgnrBBIpnbYU4y7pOMNlPn2QVxVzkvEA2pEgvzbelQq4ZOUxbp2oiyo+BOtiYlm8Q44wShHJoBvDPAjQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.28",
@@ -5692,7 +5693,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.28.tgz",
"integrity": "sha512-4SXxSF8SXYMuhAIkT+eBRqOkWEfPu6nhccrzrkioA6l0boiq7sp18HCOov9qWJA5HML61kW8p/cB4MmBiG9dSA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.28",
@@ -5705,7 +5705,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.28.tgz",
"integrity": "sha512-pf+5ECKGj8fX95bNincbzJ6yp6nyzuLDhYZCeFxUNp8EBrQpPpQaLX3nNCp49+UbgbPun3CeVE+5CXVV1Xydfg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-ssr": "3.5.28",
@@ -5719,7 +5718,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.28.tgz",
"integrity": "sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/@vue/test-utils": {
@@ -6352,7 +6350,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/builtin-modules": {
@@ -6993,7 +6991,6 @@
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
@@ -7227,7 +7224,6 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/data-urls": {
@@ -7714,7 +7710,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
- "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
@@ -7780,7 +7775,6 @@
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
"integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@@ -8354,7 +8348,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
- "dev": true,
"license": "MIT"
},
"node_modules/esutils": {
@@ -8411,7 +8404,6 @@
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
"integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"cross-spawn": "^7.0.3",
@@ -8799,7 +8791,6 @@
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
"integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=16"
@@ -9229,7 +9220,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
"integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
- "dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">=16.17.0"
@@ -9611,7 +9601,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
@@ -9676,7 +9665,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
"license": "ISC"
},
"node_modules/jackspeak": {
@@ -10358,7 +10346,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz",
"integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"mlly": "^1.7.4",
@@ -10519,6 +10506,12 @@
"source-map-js": "^1.2.1"
}
},
+ "node_modules/maska": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/maska/-/maska-3.2.0.tgz",
+ "integrity": "sha512-zSmSgs5/q9vMSmrdZT3rKOv9uLznNWR/niuuAdBZDTvB3SMKOX9vhMtDijFyExz+B4UClu2rvksylUh/ea1bLA==",
+ "license": "MIT"
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -10548,7 +10541,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true,
"license": "MIT"
},
"node_modules/merge2": {
@@ -10641,7 +10633,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@@ -11045,7 +11036,6 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
"integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^4.0.0"
@@ -11061,7 +11051,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@@ -11296,7 +11285,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"mimic-fn": "^4.0.0"
@@ -11542,7 +11530,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz",
"integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==",
- "dev": true,
"license": "MIT"
},
"node_modules/parse-imports-exports": {
@@ -11627,7 +11614,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -12491,7 +12477,6 @@
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
"integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
- "dev": true,
"funding": [
{
"type": "individual",
@@ -12906,7 +12891,6 @@
"version": "4.57.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz",
"integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.8"
@@ -13208,7 +13192,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
@@ -13221,7 +13204,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -13251,7 +13233,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=14"
@@ -13344,7 +13325,7 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
@@ -13355,7 +13336,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
+ "devOptional": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -13446,7 +13427,6 @@
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
"integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
- "dev": true,
"license": "MIT"
},
"node_modules/streamx": {
@@ -13531,7 +13511,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@@ -13975,7 +13954,7 @@
"version": "5.46.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz",
"integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==",
- "dev": true,
+ "devOptional": true,
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
@@ -13994,7 +13973,7 @@
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/text-decoder": {
@@ -14295,7 +14274,7 @@
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
- "dev": true,
+ "devOptional": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -14364,7 +14343,7 @@
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
"node_modules/unenv": {
@@ -14862,7 +14841,6 @@
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.27.0",
@@ -15354,7 +15332,6 @@
"version": "3.5.28",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.28.tgz",
"integrity": "sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.28",
@@ -15510,7 +15487,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
diff --git a/package.json b/package.json
index 005d5b3..3be8d98 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,11 @@
"type": "module",
"version": "0.0.1",
"main": "./nuxt.config.ts",
- "files": ["app/**", "nuxt.config.ts", "README.md"],
+ "files": [
+ "app/**",
+ "nuxt.config.ts",
+ "README.md"
+ ],
"scripts": {
"dev": "nuxi dev .playground",
"dev:prepare": "nuxt prepare .playground",
@@ -29,6 +33,8 @@
"vue": "latest"
},
"dependencies": {
- "@nuxtjs/tailwindcss": "^6.14.0"
+ "@nuxt/icon": "^2.2.1",
+ "@nuxtjs/tailwindcss": "^6.14.0",
+ "maska": "^3.2.0"
}
}
diff --git a/pre-commit b/pre-commit
index b616324..cf4eeee 100644
--- a/pre-commit
+++ b/pre-commit
@@ -3,23 +3,14 @@ set -e
echo "######### Pre-commit hook start #############"
-if ! command -v npm >/dev/null 2>&1; then
- if [ -f ".nvmrc" ]; then
- NVM_VERSION="$(tr -d '\r\n' < .nvmrc)"
- NVM_VERSION="${NVM_VERSION#v}"
- NPM_BIN="$HOME/.nvm/versions/node/v$NVM_VERSION/bin"
- if [ -x "$NPM_BIN/npm" ]; then
- PATH="$NPM_BIN:$PATH"
- export PATH
- fi
- fi
-fi
-
-if ! command -v npm >/dev/null 2>&1; then
- if [ -s "$HOME/.nvm/nvm.sh" ]; then
- # shellcheck disable=SC1090
- . "$HOME/.nvm/nvm.sh"
- nvm use >/dev/null 2>&1 || true
+# Prefer the exact Node version from .nvmrc for hooks (IDE + CLI consistency).
+if [ -f ".nvmrc" ]; then
+ NVM_VERSION="$(tr -d '\r\n' < .nvmrc)"
+ NVM_VERSION="${NVM_VERSION#v}"
+ NVM_BIN="$HOME/.nvm/versions/node/v$NVM_VERSION/bin"
+ if [ -x "$NVM_BIN/node" ] && [ -x "$NVM_BIN/npm" ]; then
+ PATH="$NVM_BIN:$PATH"
+ export PATH
fi
fi
@@ -28,6 +19,7 @@ if ! command -v npm >/dev/null 2>&1; then
exit 1
fi
+echo "Node $(node -v) / npm $(npm -v)"
echo "--- make pre-commit start ---"
make pre-commit
echo "--- make pre-commit finished ---"
diff --git a/tailwind.config.ts b/tailwind.config.ts
new file mode 100644
index 0000000..6f76011
--- /dev/null
+++ b/tailwind.config.ts
@@ -0,0 +1,22 @@
+import type {Config} from 'tailwindcss'
+
+export default >{
+ theme: {
+ extend: {
+ fontFamily: {
+ sans: ['"Helvetica Neue"', 'Helvetica', 'Arial', 'sans-serif']
+ },
+ colors: {
+ primary: {
+ 500: '#222783',
+ },
+ secondary: {
+ 500: '#304998'
+ },
+ 5: {
+ 500: '#F3F4F8'
+ }
+ }
+ }
+ }
+}