UNPKG

slim-select

Version:

Slim advanced select dropdown

87 lines (86 loc) 3.44 kB
import { default as Render } from './render'; import { default as Select } from './select'; import { default as Store, Optgroup, Option } from './store'; /** Where a change originated — affects batching and render behavior. */ export type ChangeSource = 'native' | 'ui' | 'api'; export interface SyncEvents { afterChange?: (newVal: Option[]) => void; error?: (err: Error) => void; } /** * A single unit of work in the sync queue. * Structure = replace option list; selection = change selected only; addOption = append one. */ export type SyncChange = { type: 'structure'; data: (Partial<Option> | Partial<Optgroup>)[]; source: ChangeSource; /** Keep current selection when replacing data (async search results). */ preserveSelection?: boolean; /** API search results — do not update the catalog baseline. */ isSearchResult?: boolean; } | { type: 'selection'; values: string | string[]; source: ChangeSource; /** false when Vue/parent is pushing modelValue down (avoid emit loop). */ runAfterChange?: boolean; } | { type: 'addOption'; option: Partial<Option>; source: ChangeSource; }; export interface SyncDeps { select: Select; store: Store; render: Render; events: SyncEvents; search?: (value: string) => void; onError?: (err: Error) => void; } /** Skip structure sync when incoming data matches what's already in the store. */ export declare function shouldSkipStructureUpdate(store: Store, data: (Partial<Option> | Partial<Optgroup>)[]): boolean; /** * Resolve setSelected() arguments to option ids. * Accepts either ids or values for backward compatibility. */ export declare function resolveSelectedIds(store: Store, values: string | string[]): string[]; export default class SyncCoordinator { private deps; private queue; private flushScheduled; /** True while applyChange is running — prevents re-entrant flush loops. */ isSyncing: boolean; constructor(deps: SyncDeps); enqueue(change: SyncChange): void; /** Process everything in the queue. Callable from tests for deterministic native sync. */ flush(): void; /** * Collapse a batch into the minimum work needed. * Structure sync already includes selection from getData(), so drop redundant * selection changes in the same batch. When multiple structure updates arrive, * only the last one wins. */ private coalesceBatch; private applyChange; /** * Full sync: store → native <select> rebuild → render values + options. * Used when the option list itself changes (setData, native DOM edits). * API search results update store + UI only — native select stays form/selection state. */ private applyStructure; /** * Sync native <select> to current selection (form truth). * When selected options are missing from the native DOM (e.g. picked from API * search results), rebuild from selected options only — never from search hits. */ private syncNativeSelection; /** * Lightweight selection sync: flip option.selected on native DOM only. * Avoids select.updateOptions() (innerHTML rebuild) for selection-only changes * when the options already exist on the native select. */ private applySelection; /** Append a single option then full-sync native + render (same as legacy addOption). */ private applyAddOption; }