import type { Meta, StoryObj } from '@storybook/vue3' import SySelect from '@/components/Customs/Selects/SySelect/SySelect.vue' import SyAlert from '../../../SyAlert/SyAlert.vue' import { VBtn, VMenu, VList, VListItem, VListItemTitle } from 'vuetify/components' import { ref } from 'vue' import { fn } from '@storybook/test' import { getValidationDocumentation } from '@/composables/unifyValidation/documentationValidationProps' const meta: Meta = { title: 'Composants/Formulaires/Selects/SySelect', component: SySelect, parameters: { layout: 'fullscreen', controls: { exclude: ['onUpdate:modelValue', 'selectedValue', 'isOpen', 'closeList'] }, }, argTypes: { ...getValidationDocumentation('string'), selectedValue: { control: 'text' }, items: { control: 'object' }, displayAsterisk: { control: 'boolean' }, textKey: { control: 'text', description: 'Nom de la propriété qui contient le texte à afficher', }, plainTextKey: { control: 'text', description: 'Nom de la propriété qui contient le texte à afficher en mode texte brut (utile dans le cas de données HTML)', }, allowHtml: { control: 'boolean', description: 'Permet d\'afficher le texte des options en HTML. À utiliser avec plainTextKey pour le filtrage en texte brut.', }, valueKey: { control: 'text', description: 'Nom de la propriété qui contient la valeur à retourner', }, returnObject: { control: 'boolean', description: 'Retourne l\'objet complet sélectionné au lieu de la seule valeur de valueKey.', }, clearable: { control: 'boolean', description: 'Permet de vider la sélection', }, multiple: { control: 'boolean', description: 'Permet la sélection multiple d\'options', }, chips: { control: 'boolean', description: 'Affiche les options sélectionnées sous forme de chips', }, variantStyle: { control: 'select', options: ['outlined', 'plain', 'underlined', 'filled', 'solo', 'solo-inverted', 'solo-filled'], description: 'Style visuel du champ. Par défaut le composant utilise le style outlined.', }, color: { control: 'select', options: ['primary', 'secondary', 'success', 'error', 'warning'], description: 'Couleur principale du champ (bordure et label au focus).', }, density: { control: 'select', options: ['default', 'comfortable', 'compact'], description: 'Définit la densité du champ de sélection', }, width: { control: 'text', description: 'Permet de définir une largeur personnalisée pour le champ de sélection', }, helpText: { control: 'text', description: 'Texte d\'aide affiché sous le champ. Remplace les messages de validation si aucun n\'est présent, sinon s\'affiche en dessous.', }, prependTooltip: { description: 'Texte du tooltip affiché au survol de l\'icône prepend. Si renseigné, l\'icône tooltip est automatiquement affichée.', control: 'text', }, appendTooltip: { description: 'Texte du tooltip affiché au survol de l\'icône append. Si renseigné, l\'icône tooltip est automatiquement affichée.', control: 'text', }, tooltipLocation: { description: 'Position des tooltips des icônes prepend et append.', control: 'select', options: ['top', 'bottom', 'start', 'end'], default: 'top', }, append: { description: 'Slot pour ajouter du contenu à droite du champ', control: false, table: { type: { summary: 'VNode' }, category: 'slots', }, }, prepend: { description: 'Slot pour ajouter du contenu à gauche du champ', control: false, table: { type: { summary: 'VNode' }, category: 'slots', }, }, }, } as Meta export default meta type Story = StoryObj export const Default: Story = { parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { 'items': [ { text: 'Lorem Ipsum is simply dummy text of the printing and typesetting', value: 'Adrien' }, { text: 'Industry. Lorem Ipsum has been the industry\'s standard dummy', value: 'Axel' }, { text: 'Text ever since the 1500s, when an unknown printer took a galley', value: 'Baptiste' }, { text: 'Of type and scrambled it to make a type specimen book. It has', value: 'Clement' }, { text: 'Survived not only five centuries, but also the leap into electronic', value: 'Corentin' }, { text: 'Cum haec taliaque sollicitas eius aures everberarent ', value: 'Damien' }, { text: 'Expositas semper eius modi rumoribus et patentes, varia ', value: 'David' }, { text: 'Expositas semper eius modi rumoribus et patentes, varia', value: 'Eloi' }, { text: 'Emensis itaque difficultatibus multis et nive obrutis callibus', value: 'Louis' }, { text: 'Plurimis ubi prope Rauracum ventum est ad supercilia', value: 'Valentin' }, ], 'customSuccessRules': [{ type: 'custom', options: { validate: (v: unknown) => v !== null && v !== undefined, successMessage: 'Option sélectionnée avec succès.', }, }], 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect, VBtn, VMenu, VList, VListItem, VListItemTitle }, setup() { const value = ref(null) return { args, value } }, template: `
`, } }, } export const HelpText: Story = { parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { 'items': [ { text: 'Adrien', value: 'Adrien' }, { text: 'Axel', value: 'Axel' }, { text: 'Baptiste', value: 'Baptiste' }, { text: 'Clement', value: 'Clement' }, { text: 'Corentin', value: 'Corentin' }, { text: 'Damien', value: 'Damien' }, { text: 'David', value: 'David' }, { text: 'Eloi', value: 'Eloi' }, { text: 'Louis', value: 'Louis' }, { text: 'Valentin', value: 'Valentin' }, ], 'helpText': 'Texte d\'aide à la saisie', 'hideDetails': false, 'customSuccessRules': [{ type: 'custom', options: { validate: (v: unknown) => v !== null && v !== undefined, successMessage: 'Option sélectionnée avec succès.', }, }], 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect, VBtn, VMenu, VList, VListItem, VListItemTitle }, setup() { const value = ref(null) return { args, value } }, template: `
`, } }, } export const Required: Story = { parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { 'items': [ { text: 'Option 1', value: '1' }, { text: 'Option 2', value: '2' }, ], 'required': true, 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect }, setup() { const value = ref(null) return { args, value } }, template: `

Ce champ est obligatoire

`, } }, } export const RequiredWithAsterisk: Story = { parameters: { docs: { description: { story: 'Version du champ de sélection requis avec un astérisque visuel.', }, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { ...Default.args, 'label': 'Sélectionnez une option', 'required': true, 'displayAsterisk': true, 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect }, setup() { const value = ref(null) return { args, value } }, template: `
`, } }, } export const SlotPrepend: Story = { parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { ...Default.args, 'items': [ { text: 'Option 1', value: '1' }, { text: 'Option 2', value: '2' }, ], 'prependIcon': 'success', 'disableClickButton': false, 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect }, setup() { const value = ref(null) const onPrependIconClick = fn() return { args, value, onPrependIconClick } }, template: `
`, } }, } export const SlotAppend: Story = { parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { ...Default.args, 'items': [ { text: 'Option 1', value: '1' }, { text: 'Option 2', value: '2' }, ], 'appendIcon': 'success', 'disableClickButton': false, 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect }, setup() { const value = ref(null) const onAppendIconClick = fn() return { args, value, onAppendIconClick } }, template: `
`, } }, } export const WithTooltips: Story = { args: { ...Default.args, 'items': [ { text: 'Option 1', value: '1' }, { text: 'Option 2', value: '2' }, ], 'label': 'Champ avec tooltips', 'prependTooltip': 'Information à gauche du champ', 'appendTooltip': 'Information à droite du champ', 'tooltipLocation': 'top', 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect }, setup() { const value = ref(null) return { args, value } }, template: `

Des icônes d'information avec tooltips sont affichées de chaque côté du champ. Survolez-les pour voir les messages d'aide qui apparaissent en haut grâce à la prop tooltipLocation="top".

`, } }, parameters: { docs: { description: { story: 'Exemple de champ avec des tooltips d\'information. Les icônes d\'information apparaissent automatiquement lorsque les props prependTooltip et/ou appendTooltip sont renseignées. La position des tooltips peut être contrôlée avec la prop tooltipLocation.', }, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const MultipleSelection: Story = { parameters: { docs: { description: { story: 'Exemple de sélection multiple avec SySelect. Les options dans le menu déroulant sont affichées avec des cases à cocher pour faciliter la sélection multiple.', }, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { 'items': [ { text: 'Adrien', value: 'Adrien' }, { text: 'Axel', value: 'Axel' }, { text: 'Baptiste', value: 'Baptiste' }, { text: 'Clement', value: 'Clement' }, { text: 'Corentin', value: 'Corentin' }, { text: 'Damien', value: 'Damien' }, { text: 'David', value: 'David' }, { text: 'Eloi', value: 'Eloi' }, { text: 'Louis', value: 'Louis' }, { text: 'Valentin', value: 'Valentin' }, ], 'label': 'Sélection multiple', 'multiple': true, 'clearable': true, 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect }, setup() { const selectedOptions = ref(null) return { args, selectedOptions } }, template: `
Options sélectionnées: {{ selectedOptions }}
`, } }, } export const ChipsDisplay: Story = { parameters: { docs: { description: { story: 'Exemple de sélection multiple avec affichage en chips. Les options sélectionnées sont affichées sous forme de chips dans le champ, et les options dans le menu déroulant sont affichées avec des cases à cocher.', }, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { 'items': [ { text: 'Option 1', value: '1' }, { text: 'Option 2', value: '2' }, { text: 'Option 3', value: '3' }, { text: 'Option 4', value: '4' }, ], 'label': 'Sélection avec chips', 'multiple': true, 'chips': true, 'clearable': true, 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect }, setup() { const selectedOptions = ref(null) return { args, selectedOptions } }, template: `
`, } }, } export const withCustomKey: Story = { parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { 'items': [ { customKey: 'Choix 1', value: '1' }, { customKey: 'Choix 2', value: '2' }, ], 'customSuccessRules': [{ type: 'custom', options: { validate: (v: unknown) => v !== null && v !== undefined, successMessage: 'Option sélectionnée avec succès.', }, }], 'onUpdate:modelValue': fn(), }, render: (args) => { return { components: { SySelect, VBtn, VMenu, VList, VListItem, VListItemTitle }, setup() { const value = ref(null) return { args, value } }, template: `
`, } }, } export const Info: Story = { render: (args) => { return { components: { SyAlert }, setup() { return { args } }, template: ` `, } }, tags: ['!dev'], }