import type { Snippet } from 'svelte'; import type { FlipParams } from 'svelte/animate'; import type { HTMLAttributes, HTMLInputAttributes } from 'svelte/elements'; export type Option = string | number | ObjectOption; export type OptionStyle = string | { option: string; selected: string; }; export type ObjectOption = { label: string | number; value?: unknown; title?: string; disabled?: boolean; preselected?: boolean; disabledTitle?: string; selectedTitle?: string; style?: OptionStyle; group?: string; [key: string]: unknown; }; export type PlaceholderConfig = { text: string; persistent?: boolean; }; export interface MultiSelectEvents { onadd?: (data: { option: T; selected: T[]; }) => unknown; oncreate?: (data: { option: T; }) => false | T | undefined; onremove?: (data: { option: T; selected: T[]; }) => unknown; onremoveAll?: (data: { options: T[]; }) => unknown; onselectAll?: (data: { options: T[]; }) => unknown; onreorder?: (data: { options: T[]; previous: T[]; }) => unknown; onchange?: (data: { option?: T; options?: T[]; type: `add` | `remove` | `removeAll` | `selectAll` | `reorder`; }) => unknown; onopen?: (data: { event: Event; }) => unknown; onclose?: (data: { event: Event; }) => unknown; ongroupToggle?: (data: { group: string; collapsed: boolean; }) => unknown; oncollapseAll?: (data: { groups: string[]; }) => unknown; onexpandAll?: (data: { groups: string[]; }) => unknown; onsearch?: (data: { searchText: string; matchingOptions: T[]; }) => unknown; onmaxreached?: (data: { selected: T[]; maxSelect: number; attemptedOption: T; }) => unknown; onduplicate?: (data: { option: T; }) => unknown; onparsed_paste?: (data: { added: T[]; rejected: T[]; overflow: T[]; raw_text: string; }) => unknown; onactivate?: (data: { option: T | null; index: number | null; }) => unknown; onundo?: (data: { previous: T[]; current: T[]; }) => unknown; onredo?: (data: { previous: T[]; current: T[]; }) => unknown; } export interface LoadOptionsParams { search: string; offset: number; limit: number; } export interface LoadOptionsResult { options: T[]; hasMore: boolean; } export type LoadOptionsFn = (params: LoadOptionsParams) => Promise>; export interface LoadOptionsConfig { fetch: LoadOptionsFn; debounceMs?: number; batchSize?: number; onOpen?: boolean; } export type LoadOptions = LoadOptionsFn | LoadOptionsConfig; export type FormSerialize = (selected: T[]) => string | null; type InputSnippetProps = Pick, `selected` | `disabled` | `invalid` | `id` | `open` | `required` | `searchText`> & { placeholder: string | null; }; type UserMsgProps = { searchText: string; msgType: false | `dupe` | `create` | `no-match`; msg: null | string; }; export type GroupHeaderProps = { group: string; options: T[]; collapsed: boolean; }; export type GroupedOptions = { group: string | null; options: T[]; collapsed: boolean; }; export interface MultiSelectSnippets { expandIcon?: Snippet<[{ open: boolean; disabled: boolean; }]>; selectedItem?: Snippet<[{ option: T; idx: number; }]>; children?: Snippet<[{ option: T; idx: number; type: `option` | `selected`; }]>; removeIcon?: Snippet<[ { option: T; isRemoveAll: false; } | { option?: undefined; isRemoveAll: true; } ]>; beforeInput?: Snippet<[InputSnippetProps]>; afterInput?: Snippet<[InputSnippetProps]>; spinner?: Snippet; disabledIcon?: Snippet; option?: Snippet<[ { option: T; idx: number; selected: boolean; active: boolean; disabled: boolean; } ]>; userMsg?: Snippet<[UserMsgProps]>; groupHeader?: Snippet<[GroupHeaderProps]>; } export interface PortalParams { target_node?: HTMLElement | null; active?: boolean; } type InputEventProp = Extract; export type InputProps = Omit; export interface MultiSelectProps extends MultiSelectEvents, MultiSelectSnippets, Omit, `children` | `onchange` | `onclose` | `placeholder`> { activeIndex?: number | null; activeOption?: T | null; createOptionMsg?: string | ((state: { searchText: string; selected: T[]; options: T[]; matchingOptions: T[]; }) => string) | null; allowUserOptions?: boolean | `append`; allowEmpty?: boolean; autocomplete?: HTMLInputAttributes[`autocomplete`]; autoScroll?: boolean; breakpoint?: number; defaultDisabledTitle?: string; disabled?: boolean; disabledInputTitle?: string; duplicateOptionMsg?: string; duplicates?: boolean | `case-insensitive`; expandIconPosition?: `left` | `right` | `none`; keepSelectedInDropdown?: false | `plain` | `checkboxes`; key?: (opt: T) => unknown; filterFunc?: (opt: T, searchText: string) => boolean; fuzzy?: boolean; closeDropdownOnSelect?: boolean | `if-mobile` | `retain-focus`; form_input?: HTMLInputElement | null; formSerialize?: FormSerialize; highlightMatches?: boolean; id?: string | null; input?: HTMLInputElement | null; inputClass?: string; inputProps?: InputProps; inputStyle?: string | null; inputmode?: HTMLInputAttributes[`inputmode`] | null; invalid?: boolean; liActiveOptionClass?: string; liActiveUserMsgClass?: string; liOptionClass?: string; liOptionStyle?: string | null; liSelectedClass?: string; liSelectedStyle?: string | null; liUserMsgClass?: string; loading?: boolean; matchingOptions?: T[]; maxOptions?: number | undefined; maxSelect?: number | null; maxSelectMsg?: ((current: number, max: number) => string) | null; maxSelectMsgClass?: string; name?: string | null; noMatchingOptionsMsg?: string; open?: boolean; options?: T[]; outerDiv?: HTMLDivElement | null; outerDivClass?: string; parseLabelsAsHtml?: boolean; pattern?: string | null; placeholder?: string | PlaceholderConfig | null; removeAllTitle?: string; removeBtnTitle?: string; minSelect?: number | null; required?: boolean | number; resetFilterOnAdd?: boolean; parse_paste?: (text: string) => T[]; searchText?: string; selected?: T[]; selectedDisplay?: `chips` | `input`; sortSelected?: boolean | ((op1: T, op2: T) => number); selectedOptionsDraggable?: boolean; style?: string | null; ulOptionsClass?: string; ulSelectedClass?: string; ulSelectedStyle?: string | null; ulOptionsStyle?: string | null; value?: T | T[] | null; portal?: PortalParams; selectAllOption?: boolean | string; selectAllDisabledTitle?: string | ((state: { max_reached: boolean; maxSelect: number | null; selected_count: number; }) => string) | null; liSelectAllClass?: string; loadOptions?: LoadOptions; selectedFlipParams?: FlipParams; collapsibleGroups?: boolean; collapsedGroups?: Set; groupSelectAll?: boolean; ungroupedPosition?: `first` | `last`; groupSortOrder?: `none` | `asc` | `desc` | ((a: string, b: string) => number); searchExpandsCollapsedGroups?: boolean; searchMatchesGroups?: boolean; keyboardExpandsCollapsedGroups?: boolean; stickyGroupHeaders?: boolean; liGroupHeaderClass?: string; liGroupHeaderStyle?: string | null; collapseAllGroups?: () => void; expandAllGroups?: () => void; shortcuts?: Partial; history?: boolean | number; undo?: () => boolean; redo?: () => boolean; canUndo?: boolean; canRedo?: boolean; } export interface KeyboardShortcuts { select_all?: string | null; clear_all?: string | null; open?: string | null; close?: string | null; undo?: string | null; redo?: string | null; } export interface NavRouteObject { href: string; label?: string; children?: string[]; disabled?: boolean | string; separator?: boolean; align?: `left` | `right`; external?: boolean; tooltip?: string; class?: string; style?: string; [key: string]: unknown; } export type NavRoute = string | [string, string] | [string, string[]] | NavRouteObject; export {};