import type { Meta, StoryObj } from '@storybook/vue3' import { ref } from 'vue' import FdsSearchSelect from './FdsSearchSelect.vue' const meta: Meta = { title: 'FDS/Form/FdsSearchSelect', component: FdsSearchSelect, tags: ['autodocs'], argTypes: { items: { control: { type: 'object' }, description: 'Array of items to display in the search select dropdown', }, page: { control: { type: 'number' }, description: 'Current page number for server-side pagination', }, totalPages: { control: { type: 'number' }, description: 'Total number of pages for server-side pagination', }, totalCount: { control: { type: 'number' }, description: 'Total count of unfiltered items (displayed as "x av y")', }, loading: { control: { type: 'boolean' }, description: 'Shows loading spinner in the dropdown when true', }, searchFields: { control: { type: 'object' }, description: 'Array of field names to search in (e.g., ["fullName", "email"])', }, preserveOrder: { control: { type: 'boolean' }, description: 'If true, preserves the order of searchFields when displaying results', }, initialValue: { control: { type: 'text' }, description: 'Initial value to display in the input field', }, disabled: { control: { type: 'boolean' }, description: 'Disables the search select component', }, dropdownAbsolute: { control: { type: 'boolean' }, description: 'If true, positions the dropdown absolutely', }, labelLeft: { control: { type: 'boolean' }, description: 'If true, positions the label to the left of the input', }, label: { control: { type: 'text' }, description: 'Label text for the input field', }, meta: { control: { type: 'text' }, description: 'Meta text displayed below the label', }, singleItemLabel: { control: { type: 'text' }, description: 'Label text displayed when a single item is shown', }, searchContext: { control: { type: 'object' }, description: 'Context object with "context" and "linkWord" for displaying search results count', }, valid: { control: { type: 'select' }, options: [true, false, null], mapping: { true: true, false: false, null: null }, description: 'Validation state: true for valid, false for invalid, null for neutral', }, invalidMessage: { control: { type: 'text' }, description: 'Error message displayed when validation is false', }, noResultPrompt: { control: { type: 'text' }, description: 'Message displayed when no search results are found', }, borderless: { control: { type: 'boolean' }, description: 'If true, removes borders from the dropdown list', }, marginless: { control: { type: 'boolean' }, description: 'If true, removes bottom margin from the component', }, maxListHeight: { control: { type: 'number' }, description: 'Maximum height of the dropdown list in pixels', }, clearTrigger: { control: { type: 'boolean' }, description: 'When set to true, clears the search input and selection', }, }, args: { items: [], searchFields: ['companyName', 'orgNumber'], preserveOrder: false, initialValue: '', disabled: false, dropdownAbsolute: false, labelLeft: false, label: 'Sök organisation', meta: undefined, singleItemLabel: 'Vald organisation', searchContext: { context: 'organisationer', linkWord: 'av' }, valid: undefined, invalidMessage: 'Vänligen välj en organisation', noResultPrompt: 'Inga resultat hittades', borderless: false, marginless: false, maxListHeight: undefined, clearTrigger: false, }, } export default meta type Story = StoryObj // Mock data for items examples const mockItems = [ { companyName: 'Acme Corporation', orgNumber: '1234567890', companyFqn: 'Acme Corporation | 1234567890', }, { companyName: 'Tech Solutions AB', orgNumber: '9876543210', companyFqn: 'Tech Solutions AB | 9876543210', }, { companyName: 'Global Industries', orgNumber: '5555555555', companyFqn: 'Global Industries | 5555555555', }, { companyName: 'Nordic Ventures', orgNumber: '1111111111', companyFqn: 'Nordic Ventures | 1111111111', }, { companyName: 'Scandinavian Group', orgNumber: '2222222222', companyFqn: 'Scandinavian Group | 2222222222', }, ] export const WithItems: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => { const selected = ref | null>(null) const handleSearchSelected = (value: Record | null) => { selected.value = value } return { args, selected, handleSearchSelected } }, template: ` `, }), args: { items: mockItems, label: 'Sök bland organisationer', meta: 'Börja skriva för att söka', }, } export const WithSelectedEarlier: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => { const selected = ref | null>(null) const handleSearchSelected = (value: Record | null) => { selected.value = value } return { args, selected, handleSearchSelected } }, template: ` `, }), args: { items: mockItems, initialValue: 'Acme Corporation', label: 'Organisation', }, } export const SingleOrganization: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => { const selected = ref | null>(null) const handleSearchSelected = (value: Record | null) => { selected.value = value } return { args, selected, handleSearchSelected } }, template: ` `, }), args: { items: [ { companyName: 'Acme Corporation', orgNumber: '1234567890', companyFqn: 'Acme Corporation | 1234567890', }, ], singleItemLabel: 'Vald organisation', label: 'Organisation', }, } export const WithValidation: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => { const selected = ref | null>(null) const valid = ref(null) const handleSearchSelected = (value: Record | null) => { selected.value = value valid.value = value ? true : null } return { args, selected, valid, handleSearchSelected } }, template: ` `, }), args: { items: mockItems, label: 'Välj organisation', invalidMessage: 'Vänligen välj en organisation', }, } export const WithLabelLeft: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => { const selected = ref | null>(null) const handleSearchSelected = (value: Record | null) => { selected.value = value } return { args, selected, handleSearchSelected } }, template: `
`, }), args: { items: mockItems, label: 'Organisation', labelLeft: true, meta: 'Sök efter organisation', }, } export const WithAbsoluteList: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => { const selected = ref | null>(null) const handleSearchSelected = (value: Record | null) => { selected.value = value } return { args, selected, handleSearchSelected } }, template: `
`, }), args: { items: mockItems, dropdownAbsolute: true, label: 'Sök organisation', }, } export const Disabled: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => ({ args }), template: '', }), args: { items: mockItems, disabled: true, label: 'Sök organisation', }, } export const EnglishCopy: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => { const selected = ref | null>(null) const handleSearchSelected = (value: Record | null) => { selected.value = value } return { args, selected, handleSearchSelected } }, template: `
`, }), args: { items: mockItems, label: 'Search organization', meta: 'Start typing to search', singleItemLabel: 'Selected organization', searchContext: { context: 'organizations', linkWord: 'of' }, noResultPrompt: 'No results found', invalidMessage: 'Please select an organization', }, } export const WithPagination: Story = { render: (args: Story['args']) => ({ components: { FdsSearchSelect }, setup: () => { const selected = ref | null>(null) const handleSearchSelected = (value: Record | null) => { selected.value = value } const handlePaginate = (page: number) => { // eslint-disable-next-line no-console console.log('Paginate to page:', page) } return { args, selected, handleSearchSelected, handlePaginate } }, template: `
`, }), args: { items: [ ...mockItems, { companyName: 'Company 6', orgNumber: '6666666666', companyFqn: 'Company 6 | 6666666666', }, { companyName: 'Company 7', orgNumber: '7777777777', companyFqn: 'Company 7 | 7777777777', }, { companyName: 'Company 8', orgNumber: '8888888888', companyFqn: 'Company 8 | 8888888888', }, { companyName: 'Company 9', orgNumber: '9999999999', companyFqn: 'Company 9 | 9999999999', }, { companyName: 'Company 10', orgNumber: '1010101010', companyFqn: 'Company 10 | 1010101010', }, ], page: 1, totalPages: 2, label: 'Sök organisation', }, }