@plastic-js/tsumiki 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -26,6 +26,12 @@ var Root = (props = {}) => {
|
|
|
26
26
|
const itemToValue = local.itemToValue ?? defaultItemToValue;
|
|
27
27
|
const itemToString = local.itemToString ?? defaultItemToString;
|
|
28
28
|
const filter = local.filter ?? defaultFilter;
|
|
29
|
+
const rawValue = access(rest.value);
|
|
30
|
+
const normalizedValue = rawValue == null ? [] : [rawValue];
|
|
31
|
+
const handleValueChange = (value) => {
|
|
32
|
+
const v = value.length >= 1 ? value[0] : null;
|
|
33
|
+
rest.onValueChange?.(v);
|
|
34
|
+
};
|
|
29
35
|
const query = createSignal(access(local.inputValue) ?? "");
|
|
30
36
|
const filteredItems = createComputed(() => {
|
|
31
37
|
const q = query().trim().toLowerCase();
|
|
@@ -40,6 +46,8 @@ var Root = (props = {}) => {
|
|
|
40
46
|
return jsx(FilterContext.Provider, mergeProps({
|
|
41
47
|
value: filteredItems,
|
|
42
48
|
children: () => jsx(Combobox.Root, mergeProps(rest, {
|
|
49
|
+
value: normalizedValue,
|
|
50
|
+
onValueChange: handleValueChange,
|
|
43
51
|
collection: collection$1,
|
|
44
52
|
inputValue: query,
|
|
45
53
|
onInputValueChange: (value) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilteredSelect.js","names":["Combobox","useComboboxContext","Loop","createComputed","createContext","createEffect","createSignal","splitProps","useContext","collection","createCollection","_tmpl3","_template","_tmpl2","_tmpl","access","value","FilterContext","defaultItemToValue","item","String","id","defaultItemToString","label","name","defaultFilter","query","itemToString","toLowerCase","includes","Root","props","local","rest","itemToValue","filter","inputValue","filteredItems","q","trim","list","items","_jsx","Provider","_mergeProps","children","onInputValueChange","HighlightSingleMatch","combobox","api","open","length","highlightedValue","setHighlightValue","Input","onInput","event","getInputProps","onChange","Items","each","ChevronIcon","cloneNode","CheckIcon","FilteredSelect","cn","classNames","openOnClick","Label","className","Control","control","input","disabled","placeholder","Trigger","trigger","type","Content","content","Empty","empty","emptyText","Item","key","ItemText","itemText","_el0","_insert","_setProp","check"],"sources":["../../src/components/FilteredSelect.jsx"],"sourcesContent":["import { Combobox, useComboboxContext } from '@plastic-js/ark'\nimport {\n\tLoop, createComputed, createContext, createEffect, createSignal, splitProps, useContext,\n} from '@plastic-js/plastic'\nimport { collection as createCollection } from '@zag-js/combobox'\n\n// FilteredSelect — a filterable single-select built on the pure `Combobox`\n// primitive's underlying headless machine.\n//\n// This file owns two things:\n// 1. The filter plumbing. The headless component is \"controlled collection\"\n// only: it expects you to build a @zag-js collection yourself and narrow it\n// down as the user types. The internal <Root> keeps a query in sync with the\n// input, filters the list and feeds a reactive collection back to the\n// headless Root.\n// 2. The public API / contract. The default-exported <FilteredSelect> assembles\n// the full structure (label, control, input, trigger, content, items) and\n// exposes a flat prop API. It is intentionally style-agnostic: every visual\n// slot is themed through the `classNames` map, so the styling layer\n// only has to supply CSS.\n\nconst access = (value)=> {\n\treturn typeof value === 'function' ? value() : value\n}\n\n// Exposes the filtered items to <Items> without forcing the caller to thread\n// them through props.\nconst FilterContext = createContext(null)\n\nconst defaultItemToValue = item=> String(item?.value ?? item?.id ?? item)\nconst defaultItemToString = item=> String(item?.label ?? item?.name ?? item)\n\n// Substring match on the item's display string. Override via the `filter` prop\n// for fuzzy/score-based matching.\nconst defaultFilter = (item, query, itemToString)=> itemToString(item).toLowerCase().includes(query)\n\nconst Root = (props = {})=> {\n\tconst [local, rest] = splitProps(props, [\n\t\t'items', 'itemToValue', 'itemToString', 'filter', 'inputValue', 'onInputValueChange', 'children',\n\t])\n\n\tconst itemToValue = local.itemToValue ?? defaultItemToValue\n\tconst itemToString = local.itemToString ?? defaultItemToString\n\tconst filter = local.filter ?? defaultFilter\n\n\t// Internal query mirrors the input. We seed it from any `inputValue` the\n\t// caller passed so an initial/controlled value still filters correctly.\n\tconst query = createSignal(access(local.inputValue) ?? '')\n\n\t// Recomputes on typing and whenever the source `items` change. An empty\n\t// query shows everything; otherwise only the matches survive.\n\tconst filteredItems = createComputed(()=> {\n\t\tconst q = query().trim().toLowerCase()\n\t\tconst list = access(local.items) ?? []\n\t\treturn q ? list.filter(item=> filter(item, q, itemToString)) : list\n\t})\n\n\tconst collection = createComputed(()=> createCollection({\n\t\titems: filteredItems(),\n\t\titemToValue,\n\t\titemToString,\n\t}))\n\n\treturn (\n\t\t<FilterContext.Provider value={filteredItems}>\n\t\t\t<Combobox.Root\n\t\t\t\t{...rest}\n\t\t\t\tcollection={collection}\n\t\t\t\tinputValue={query}\n\t\t\t\tonInputValueChange={(value)=> {\n\t\t\t\t\tquery(value)\n\t\t\t\t\tlocal.onInputValueChange?.(value)\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<HighlightSingleMatch itemToValue={itemToValue} items={filteredItems} />\n\t\t\t\t{local.children}\n\t\t\t</Combobox.Root>\n\t\t</FilterContext.Provider>\n\t)\n}\n\n// When the open list narrows to a single match, pre-highlight it so the user\n// can confirm with Enter/Tab without arrowing down. We nudge the machine's own\n// (uncontrolled) highlight imperatively rather than controlling `highlightedValue`\n// — controlling it would pin the highlight in place and fight the machine, e.g.\n// blocking the highlight-clear on the next keystroke and the select-and-close on\n// Enter. We only set it; the machine still clears/moves it on input and navigation.\nconst HighlightSingleMatch = (props = {})=> {\n\tconst combobox = useComboboxContext()\n\tcreateEffect(()=> {\n\t\tconst api = combobox()\n\t\tconst list = props.items()\n\t\tif (!api.open || list.length !== 1){ return }\n\t\tconst value = props.itemToValue(list[0])\n\t\tif (api.highlightedValue !== value){ api.setHighlightValue(value) }\n\t})\n\treturn null\n}\n\n// The headless input only fires zag's INPUT.CHANGE on the native `change`\n// event — which, unlike React's onChange, fires on blur, not per keystroke. So\n// typing never reached the machine and the list never filtered. We bridge the\n// per-keystroke `input` event to zag's own onChange handler so every character\n// drives the same INPUT.CHANGE (open + filter) behaviour.\nconst Input = (props = {})=> {\n\tconst combobox = useComboboxContext()\n\treturn (\n\t\t<Combobox.Input\n\t\t\t{...props}\n\t\t\tonInput={event=> combobox().getInputProps().onChange?.(event)}\n\t\t/>\n\t)\n}\n\n// Render-prop over the filtered items. Place inside <Combobox.Content> and\n// return a <Combobox.Item> for each match. Backed by <Loop> so the list stays\n// reactive — a bare thunk returned from a component is unwrapped once and would\n// never re-filter.\nconst Items = (props = {})=> {\n\tconst items = useContext(FilterContext)\n\treturn (\n\t\t<Loop each={items ?? []}>\n\t\t\t{item=> props.children?.(item)}\n\t\t</Loop>\n\t)\n}\n\nfunction ChevronIcon(){\n\treturn (\n\t\t<svg\n\t\t\tfill='none' stroke='currentColor' strokeLinecap='round' strokeLinejoin='round'\n\t\t\tstrokeWidth='2' viewBox='0 0 24 24'\n\t\t>\n\t\t\t<polyline points='6 9 12 15 18 9' />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon(){\n\treturn (\n\t\t<svg\n\t\t\tfill='none' stroke='currentColor' strokeLinecap='round' strokeLinejoin='round'\n\t\t\tstrokeWidth='2.5' viewBox='0 0 24 24'\n\t\t>\n\t\t\t<polyline points='20 6 9 17 4 12' />\n\t\t</svg>\n\t)\n}\n\n// Public component. `classNames` themes each slot (control/input/trigger/content/\n// empty/item/itemText/check/label); anything not split here (e.g. `filter`,\n// `name`) flows through to the filter Root.\nconst FilteredSelect = (props = {})=> {\n\tconst [local, rest] = splitProps(props, [\n\t\t'items',\n\t\t'itemToString',\n\t\t'itemToValue',\n\t\t'placeholder',\n\t\t'label',\n\t\t'openOnClick',\n\t\t'disabled',\n\t\t'classNames',\n\t\t'emptyText',\n\t])\n\n\tconst cn = local.classNames ?? {}\n\n\t// `value`, `onValueChange`, `filter`, `name`, … are not transformed here, so\n\t// they ride `rest` straight through to the underlying machine.\n\treturn (\n\t\t<Root\n\t\t\titemToString={local.itemToString}\n\t\t\titemToValue={local.itemToValue}\n\t\t\titems={local.items}\n\t\t\topenOnClick={local.openOnClick ?? true}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{local.label && (\n\t\t\t\t<Combobox.Label className={cn.label}>\n\t\t\t\t\t{local.label}\n\t\t\t\t</Combobox.Label>\n\t\t\t)}\n\t\t\t<Combobox.Control className={cn.control}>\n\t\t\t\t<Input\n\t\t\t\t\tclassName={cn.input}\n\t\t\t\t\tdisabled={local.disabled}\n\t\t\t\t\tplaceholder={local.placeholder ?? 'Type to search...'}\n\t\t\t\t/>\n\t\t\t\t<Combobox.Trigger className={cn.trigger} type='button'>\n\t\t\t\t\t<ChevronIcon />\n\t\t\t\t</Combobox.Trigger>\n\t\t\t</Combobox.Control>\n\t\t\t<Combobox.Content className={cn.content}>\n\t\t\t\t<Combobox.Empty className={cn.empty}>\n\t\t\t\t\t{local.emptyText ?? 'No results found'}\n\t\t\t\t</Combobox.Empty>\n\t\t\t\t<Items>\n\t\t\t\t\t{item=> (\n\t\t\t\t\t\t<Combobox.Item className={cn.item} item={item} key={local.itemToValue?.(item) ?? item}>\n\t\t\t\t\t\t\t<Combobox.ItemText className={cn.itemText}>\n\t\t\t\t\t\t\t\t{local.itemToString?.(item) ?? String(item)}\n\t\t\t\t\t\t\t</Combobox.ItemText>\n\t\t\t\t\t\t\t<span className={cn.check}>\n\t\t\t\t\t\t\t\t<CheckIcon />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Combobox.Item>\n\t\t\t\t\t)}\n\t\t\t\t</Items>\n\t\t\t</Combobox.Content>\n\t\t</Root>\n\t)\n}\n\nexport default FilteredSelect\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FilteredSelect.js","names":["Combobox","useComboboxContext","Loop","createComputed","createContext","createEffect","createSignal","splitProps","useContext","collection","createCollection","_tmpl3","_template","_tmpl2","_tmpl","access","value","FilterContext","defaultItemToValue","item","String","id","defaultItemToString","label","name","defaultFilter","query","itemToString","toLowerCase","includes","Root","props","local","rest","itemToValue","filter","rawValue","normalizedValue","handleValueChange","v","length","onValueChange","inputValue","filteredItems","q","trim","list","items","_jsx","Provider","_mergeProps","children","onInputValueChange","HighlightSingleMatch","combobox","api","open","highlightedValue","setHighlightValue","Input","onInput","event","getInputProps","onChange","Items","each","ChevronIcon","cloneNode","CheckIcon","FilteredSelect","cn","classNames","openOnClick","Label","className","Control","control","input","disabled","placeholder","Trigger","trigger","type","Content","content","Empty","empty","emptyText","Item","key","ItemText","itemText","_el0","_insert","_setProp","check"],"sources":["../../src/components/FilteredSelect.jsx"],"sourcesContent":["import { Combobox, useComboboxContext } from '@plastic-js/ark'\nimport {\n\tLoop, createComputed, createContext, createEffect, createSignal, splitProps, useContext,\n} from '@plastic-js/plastic'\nimport { collection as createCollection } from '@zag-js/combobox'\n\n// FilteredSelect — a filterable single-select built on the pure `Combobox`\n// primitive's underlying headless machine.\n//\n// This file owns two things:\n// 1. The filter plumbing. The headless component is \"controlled collection\"\n// only: it expects you to build a @zag-js collection yourself and narrow it\n// down as the user types. The internal <Root> keeps a query in sync with the\n// input, filters the list and feeds a reactive collection back to the\n// headless Root.\n// 2. The public API / contract. The default-exported <FilteredSelect> assembles\n// the full structure (label, control, input, trigger, content, items) and\n// exposes a flat prop API. It is intentionally style-agnostic: every visual\n// slot is themed through the `classNames` map, so the styling layer\n// only has to supply CSS.\n\nconst access = (value)=> {\n\treturn typeof value === 'function' ? value() : value\n}\n\n// Exposes the filtered items to <Items> without forcing the caller to thread\n// them through props.\nconst FilterContext = createContext(null)\n\nconst defaultItemToValue = item=> String(item?.value ?? item?.id ?? item)\nconst defaultItemToString = item=> String(item?.label ?? item?.name ?? item)\n\n// Substring match on the item's display string. Override via the `filter` prop\n// for fuzzy/score-based matching.\nconst defaultFilter = (item, query, itemToString)=> itemToString(item).toLowerCase().includes(query)\n\nconst Root = (props = {})=> {\n\tconst [local, rest] = splitProps(props, [\n\t\t'items', 'itemToValue', 'itemToString', 'filter', 'inputValue', 'onInputValueChange', 'children',\n\t])\n\n\tconst itemToValue = local.itemToValue ?? defaultItemToValue\n\tconst itemToString = local.itemToString ?? defaultItemToString\n\tconst filter = local.filter ?? defaultFilter\n\n\t// zag-js/combobox expects value to be an array (it calls .join(\",\")).\n\t// Single-select means a 0‑ or 1‑element array.\n\tconst rawValue = access(rest.value)\n\tconst normalizedValue = rawValue == null ? [] : [rawValue]\n\n\tconst handleValueChange = (value)=> {\n\t\tconst v = value.length >= 1 ? value[0] : null\n\t\trest.onValueChange?.(v)\n\t}\n\n\t// Internal query mirrors the input. We seed it from any `inputValue` the\n\t// caller passed so an initial/controlled value still filters correctly.\n\tconst query = createSignal(access(local.inputValue) ?? '')\n\n\t// Recomputes on typing and whenever the source `items` change. An empty\n\t// query shows everything; otherwise only the matches survive.\n\tconst filteredItems = createComputed(()=> {\n\t\tconst q = query().trim().toLowerCase()\n\t\tconst list = access(local.items) ?? []\n\t\treturn q ? list.filter(item=> filter(item, q, itemToString)) : list\n\t})\n\n\tconst collection = createComputed(()=> createCollection({\n\t\titems: filteredItems(),\n\t\titemToValue,\n\t\titemToString,\n\t}))\n\n\treturn (\n\t\t<FilterContext.Provider value={filteredItems}>\n\t\t\t<Combobox.Root\n\t\t\t\t{...rest}\n\t\t\t\tvalue={normalizedValue}\n\t\t\t\tonValueChange={handleValueChange}\n\t\t\t\tcollection={collection}\n\t\t\t\tinputValue={query}\n\t\t\t\tonInputValueChange={(value)=> {\n\t\t\t\t\tquery(value)\n\t\t\t\t\tlocal.onInputValueChange?.(value)\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<HighlightSingleMatch itemToValue={itemToValue} items={filteredItems} />\n\t\t\t\t{local.children}\n\t\t\t</Combobox.Root>\n\t\t</FilterContext.Provider>\n\t)\n}\n\n// When the open list narrows to a single match, pre-highlight it so the user\n// can confirm with Enter/Tab without arrowing down. We nudge the machine's own\n// (uncontrolled) highlight imperatively rather than controlling `highlightedValue`\n// — controlling it would pin the highlight in place and fight the machine, e.g.\n// blocking the highlight-clear on the next keystroke and the select-and-close on\n// Enter. We only set it; the machine still clears/moves it on input and navigation.\nconst HighlightSingleMatch = (props = {})=> {\n\tconst combobox = useComboboxContext()\n\tcreateEffect(()=> {\n\t\tconst api = combobox()\n\t\tconst list = props.items()\n\t\tif (!api.open || list.length !== 1){ return }\n\t\tconst value = props.itemToValue(list[0])\n\t\tif (api.highlightedValue !== value){ api.setHighlightValue(value) }\n\t})\n\treturn null\n}\n\n// The headless input only fires zag's INPUT.CHANGE on the native `change`\n// event — which, unlike React's onChange, fires on blur, not per keystroke. So\n// typing never reached the machine and the list never filtered. We bridge the\n// per-keystroke `input` event to zag's own onChange handler so every character\n// drives the same INPUT.CHANGE (open + filter) behaviour.\nconst Input = (props = {})=> {\n\tconst combobox = useComboboxContext()\n\treturn (\n\t\t<Combobox.Input\n\t\t\t{...props}\n\t\t\tonInput={event=> combobox().getInputProps().onChange?.(event)}\n\t\t/>\n\t)\n}\n\n// Render-prop over the filtered items. Place inside <Combobox.Content> and\n// return a <Combobox.Item> for each match. Backed by <Loop> so the list stays\n// reactive — a bare thunk returned from a component is unwrapped once and would\n// never re-filter.\nconst Items = (props = {})=> {\n\tconst items = useContext(FilterContext)\n\treturn (\n\t\t<Loop each={items ?? []}>\n\t\t\t{item=> props.children?.(item)}\n\t\t</Loop>\n\t)\n}\n\nfunction ChevronIcon(){\n\treturn (\n\t\t<svg\n\t\t\tfill='none' stroke='currentColor' strokeLinecap='round' strokeLinejoin='round'\n\t\t\tstrokeWidth='2' viewBox='0 0 24 24'\n\t\t>\n\t\t\t<polyline points='6 9 12 15 18 9' />\n\t\t</svg>\n\t)\n}\n\nfunction CheckIcon(){\n\treturn (\n\t\t<svg\n\t\t\tfill='none' stroke='currentColor' strokeLinecap='round' strokeLinejoin='round'\n\t\t\tstrokeWidth='2.5' viewBox='0 0 24 24'\n\t\t>\n\t\t\t<polyline points='20 6 9 17 4 12' />\n\t\t</svg>\n\t)\n}\n\n// Public component. `classNames` themes each slot (control/input/trigger/content/\n// empty/item/itemText/check/label); anything not split here (e.g. `filter`,\n// `name`) flows through to the filter Root.\nconst FilteredSelect = (props = {})=> {\n\tconst [local, rest] = splitProps(props, [\n\t\t'items',\n\t\t'itemToString',\n\t\t'itemToValue',\n\t\t'placeholder',\n\t\t'label',\n\t\t'openOnClick',\n\t\t'disabled',\n\t\t'classNames',\n\t\t'emptyText',\n\t])\n\n\tconst cn = local.classNames ?? {}\n\n\t// `value`, `onValueChange`, `filter`, `name`, … are not transformed here, so\n\t// they ride `rest` straight through to the underlying machine.\n\treturn (\n\t\t<Root\n\t\t\titemToString={local.itemToString}\n\t\t\titemToValue={local.itemToValue}\n\t\t\titems={local.items}\n\t\t\topenOnClick={local.openOnClick ?? true}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{local.label && (\n\t\t\t\t<Combobox.Label className={cn.label}>\n\t\t\t\t\t{local.label}\n\t\t\t\t</Combobox.Label>\n\t\t\t)}\n\t\t\t<Combobox.Control className={cn.control}>\n\t\t\t\t<Input\n\t\t\t\t\tclassName={cn.input}\n\t\t\t\t\tdisabled={local.disabled}\n\t\t\t\t\tplaceholder={local.placeholder ?? 'Type to search...'}\n\t\t\t\t/>\n\t\t\t\t<Combobox.Trigger className={cn.trigger} type='button'>\n\t\t\t\t\t<ChevronIcon />\n\t\t\t\t</Combobox.Trigger>\n\t\t\t</Combobox.Control>\n\t\t\t<Combobox.Content className={cn.content}>\n\t\t\t\t<Combobox.Empty className={cn.empty}>\n\t\t\t\t\t{local.emptyText ?? 'No results found'}\n\t\t\t\t</Combobox.Empty>\n\t\t\t\t<Items>\n\t\t\t\t\t{item=> (\n\t\t\t\t\t\t<Combobox.Item className={cn.item} item={item} key={local.itemToValue?.(item) ?? item}>\n\t\t\t\t\t\t\t<Combobox.ItemText className={cn.itemText}>\n\t\t\t\t\t\t\t\t{local.itemToString?.(item) ?? String(item)}\n\t\t\t\t\t\t\t</Combobox.ItemText>\n\t\t\t\t\t\t\t<span className={cn.check}>\n\t\t\t\t\t\t\t\t<CheckIcon />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</Combobox.Item>\n\t\t\t\t\t)}\n\t\t\t\t</Items>\n\t\t\t</Combobox.Content>\n\t\t</Root>\n\t)\n}\n\nexport default FilteredSelect\n"],"mappings":"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"}
|