feat : reorganisation de la structure projet

This commit is contained in:
2026-03-20 14:22:40 +01:00
parent c95a3657c0
commit 09cc3edf6f
51 changed files with 116 additions and 45 deletions

View File

@@ -2,7 +2,17 @@
"permissions": { "permissions": {
"allow": [ "allow": [
"Bash(npm run:*)", "Bash(npm run:*)",
"Bash(npx vitest:*)" "Bash(npx vitest:*)",
"Bash(sed -i \"s|from ''../../../app/components/malio/Checkbox.vue''|from ''../../../app/components/malio/checkbox/Checkbox.vue''|\" .playground/pages/composant/checkbox.vue)",
"Bash(sed -i \"s|from ''../../../app/components/malio/RadioButton.vue''|from ''../../../app/components/malio/radio/RadioButton.vue''|\" .playground/pages/composant/radioButton.vue)",
"Bash(sed -i \"s|from ''../../../app/components/malio/Time.vue''|from ''../../../app/components/malio/time/Time.vue''|\" .playground/pages/composant/time.vue)",
"Bash(sed -i \"s|from ''../../../app/components/malio/InputTextArea.vue''|from ''../../../app/components/malio/input/InputTextArea.vue''|\" .playground/pages/composant/inputTextArea.vue)",
"Bash(npx nuxi:*)",
"Bash(mkdir -p button input select checkbox radio time)",
"Bash(mv buttonIcon.story.vue button/)",
"Bash(mv inputText.story.vue inputAmount.story.vue inputNumber.story.vue inputPassword.story.vue inputTextArea.story.vue inputUpload.story.vue input/)",
"Bash(mv InputSelect.story.vue selectCheckbox.story.vue select/)",
"Bash(mv inputCheckbox.story.vue checkbox/)"
] ]
} }
} }

View File

@@ -87,7 +87,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioCheckbox from '../../../app/components/malio/Checkbox.vue' import MalioCheckbox from '../../../../app/components/malio/checkbox/Checkbox.vue'
const simpleValue = ref(false) const simpleValue = ref(false)
const checkedValue = ref(true) const checkedValue = ref(true)
const hintValue = ref(false) const hintValue = ref(false)

View File

@@ -92,7 +92,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioInputTextArea from '../../../app/components/malio/InputTextArea.vue' import MalioInputTextArea from '../../../../app/components/malio/input/InputTextArea.vue'
const hintValue = ref('') const hintValue = ref('')
const iconValue = ref('') const iconValue = ref('')

View File

@@ -93,7 +93,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioRadioButton from '../../../app/components/malio/RadioButton.vue' import MalioRadioButton from '../../../../app/components/malio/radio/RadioButton.vue'
const options = [ const options = [
{label: 'Option 1', value: 'option1'}, {label: 'Option 1', value: 'option1'},

View File

@@ -74,7 +74,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioTime from '../../../app/components/malio/Time.vue' import MalioTime from '../../../../app/components/malio/time/Time.vue'
const simpleValue = ref('') const simpleValue = ref('')
const labeledValue = ref('') const labeledValue = ref('')

View File

@@ -9,17 +9,41 @@
Liste des composants Liste des composants
</button> </button>
<nav class="mt-6 flex flex-col gap-2"> <nav class="mt-6 flex flex-col gap-1">
<button <div
v-for="item in items" v-for="group in groups"
:key="item.name" :key="group.category"
type="button"
class="rounded px-3 py-2 text-left text-black font-bold hover:bg-m-primary hover:text-white"
:class="selectedName === item.name ? 'bg-m-secondary text-white' : ''"
@click="selectOrToggle(item.name)"
> >
{{ item.label }} <button
</button> type="button"
class="flex w-full items-center justify-between rounded px-3 py-2 text-left text-black font-bold hover:bg-m-primary/10"
@click="toggleCategory(group.category)"
>
{{ group.category }}
<span
class="text-xs transition-transform duration-200"
:class="openCategories.has(group.category) ? 'rotate-90' : ''"
>
&#9654;
</span>
</button>
<div
v-if="openCategories.has(group.category)"
class="ml-3 flex flex-col gap-1 border-l border-gray-300 pl-2"
>
<button
v-for="item in group.items"
:key="item.name"
type="button"
class="rounded px-3 py-1.5 text-left text-sm text-black hover:bg-m-primary hover:text-white"
:class="selectedName === item.name ? 'bg-m-secondary text-white' : ''"
@click="selectItem(item.name)"
>
{{ item.label }}
</button>
</div>
</div>
</nav> </nav>
</aside> </aside>
@@ -48,7 +72,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch, shallowRef } from 'vue' import {computed, reactive, ref, watch, shallowRef} from 'vue'
type LoadedModule = { type LoadedModule = {
default: unknown default: unknown
@@ -59,8 +83,13 @@ type Item = {
label: string label: string
} }
const componentModules = import.meta.glob('../../app/components/malio/*.vue') type Group = {
const demoModules = import.meta.glob('./composant/*.vue') category: string
items: Item[]
}
const componentModules = import.meta.glob('../../app/components/malio/**/*.vue')
const demoModules = import.meta.glob('./composant/**/*.vue')
const demoByName: Record<string, () => Promise<LoadedModule>> = const demoByName: Record<string, () => Promise<LoadedModule>> =
Object.fromEntries( Object.fromEntries(
@@ -70,31 +99,55 @@ const demoByName: Record<string, () => Promise<LoadedModule>> =
}), }),
) )
const items = computed<Item[]>(() => const groups = computed<Group[]>(() => {
Object.keys(componentModules).map((file) => { const categoryMap = new Map<string, Item[]>()
const name = file.split('/').pop()?.replace('.vue', '') ?? ''
return {
name,
label: name,
}
}),
)
Object.keys(componentModules).forEach((file) => {
const parts = file.split('/')
const name = parts.pop()?.replace('.vue', '') ?? ''
const category = parts.pop() ?? ''
if (!categoryMap.has(category)) {
categoryMap.set(category, [])
}
categoryMap.get(category)!.push({name, label: name})
})
return Array.from(categoryMap.entries())
.sort(([a], [b]) => a.localeCompare(b))
.map(([category, items]) => ({
category: category.charAt(0).toUpperCase() + category.slice(1),
items: items.sort((a, b) => a.label.localeCompare(b.label)),
}))
})
const openCategories = reactive(new Set<string>())
const selectedName = ref('') const selectedName = ref('')
const hasInitializedSelection = ref(false) const hasInitializedSelection = ref(false)
watch( watch(
items, groups,
(val) => { (val) => {
if (!hasInitializedSelection.value && val.length > 0) { if (!hasInitializedSelection.value && val.length > 0) {
selectedName.value = val[0].name openCategories.add(val[0].category)
if (val[0].items.length > 0) {
selectedName.value = val[0].items[0].name
}
hasInitializedSelection.value = true hasInitializedSelection.value = true
} }
}, },
{ immediate: true }, {immediate: true},
) )
function selectOrToggle(name: string) { function toggleCategory(category: string) {
if (openCategories.has(category)) {
openCategories.delete(category)
} else {
openCategories.add(category)
}
}
function selectItem(name: string) {
selectedName.value = selectedName.value === name ? '' : name selectedName.value = selectedName.value === name ? '' : name
} }

View File

@@ -204,7 +204,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {computed, onBeforeUnmount, onMounted, ref, useId, nextTick} from 'vue' import {computed, onBeforeUnmount, onMounted, ref, useId, nextTick} from 'vue'
import {Icon as IconifyIcon} from '@iconify/vue' import {Icon as IconifyIcon} from '@iconify/vue'
import Checkbox from './Checkbox.vue' import Checkbox from '../checkbox/Checkbox.vue'
defineOptions({name: 'MalioSelectCheckbox', inheritAttrs: false}) defineOptions({name: 'MalioSelectCheckbox', inheritAttrs: false})

View File

@@ -238,5 +238,5 @@ rapides et compactes (retour, modifier, supprimer, etc.).
</docs> </docs>
<script setup lang="ts"> <script setup lang="ts">
import MalioButtonIcon from '../components/malio/ButtonIcon.vue' import MalioButtonIcon from '../../components/malio/button/ButtonIcon.vue'
</script> </script>

View File

@@ -166,7 +166,7 @@ Composant checkbox custom avec `v-model`, message d'aide, et états visuels
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioCheckbox from '../components/malio/Checkbox.vue' import MalioCheckbox from '../../components/malio/checkbox/Checkbox.vue'
const simpleValue = ref(false) const simpleValue = ref(false)
const checkedValue = ref(true) const checkedValue = ref(true)

View File

@@ -248,7 +248,7 @@ Composant input dédié à la saisie dun montant décimal avec label flottant
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioInputAmount from '../components/malio/InputAmount.vue' import MalioInputAmount from '../../components/malio/input/InputAmount.vue'
const simpleValue = ref('') const simpleValue = ref('')
const hintValue = ref('') const hintValue = ref('')

View File

@@ -71,7 +71,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioInputNumber from '../components/malio/InputNumber.vue' import MalioInputNumber from '../../components/malio/input/InputNumber.vue'
const simpleValue = ref('') const simpleValue = ref('')
const initialValue = ref('3') const initialValue = ref('3')

View File

@@ -240,7 +240,7 @@ automatiquement.
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioInputPassword from '../components/malio/InputPassword.vue' import MalioInputPassword from '../../components/malio/input/InputPassword.vue'
const simpleValue = ref('') const simpleValue = ref('')
const noIconValue = ref('') const noIconValue = ref('')

View File

@@ -266,7 +266,7 @@ largeur.
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioInputText from '../components/malio/InputText.vue' import MalioInputText from '../../components/malio/input/InputText.vue'
const simpleValue = ref('') const simpleValue = ref('')
const hintValue = ref('') const hintValue = ref('')

View File

@@ -250,7 +250,7 @@ redimensionnement.
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioInputTextArea from '../components/malio/InputTextArea.vue' import MalioInputTextArea from '../../components/malio/input/InputTextArea.vue'
const simpleValue = ref('') const simpleValue = ref('')
const hintValue = ref('') const hintValue = ref('')

View File

@@ -223,7 +223,7 @@ et accessibilité.
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioInputUpload from '../components/malio/InputUpload.vue' import MalioInputUpload from '../../components/malio/input/InputUpload.vue'
const simpleValue = ref('') const simpleValue = ref('')
const noIconValue = ref('') const noIconValue = ref('')

View File

@@ -169,7 +169,7 @@ et les états visuels de validation.
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioRadioButton from '../components/malio/RadioButton.vue' import MalioRadioButton from '../../components/malio/radio/RadioButton.vue'
const options = [ const options = [
{label: 'Option 1', value: 'option1'}, {label: 'Option 1', value: 'option1'},

View File

@@ -1,5 +1,5 @@
<template> <template>
<Story title="Select"> <Story title="Select/Select">
<div class="grid grid-cols-1 gap-6 md:grid-cols-2"> <div class="grid grid-cols-1 gap-6 md:grid-cols-2">
<div class="rounded-lg border p-4"> <div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Simple</h2> <h2 class="mb-4 text-xl font-bold">Simple</h2>
@@ -178,7 +178,7 @@ largeur.
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioSelect from '../components/malio/Select.vue' import MalioSelect from '../../components/malio/select/Select.vue'
const simpleValue = ref<string | number | null>(null) const simpleValue = ref<string | number | null>(null)
const preselectedValue = ref<string | number | null>('fr') const preselectedValue = ref<string | number | null>('fr')

View File

@@ -192,7 +192,7 @@ Composant select avec checkboxes multiples, label flottant, tags optionnels,
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioSelectCheckbox from '../components/malio/SelectCheckbox.vue' import MalioSelectCheckbox from '../../components/malio/select/SelectCheckbox.vue'
const options = [ const options = [
{label: 'France', value: 'fr'}, {label: 'France', value: 'fr'},

View File

@@ -76,7 +76,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import MalioTime from '../components/malio/Time.vue' import MalioTime from '../../components/malio/time/Time.vue'
const simpleValue = ref('') const simpleValue = ref('')
const labeledValue = ref('') const labeledValue = ref('')

View File

@@ -7,6 +7,14 @@ export default defineNuxtConfig({
modules: ['@nuxtjs/tailwindcss','@nuxt/icon'], modules: ['@nuxtjs/tailwindcss','@nuxt/icon'],
css: [join(dir, 'app/assets/css/malio.css')], css: [join(dir, 'app/assets/css/malio.css')],
components: [
{
path: join(dir, 'app/components/malio'),
prefix: 'Malio',
pathPrefix: false,
},
],
tailwindcss: { tailwindcss: {
config: { config: {
theme: { theme: {