feat : ajouts du composant input text area et fix sur le input text

This commit is contained in:
2026-02-27 09:24:37 +01:00
parent 0a3cf50576
commit 594708e71c
8 changed files with 767 additions and 85 deletions

View File

@@ -15,7 +15,7 @@
:key="item.name"
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 ' : ''"
:class="selectedName === item.name ? 'bg-m-secondary text-white' : ''"
@click="selectOrToggle(item.name)"
>
{{ item.label }}
@@ -32,10 +32,13 @@
v-else-if="selectedName"
class="text-gray-700"
>
Page de demo introuvable: <code>.playground/pages/composant/{{ selectedDemoFileName }}.vue</code>
Page de demo introuvable:
<code>.playground/pages/composant/{{ selectedDemoFileName }}.vue</code>
</p>
<div v-else>
<h1 class="text-2xl font-semibold text-gray-900">Playground composants</h1>
<h1 class="text-2xl font-semibold text-gray-900">
Playground composants
</h1>
<p class="mt-2 text-gray-600">
Selectionne un composant dans la liste pour afficher sa page de demo.
</p>
@@ -45,6 +48,8 @@
</template>
<script setup lang="ts">
import { computed, ref, watch, shallowRef } from 'vue'
type LoadedModule = {
default: unknown
}
@@ -52,40 +57,42 @@ type LoadedModule = {
type Item = {
name: string
label: string
demoComponent?: unknown
}
const componentModules = import.meta.glob('../../app/components/malio/*.vue', { eager: true }) as Record<string, LoadedModule>
const demoModules = import.meta.glob('./composant/*.vue', { eager: true }) as Record<string, LoadedModule>
const componentModules = import.meta.glob('../../app/components/malio/*.vue')
const demoModules = import.meta.glob('./composant/*.vue')
const demoByName = Object.fromEntries(
Object.entries(demoModules).map(([file, mod]) => {
const demoByName: Record<string, () => Promise<LoadedModule>> =
Object.fromEntries(
Object.entries(demoModules).map(([file, loader]) => {
const name = file.split('/').pop()?.replace('.vue', '') ?? ''
return [name.toLowerCase(), loader as () => Promise<LoadedModule>]
}),
)
const items = computed<Item[]>(() =>
Object.keys(componentModules).map((file) => {
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
}
})
watch(
items,
(val) => {
if (!hasInitializedSelection.value && val.length > 0) {
selectedName.value = val[0].name
hasInitializedSelection.value = true
}
},
{ immediate: true },
)
function selectOrToggle(name: string) {
selectedName.value = selectedName.value === name ? '' : name
@@ -95,9 +102,23 @@ function clearSelection() {
selectedName.value = ''
}
const selectedDemoComponent = computed(() =>
items.value.find((item) => item.name === selectedName.value)?.demoComponent,
)
const selectedDemoComponent = shallowRef<unknown>(null)
watch(selectedName, async (name) => {
if (!name) {
selectedDemoComponent.value = null
return
}
const loader = demoByName[name.toLowerCase()]
if (!loader) {
selectedDemoComponent.value = null
return
}
const mod = await loader()
selectedDemoComponent.value = mod.default
})
const selectedDemoFileName = computed(() => {
const name = selectedName.value