import type { Meta, StoryObj } from '@storybook/vue3' import FilterSideBar from './FilterSideBar.vue' import { fn } from '@storybook/test' import { VBtn, VDialog, VCard, VCardText, VCardActions, VDivider, VSelect } from 'vuetify/components' import PeriodField from '../PeriodField/PeriodField.vue' import SearchListField from '../SearchListField/SearchListField.vue' import { ref } from 'vue' import FilterInline from '../FilterInline/FilterInline.vue' import RangeField from '../RangeField/RangeField.vue' import SyTextField from '../Customs/SyTextField/SyTextField.vue' const meta = { title: 'Composants/Filtres/FiltersSideBar', component: FilterSideBar, argTypes: { 'modelValue': { description: 'Valeur des filtres', control: { type: 'object', }, table: { category: 'props', type: { summary: 'array', detail: `{ name: string value?: unknown formatChip?: (value: unknown) => ChipItem[] chipOverflowLimit?: number title?: string }[]`, }, defaultValue: { summary: '[]', }, }, }, 'modale': { description: 'Definit la dialogue en mode modale et bloque le focus dans la dialogue.', control: { type: 'boolean', }, table: { category: 'props', type: { summary: 'boolean', }, defaultValue: { summary: 'false', }, }, }, 'locales': { description: 'Traductions', control: { type: 'object', }, table: { category: 'props', type: { summary: 'Record', }, defaultValue: { summary: 'locales', detail: `{ filterBtnLabel: 'Filtres', badgeLabel: (count: number): string => \`\${count} filtre\${count > 1 ? 's' : ''}\`, reset: 'Réinitialiser', close: 'Fermer', apply: 'Appliquer', }`, }, }, }, 'zIndex': { description: 'Surcharge le z-index du panneau. À utiliser uniquement lorsque le FilterSideBar doit s\'afficher par-dessus ou en-dessous d\'un composant en surimpression (modale, bottom sheet…). Voir la section Gestion du z-index ci-dessous pour les préconisations.', control: { type: 'number', }, table: { category: 'props', type: { summary: 'number', }, defaultValue: { summary: 'undefined', }, }, }, 'onUpdate:modelValue': { description: 'Événement déclenché lors de la mise à jour des filtres', control: { type: undefined, }, table: { category: 'events', type: { summary: 'array', detail: `{ name: string value?: unknown formatChip?: (value: unknown) => ChipItem[] chipOverflowLimit?: number title?: string }[]`, }, }, }, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - storybook can't infer dynamic slot name '${filterName}': { description: 'Slot pour les filtres.
Le nom de chaque slot correspond au nom (`name`) du filtre.
Le paramètre du slot `props` est un objet contenant les props à passer au filtre.', table: { category: 'slots', type: { summary: '{ props: Object }', }, }, }, }, parameters: { layout: 'fullscreen', controls: { exclude: ['update:modelValue', '`${formatFilterName(filter.name)}`'], }, }, } satisfies Meta export default meta type Story = StoryObj export const Default: Story = { args: { 'onUpdate:modelValue': fn(), }, decorators: [ () => ({ template: `
`, }), ], render: args => ({ components: { FilterSideBar, SyTextField, VSelect, PeriodField, SearchListField }, setup() { const filters = ref([ { name: 'name', title: 'Identité', }, { name: 'folder', title: 'Type de dossier', }, { name: 'period', title: 'Période', }, { name: 'profession', title: 'Profession', }, ]) const folderTypes = [ { title: 'AT', value: 'at', }, { title: 'MP', value: 'mp', }, { title: 'Autre', value: 'other', }, ] const professionList = [ { label: 'Chirurgien-dentiste', value: 'chirurgien-dentiste', }, { label: 'Infirmier', value: 'infirmier', }, { label: 'Orthophoniste', value: 'orthophoniste', }, { label: 'Orthoptiste', value: 'orthoptiste', }, { label: 'Pédicure-podologue', value: 'pedicure-podologue', }, { label: 'Pharmacien', value: 'pharmacien', }, ] return { args, filters, folderTypes, professionList } }, template: ` `, }), parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const ChipFormat: Story = { args: { 'onUpdate:modelValue': fn(), }, decorators: [ () => ({ template: `
`, }), ], render: args => ({ components: { FilterSideBar, RangeField }, setup() { const filters = ref([ { name: 'range-slider', title: 'Intervalle', value: [0, 50], formatChip: ([min, max]: [number, number]) => [ { text: `De ${min} à ${max}`, value: [min, max], }, ], }, ]) return { args, filters } }, template: ` `, }), parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const FilterCombination: Story = { args: { 'onUpdate:modelValue': fn(), }, decorators: [ () => ({ template: `
`, }), ], render: args => ({ components: { FilterSideBar, FilterInline, SyTextField, VSelect, PeriodField, SearchListField, VDivider }, setup() { const filters = ref([ { name: 'name', title: 'Identité', }, { name: 'folder', title: 'Type de dossier', }, { name: 'period', title: 'Période', }, { name: 'profession', title: 'Profession', }, ]) const folderTypes = [ { title: 'AT', value: 'at', }, { title: 'MP', value: 'mp', }, { title: 'Autre', value: 'other', }, ] const professionList = [ { label: 'Chirurgien-dentiste', value: 'chirurgien-dentiste', }, { label: 'Infirmier', value: 'infirmier', }, { label: 'Orthophoniste', value: 'orthophoniste', }, { label: 'Orthoptiste', value: 'orthoptiste', }, { label: 'Pédicure-podologue', value: 'pedicure-podologue', }, { label: 'Pharmacien', value: 'pharmacien', }, ] return { args, filters, folderTypes, professionList } }, template: `
`, }), parameters: { sourceCode: [ { name: 'Template', code: `
`, }, { name: 'Script', code: ` `, }, ], }, } export const ZIndex: Story = { args: { 'onUpdate:modelValue': fn(), }, decorators: [ () => ({ template: `
`, }), ], render: args => ({ components: { FilterSideBar, VBtn, VDialog, VCard, VCardText, VCardActions, VSelect, VDivider }, setup() { const filters1 = ref([{ name: 'folder', title: 'Type de dossier' }]) const filters2 = ref([{ name: 'folder', title: 'Type de dossier' }]) const folderTypes = [ { title: 'AT', value: 'at' }, { title: 'MP', value: 'mp' }, { title: 'Autre', value: 'other' }, ] const dialog1 = ref(false) const dialog2 = ref(false) return { args, filters1, filters2, folderTypes, dialog1, dialog2 } }, template: `

Sans zIndex — la modale s'affiche par-dessus le panneau (comportement par défaut)

Ouvrir une modale de confirmation
Confirmez-vous la réinitialisation des filtres ? Annuler Confirmer

Avec zIndex="2401" — le panneau s'affiche par-dessus la modale

Ouvrir une modale de confirmation
Confirmez-vous la réinitialisation des filtres ? Annuler Confirmer
`, }), parameters: { docs: { description: { story: 'Deux exemples côte à côte : sans zIndex, la modale s\'affiche par-dessus le panneau (comportement par défaut) ; avec zIndex: 2401, le panneau passe au premier plan.', }, }, }, }