[#337] Création d'un composant Select (#3)

| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|       #337           |           Création d'un composant Select      |

## Description de la PR

## Modification du .env

## Check list

- [x] Pas de régression
- [ ] TU/TI/TF rédigée
- [x] TU/TI/TF OK
- [x] CHANGELOG modifié

Co-authored-by: tristan <tristan@yuno.malio.fr>
Reviewed-on: #3
Reviewed-by: Autin <tristan@yuno.malio.fr>
Co-authored-by: kevin <kevin@yuno.malio.fr>
Co-committed-by: kevin <kevin@yuno.malio.fr>
This commit was merged in pull request #3.
This commit is contained in:
2026-03-02 13:24:58 +00:00
committed by Autin
parent 82ecc9cfe2
commit 1ab7b2427a
25 changed files with 4208 additions and 188 deletions

View File

@@ -0,0 +1,184 @@
<template>
<div class="grid grid-cols-1 items-start gap-6 md:grid-cols-2">
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Simple</h2>
<MalioInputText
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Avec label</h2>
<MalioInputText
v-model="nameValue"
label="Nom d'utilisateur"
name="username"
autocomplete="username"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Avec icône à droite</h2>
<MalioInputText
v-model="searchValue"
label="Recherche"
icon-name="mdi:magnify"
icon-size="20"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Avec icône à gauche</h2>
<MalioInputText
label="Recherche"
icon-name="mdi:magnify"
icon-size="20"
icon-position="left"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Désactivé</h2>
<MalioInputText
model-value="Valeur verrouillée"
disabled
label="Champ désactivé"
/>
<MalioInputText
disabled
label="Champ désactivé"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Readonly</h2>
<MalioInputText
model-value="Lecture seule"
readonly
label="Champ readonly"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Hint + icône</h2>
<MalioInputText
v-model="cityValue"
label="Ville"
icon-name="mdi:map-marker-outline"
icon-size="20"
hint="Commencez à taper le nom de la ville"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Erreur + icône</h2>
<MalioInputText
model-value="ab"
label="Code promo"
icon-name="mdi:alert-circle-outline"
icon-size="20"
error="Le code est invalide"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Succès + icône</h2>
<MalioInputText
label="Code"
success="Code valide"
icon-name="mdi:alert-circle-outline"
icon-size="20"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Readonly + icône</h2>
<MalioInputText
model-value="Commande #A-2048"
label="Référence"
readonly
icon-name="mdi:lock-outline"
icon-size="20"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Désactivé + icône</h2>
<MalioInputText
model-value="Compte indisponible"
label="Compte"
disabled
icon-name="mdi:account-off-outline"
icon-size="20"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Avec masque</h2>
<MalioInputText
label="Plaque d'immatriculation"
:mask="maskOptions"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Code dynamique</h2>
<MalioInputText
v-model="dynamicCodeValue"
label="Code d'accès"
hint="Format attendu: 6 à 10 caractères alphanumériques"
:error="dynamicCodeError"
:success="dynamicCodeSuccess"
icon-name="mdi:key-outline"
icon-size="20"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Hint,erreur et succès</h2>
<MalioInputText
v-model="codeValue"
label="Code"
hint="Format attendu: 6 à 10 caractères alphanumériques"
/>
<div class="mt-4">
<MalioInputText
model-value="invalide"
label="Code"
error="Le code doit contenir au moins 6 caractères"
/>
</div>
<div class="mt-4">
<MalioInputText
model-value="valide"
label="Code"
success="Le code est valide"
/>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
const nameValue = ref('')
const searchValue = ref('')
const codeValue = ref('')
const cityValue = ref('')
const dynamicCodeValue = ref('')
const codeRegex = /^[A-Z0-9]{6,10}$/
const normalizedDynamicCode = computed(() => dynamicCodeValue.value.toUpperCase())
const isDynamicCodeValid = computed(() => codeRegex.test(normalizedDynamicCode.value))
const dynamicCodeError = computed(() => {
if (!dynamicCodeValue.value) return ''
return isDynamicCodeValid.value ? '' : 'Code invalide (6 à 10 caractères alphanumériques)'
})
const dynamicCodeSuccess = computed(() => {
if (!dynamicCodeValue.value) return ''
return isDynamicCodeValid.value ? 'Code valide' : ''
})
const maskOptions = {
mask: '@@-###-@@',
tokens: {
'@': {
pattern: /[A-Za-z]/,
transform: (char: string) => char.toUpperCase()
}
}
}
</script>

View File

@@ -0,0 +1,104 @@
<template>
<div class="grid grid-cols-1 items-start gap-6 p-4 md:grid-cols-2">
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Simple</h2>
<MalioInputTextArea/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Avec label + hint</h2>
<MalioInputTextArea
v-model="hintValue"
label="Description"
hint="Ajoutez un contexte clair"
:size="4"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Avec icône</h2>
<MalioInputTextArea
v-model="iconValue"
label="Commentaire"
icon-name="mdi:comment-text-outline"
:size="3"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Erreur / Succès</h2>
<div class="space-y-4">
<MalioInputTextArea
v-model="errorValue"
label="Message"
error="Le message est trop court"
:size="3"
/>
<MalioInputTextArea
v-model="successValue"
label="Message"
success="Message valide"
:size="3"
/>
</div>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Readonly / Disabled</h2>
<div class="space-y-4">
<MalioInputTextArea
model-value="Contenu en lecture seule"
label="Readonly"
readonly
:size="3"
/>
<MalioInputTextArea
model-value="Champ indisponible"
label="Disabled"
disabled
:size="3"
/>
</div>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Resize avec limites</h2>
<MalioInputTextArea
v-model="resizeValue"
label="Notes"
resize="both"
:size="4"
:min-resize-width="300"
:max-resize-width="700"
:min-resize-height="120"
:max-resize-height="280"
hint="Resize limite en largeur et hauteur"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Compteur (interne au composant)</h2>
<MalioInputTextArea
v-model="counterValue"
label="Message"
:size="5"
:max-length="120"
:show-counter="true"
hint="Le compteur est en bas a gauche"
/>
</div>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
import MalioInputTextArea from '../../../app/components/malio/InputTextArea.vue'
const hintValue = ref('')
const iconValue = ref('')
const errorValue = ref('abc')
const successValue = ref('Contenu ok')
const resizeValue = ref('Vous pouvez redimensionner ce champ.')
const counterValue = ref('')
</script>

View File

@@ -0,0 +1,149 @@
<template>
<div class="grid grid-cols-1 items-start gap-6 md:grid-cols-2">
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Simple</h2>
<MalioSelect
v-model="basicValue"
:options="options"
empty-option-label="Aucune selection"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Avec label</h2>
<MalioSelect
v-model="labelValue"
:options="options"
label="Pays"
empty-option-label="Aucune selection"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Valeur preselectionnee</h2>
<MalioSelect
v-model="selectedValue"
:options="options"
label="Pays"
empty-option-label="Aucune selection"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Hint</h2>
<MalioSelect
v-model="hintValue"
:options="options"
label="Pays"
hint="Choisissez votre pays"
empty-option-label="Aucune selection"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Erreur</h2>
<MalioSelect
v-model="errorValue"
:options="options"
label="Pays"
error="Ce champ est obligatoire"
empty-option-label="Aucune selection"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Succes</h2>
<MalioSelect
v-model="successValue"
:options="options"
label="Pays"
success="Selection validee"
empty-option-label="Aucune selection"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Desactive</h2>
<MalioSelect
v-model="disabledValue"
:options="options"
label="Pays"
disabled
empty-option-label="Aucune selection"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Sans options</h2>
<MalioSelect
v-model="emptyValue"
label="Pays"
empty-option-label="Aucun pays disponible"
/>
</div>
<div class="rounded-lg border p-4 md:col-span-2">
<h2 class="mb-4 text-xl font-bold">Liste longue</h2>
<MalioSelect
v-model="longListValue"
:options="longOptions"
label="Pays"
hint="Permet de verifier la scrollbar"
empty-option-label="Aucune selection"
/>
</div>
<div class="rounded-lg border p-4 md:col-span-2">
<h2 class="mb-4 text-xl font-bold">Ouverture en bas de page</h2>
<div class="h-64" />
<MalioSelect
v-model="bottomValue"
:options="longOptions"
label="Ouverture adaptative"
hint="A ouvrir pres du bas de la page"
empty-option-label="Aucune selection"
/>
</div>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
const options = [
{label: 'France', value: 'fr'},
{label: 'Belgique', value: 'be'},
{label: 'Suisse', value: 'ch'},
{label: 'Canada', value: 'ca'},
{label: 'Allemagne', value: 'de'},
{label: 'Espagne', value: 'es'},
{label: 'Italie', value: 'it'},
{label: 'Portugal', value: 'pt'},
]
const longOptions = [
...options,
{label: 'Pays-Bas', value: 'nl'},
{label: 'Suede', value: 'se'},
{label: 'Norvege', value: 'no'},
{label: 'Danemark', value: 'dk'},
{label: 'Finlande', value: 'fi'},
{label: 'Autriche', value: 'at'},
{label: 'Irlande', value: 'ie'},
{label: 'Grece', value: 'gr'},
{label: 'Pologne', value: 'pl'},
{label: 'Hongrie', value: 'hu'},
{label: 'Republique tcheque', value: 'cz'},
]
const basicValue = ref<string | number | null>(null)
const labelValue = ref<string | number | null>(null)
const selectedValue = ref<string | number | null>('fr')
const hintValue = ref<string | number | null>(null)
const errorValue = ref<string | number | null>(null)
const successValue = ref<string | number | null>('be')
const disabledValue = ref<string | number | null>('ca')
const emptyValue = ref<string | number | null>(null)
const longListValue = ref<string | number | null>(null)
const bottomValue = ref<string | number | null>(null)
</script>