{"version":3,"names":["createContext","createMemo","runWithOwner","useContext","createCollatorItemFilter","getFilter","isGroupedItems","stringifyAsLabel","readOption","SNAPSHOT_KEYS","snapshotKeys","AutocompleteCtx","useAutocomplete","ctx","Error","createAutocomplete","options","mode","name","disabled","Boolean","readOnly","itemToStringLabel","value","open","items","isGrouped","query","trim","isStaticItems","m","collatorFilter","locale","resolvedFilter","userFilter","filter","undefined","filteredItems","list","filt","q","label","groups","out","g","candidates","item","length","push","flatFilteredItems","fi","flatMap","itemLabel","setValue","next","reason","onValueChange","setOpen","onOpenChange","api","Provider","props","children","AUTOCOMPLETE_SNAPSHOT_KEYS"],"sources":["create-autocomplete.tsx"],"sourcesContent":["import type { JSX } from \"@solidjs/web\";\nimport {\n\ttype Accessor,\n\tcreateContext,\n\tcreateMemo,\n\trunWithOwner,\n\tuseContext,\n} from \"solid-js\";\nimport {\n\tcreateCollatorItemFilter,\n\ttype Filter,\n\tgetFilter,\n} from \"../combobox/internals/filter\";\nimport {\n\ttype Group,\n\tisGroupedItems,\n\tstringifyAsLabel,\n} from \"../combobox/internals/resolve-value-label\";\nimport { type MaybeAccessor, readOption } from \"../internals/maybe-accessor\";\nimport {\n\tSNAPSHOT_KEYS,\n\ttype Snapshottable,\n\tsnapshotKeys,\n} from \"../internals/observability/snapshot\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type AutocompleteMode = \"list\" | \"both\" | \"inline\" | \"none\";\n\nexport type AutocompleteChangeReason =\n\t| \"item-press\"\n\t| \"input-change\"\n\t| \"escape-key\"\n\t| \"outside-press\"\n\t| \"imperative\";\n\nexport interface CreateAutocompleteOptions<Value = unknown> {\n\t/**\n\t * Input value (the text in the autocomplete input). Consumer-owned signal.\n\t * Writes happen via `onValueChange` — the primitive does NOT keep an internal\n\t * copy.\n\t */\n\tvalue: MaybeAccessor<string | undefined>;\n\tonValueChange?: (value: string, reason: AutocompleteChangeReason) => void;\n\n\t/** Open state. Consumer-owned signal. */\n\topen: MaybeAccessor<boolean>;\n\tonOpenChange?: (open: boolean, reason: AutocompleteChangeReason) => void;\n\n\t/** Items to filter. Flat array or grouped (`{ items: [...] }`). */\n\titems?: MaybeAccessor<readonly Value[] | readonly Group<Value>[] | undefined>;\n\n\t/**\n\t * Filter function. Pass `null` to disable filtering. Defaults to an\n\t * `Intl.Collator`-backed \"contains\" filter.\n\t */\n\tfilter?:\n\t\t| MaybeAccessor<\n\t\t\t\t| ((\n\t\t\t\t\t\titem: Value,\n\t\t\t\t\t\tquery: string,\n\t\t\t\t\t\titemToStringLabel?: (item: Value) => string,\n\t\t\t\t  ) => boolean)\n\t\t\t\t| null\n\t\t\t\t| undefined\n\t\t  >\n\t\t| undefined;\n\n\t/** Locale for the default `Intl.Collator`. */\n\tlocale?: MaybeAccessor<Intl.LocalesArgument | undefined>;\n\n\t/**\n\t * Filtering and inline-autocomplete mode.\n\t * @default \"list\"\n\t */\n\tmode?: MaybeAccessor<AutocompleteMode | undefined>;\n\n\tdisabled?: MaybeAccessor<boolean | undefined>;\n\treadOnly?: MaybeAccessor<boolean | undefined>;\n\n\t/** Converts object items to a display string. */\n\titemToStringLabel?: MaybeAccessor<((item: Value) => string) | undefined>;\n\t/** Custom item equality. Defaults to `Object.is`. */\n\tisItemEqualToValue?: MaybeAccessor<\n\t\t((item: Value, value: Value) => boolean) | undefined\n\t>;\n}\n\nexport interface AutocompleteApi<Value = unknown> {\n\t/** Reactive accessor for the current input value. */\n\tvalue: Accessor<string>;\n\t/** Reactive accessor for the open state. */\n\topen: Accessor<boolean>;\n\n\t/** Current mode. */\n\tmode: Accessor<AutocompleteMode>;\n\tdisabled: Accessor<boolean>;\n\treadOnly: Accessor<boolean>;\n\n\t/** All items (before filtering). */\n\titems: Accessor<readonly Value[] | readonly Group<Value>[] | undefined>;\n\t/** Items after applying the filter against the current query. */\n\tfilteredItems: Accessor<readonly Value[] | readonly Group<Value>[]>;\n\t/** Flat version of `filteredItems` (groups are unwrapped). */\n\tflatFilteredItems: Accessor<readonly Value[]>;\n\t/** Trimmed query string used for filtering. */\n\tquery: Accessor<string>;\n\t/** Whether the items list is grouped. */\n\tisGrouped: Accessor<boolean>;\n\n\t/** Label accessor for rendering item text. */\n\titemLabel: (item: Value) => string;\n\n\t/** Pure event-emitter — fire `onValueChange`. Consumer owns the signal write. */\n\tsetValue: (next: string, reason?: AutocompleteChangeReason) => void;\n\t/** Pure event-emitter — fire `onOpenChange`. */\n\tsetOpen: (next: boolean, reason?: AutocompleteChangeReason) => void;\n\n\t/**\n\t * Context provider. Wrap a subtree to make the api discoverable via\n\t * `useAutocomplete()` without prop-drilling.\n\t */\n\tProvider: (props: { children: JSX.Element }) => JSX.Element;\n}\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst AutocompleteCtx = createContext<AutocompleteApi<unknown> | null>(null);\n\nexport function useAutocomplete<Value = unknown>(): AutocompleteApi<Value> {\n\tconst ctx = useContext(AutocompleteCtx);\n\tif (ctx == null) {\n\t\tthrow new Error(\n\t\t\t\"Base UI: useAutocomplete() must be called inside a <c.Provider>.\",\n\t\t);\n\t}\n\treturn ctx as AutocompleteApi<Value>;\n}\n\n// ---------------------------------------------------------------------------\n// Primitive\n// ---------------------------------------------------------------------------\n\n/**\n * Solid 2-native headless primitive for autocomplete selection + filtering\n * logic. Autocomplete is the \"input value is the source of truth\" variant:\n * there is no separate selected-value state — the input text IS the value.\n * Owns: value / open state, items / filteredItems / query derivation, and\n * item label helpers. DOM concerns (floating-ui, input element, keyboard nav,\n * portal) live in the structural `<Autocomplete.Root>` wrapper.\n */\nexport function createAutocomplete<Value = unknown>(\n\toptions: CreateAutocompleteOptions<Value>,\n): AutocompleteApi<Value> {\n\tconst mode = createMemo<AutocompleteMode>(\n\t\t() => (readOption(options.mode) ?? \"list\") as AutocompleteMode,\n\t\t{ name: \"autocomplete.mode\" },\n\t);\n\n\tconst disabled = createMemo<boolean>(\n\t\t() => Boolean(readOption(options.disabled)),\n\t\t{ name: \"autocomplete.disabled\" },\n\t);\n\n\tconst readOnly = createMemo<boolean>(\n\t\t() => Boolean(readOption(options.readOnly)),\n\t\t{ name: \"autocomplete.readOnly\" },\n\t);\n\n\tconst itemToStringLabel = createMemo<((item: Value) => string) | undefined>(\n\t\t() => readOption(options.itemToStringLabel),\n\t\t{ name: \"autocomplete.itemToStringLabel\" },\n\t);\n\n\t// Value — reads through the consumer's accessor (defaults to \"\").\n\tconst value = createMemo<string>(() => readOption(options.value) ?? \"\", {\n\t\tname: \"autocomplete.value\",\n\t});\n\n\t// Open — reads through the consumer's accessor.\n\tconst open = createMemo<boolean>(() => Boolean(readOption(options.open)), {\n\t\tname: \"autocomplete.open\",\n\t});\n\n\t// Items\n\tconst items = createMemo<\n\t\treadonly Value[] | readonly Group<Value>[] | undefined\n\t>(() => readOption(options.items), { name: \"autocomplete.items\" });\n\n\tconst isGrouped = createMemo<boolean>(\n\t\t() => isGroupedItems(items() as unknown[]),\n\t\t{ name: \"autocomplete.isGrouped\" },\n\t);\n\n\t// In \"both\" mode we filter against the typed value (not any inline-autocomplete\n\t// overlay). The query is the trimmed text.\n\tconst query = createMemo<string>(() => value().trim(), {\n\t\tname: \"autocomplete.query\",\n\t});\n\n\t// Filtering — \"inline\" and \"none\" modes show all items unfiltered.\n\tconst isStaticItems = createMemo<boolean>(() => {\n\t\tconst m = mode();\n\t\treturn m === \"inline\" || m === \"none\";\n\t});\n\n\tconst collatorFilter = createMemo<Filter>(\n\t\t() => getFilter({ locale: readOption(options.locale) }),\n\t\t{ name: \"autocomplete.collatorFilter\" },\n\t);\n\n\tconst resolvedFilter = createMemo<\n\t\t(\n\t\t\titem: Value,\n\t\t\tquery: string,\n\t\t\titemToStringLabel?: (item: Value) => string,\n\t\t) => boolean\n\t>(\n\t\t() => {\n\t\t\tif (isStaticItems()) return () => true;\n\t\t\tconst userFilter = readOption(options.filter) as\n\t\t\t\t| ((item: Value, q: string) => boolean)\n\t\t\t\t| null\n\t\t\t\t| undefined;\n\t\t\tif (userFilter === null) return () => true;\n\t\t\tif (userFilter !== undefined) return userFilter;\n\t\t\treturn createCollatorItemFilter(\n\t\t\t\tcollatorFilter(),\n\t\t\t\titemToStringLabel() as ((item: unknown) => string) | undefined,\n\t\t\t) as (item: Value, q: string) => boolean;\n\t\t},\n\t\t{ name: \"autocomplete.resolvedFilter\" },\n\t);\n\n\tconst filteredItems = createMemo<readonly Value[] | readonly Group<Value>[]>(\n\t\t() => {\n\t\t\tconst list = items();\n\t\t\tif (!list) return [];\n\t\t\tconst filt = resolvedFilter();\n\t\t\tconst q = query();\n\t\t\tconst label = itemToStringLabel();\n\t\t\tif (isGrouped()) {\n\t\t\t\tconst groups = list as ReadonlyArray<Group<Value>>;\n\t\t\t\tconst out: Group<Value>[] = [];\n\t\t\t\tfor (const g of groups) {\n\t\t\t\t\tconst candidates =\n\t\t\t\t\t\tq === \"\" ? g.items : g.items.filter((item) => filt(item, q, label));\n\t\t\t\t\tif (candidates.length > 0) {\n\t\t\t\t\t\tout.push({ ...g, items: candidates });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn out;\n\t\t\t}\n\t\t\tif (q === \"\") return list as readonly Value[];\n\t\t\treturn (list as readonly Value[]).filter((item) => filt(item, q, label));\n\t\t},\n\t\t{ name: \"autocomplete.filteredItems\" },\n\t);\n\n\tconst flatFilteredItems = createMemo<readonly Value[]>(\n\t\t() => {\n\t\t\tconst fi = filteredItems();\n\t\t\tif (isGrouped()) {\n\t\t\t\treturn (fi as ReadonlyArray<Group<Value>>).flatMap(\n\t\t\t\t\t(g) => g.items as Value[],\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn fi as readonly Value[];\n\t\t},\n\t\t{ name: \"autocomplete.flatFilteredItems\" },\n\t);\n\n\tconst itemLabel = (item: Value): string =>\n\t\tstringifyAsLabel(\n\t\t\titem,\n\t\t\titemToStringLabel() as ((item: unknown) => string) | undefined,\n\t\t);\n\n\t// Pure event-emitters — runWithOwner(null, ...) escapes the reactive owner\n\t// so signal writes inside the callback don't trigger SIGNAL_WRITE_IN_OWNED_SCOPE.\n\tconst setValue = (\n\t\tnext: string,\n\t\treason: AutocompleteChangeReason = \"imperative\",\n\t): void => {\n\t\trunWithOwner(null, () => options.onValueChange?.(next, reason));\n\t};\n\n\tconst setOpen = (\n\t\tnext: boolean,\n\t\treason: AutocompleteChangeReason = \"imperative\",\n\t): void => {\n\t\trunWithOwner(null, () => options.onOpenChange?.(next, reason));\n\t};\n\n\tconst api: AutocompleteApi<Value> = {\n\t\tvalue,\n\t\topen,\n\t\tmode,\n\t\tdisabled,\n\t\treadOnly,\n\t\titems,\n\t\tfilteredItems,\n\t\tflatFilteredItems,\n\t\tquery,\n\t\tisGrouped,\n\t\titemLabel,\n\t\tsetValue,\n\t\tsetOpen,\n\t\tProvider: (props) => (\n\t\t\t<AutocompleteCtx value={api as AutocompleteApi<unknown>}>\n\t\t\t\t{props.children}\n\t\t\t</AutocompleteCtx>\n\t\t),\n\t};\n\n\t(api as AutocompleteApi<Value> & Snapshottable)[SNAPSHOT_KEYS] =\n\t\tAUTOCOMPLETE_SNAPSHOT_KEYS;\n\n\treturn api;\n}\n\nconst AUTOCOMPLETE_SNAPSHOT_KEYS = snapshotKeys<AutocompleteApi>(\n\t\"value\",\n\t\"open\",\n\t\"mode\",\n\t\"disabled\",\n\t\"readOnly\",\n\t\"query\",\n);\n"],"mappings":"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","ignoreList":[]}