@k2b/ui 0.39.0 → 0.41.0

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.
Files changed (98) hide show
  1. package/dist/browser/chat/ChatComposer.js +759 -570
  2. package/dist/browser/chat/ChatComposer.js.map +1 -1
  3. package/dist/browser/inputs/ChoiceGroups.js +30 -18
  4. package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
  5. package/dist/browser/inputs/Select.js +32 -19
  6. package/dist/browser/inputs/Select.js.map +1 -1
  7. package/dist/browser/inputs/SpecialInputs.js +54 -25
  8. package/dist/browser/inputs/SpecialInputs.js.map +1 -1
  9. package/dist/browser/inputs/choice.js +4 -1
  10. package/dist/browser/inputs/choice.js.map +1 -1
  11. package/dist/browser/inputs/dictation/Dictation.js +546 -0
  12. package/dist/browser/inputs/dictation/Dictation.js.map +1 -0
  13. package/dist/browser/inputs/dictation/create-dictation.js +324 -0
  14. package/dist/browser/inputs/dictation/create-dictation.js.map +1 -0
  15. package/dist/browser/inputs/dictation/dictation-messages.js +115 -0
  16. package/dist/browser/inputs/dictation/dictation-messages.js.map +1 -0
  17. package/dist/browser/inputs/dictation/text-dictation.js +152 -0
  18. package/dist/browser/inputs/dictation/text-dictation.js.map +1 -0
  19. package/dist/browser/inputs/dictation/types.js +2 -0
  20. package/dist/browser/inputs/dictation/types.js.map +1 -0
  21. package/dist/browser/inputs/icon-messages.js +29 -2
  22. package/dist/browser/inputs/icon-messages.js.map +1 -1
  23. package/dist/browser/inputs/icon-texts.js +172 -0
  24. package/dist/browser/inputs/icon-texts.js.map +1 -0
  25. package/dist/browser/inputs/index.js +2 -0
  26. package/dist/browser/inputs/index.js.map +1 -1
  27. package/dist/browser/layout/AnchoredPopover.js +1 -1
  28. package/dist/browser/layout/AnchoredPopover.js.map +1 -1
  29. package/dist/browser/layout/AppWorkspace.js +31 -17
  30. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  31. package/dist/browser/layout/SettingsModal.js +10 -5
  32. package/dist/browser/layout/SettingsModal.js.map +1 -1
  33. package/dist/browser/layout/app-workspace-controller.js +49 -5
  34. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  35. package/dist/browser/text-editor/TextEditor.js +74 -25
  36. package/dist/browser/text-editor/TextEditor.js.map +1 -1
  37. package/dist/browser/text-editor/dictation.js +166 -0
  38. package/dist/browser/text-editor/dictation.js.map +1 -0
  39. package/dist/browser/text-editor.js +1 -0
  40. package/dist/browser/text-editor.js.map +1 -1
  41. package/dist/ssr/chat/ChatComposer.js +271 -99
  42. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  43. package/dist/ssr/inputs/ChoiceGroups.js +12 -3
  44. package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
  45. package/dist/ssr/inputs/Select.js +8 -2
  46. package/dist/ssr/inputs/Select.js.map +1 -1
  47. package/dist/ssr/inputs/SpecialInputs.js +54 -25
  48. package/dist/ssr/inputs/SpecialInputs.js.map +1 -1
  49. package/dist/ssr/inputs/choice.js +4 -1
  50. package/dist/ssr/inputs/choice.js.map +1 -1
  51. package/dist/ssr/inputs/dictation/Dictation.js +386 -0
  52. package/dist/ssr/inputs/dictation/Dictation.js.map +1 -0
  53. package/dist/ssr/inputs/dictation/create-dictation.js +324 -0
  54. package/dist/ssr/inputs/dictation/create-dictation.js.map +1 -0
  55. package/dist/ssr/inputs/dictation/dictation-messages.js +115 -0
  56. package/dist/ssr/inputs/dictation/dictation-messages.js.map +1 -0
  57. package/dist/ssr/inputs/dictation/text-dictation.js +152 -0
  58. package/dist/ssr/inputs/dictation/text-dictation.js.map +1 -0
  59. package/dist/ssr/inputs/dictation/types.js +2 -0
  60. package/dist/ssr/inputs/dictation/types.js.map +1 -0
  61. package/dist/ssr/inputs/icon-messages.js +29 -2
  62. package/dist/ssr/inputs/icon-messages.js.map +1 -1
  63. package/dist/ssr/inputs/icon-texts.js +172 -0
  64. package/dist/ssr/inputs/icon-texts.js.map +1 -0
  65. package/dist/ssr/inputs/index.js +2 -0
  66. package/dist/ssr/inputs/index.js.map +1 -1
  67. package/dist/ssr/layout/AnchoredPopover.js +1 -1
  68. package/dist/ssr/layout/AnchoredPopover.js.map +1 -1
  69. package/dist/ssr/layout/AppWorkspace.js +31 -17
  70. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  71. package/dist/ssr/layout/SettingsModal.js +10 -5
  72. package/dist/ssr/layout/SettingsModal.js.map +1 -1
  73. package/dist/ssr/layout/app-workspace-controller.js +49 -5
  74. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  75. package/dist/ssr/text-editor/TextEditor.js +74 -25
  76. package/dist/ssr/text-editor/TextEditor.js.map +1 -1
  77. package/dist/ssr/text-editor/dictation.js +166 -0
  78. package/dist/ssr/text-editor/dictation.js.map +1 -0
  79. package/dist/ssr/text-editor.js +1 -0
  80. package/dist/ssr/text-editor.js.map +1 -1
  81. package/dist/styles.css +1 -1
  82. package/dist/types/chat/ChatComposer.d.ts +9 -0
  83. package/dist/types/inputs/SpecialInputs.d.ts +8 -0
  84. package/dist/types/inputs/dictation/Dictation.d.ts +26 -0
  85. package/dist/types/inputs/dictation/create-dictation.d.ts +77 -0
  86. package/dist/types/inputs/dictation/dictation-messages.d.ts +54 -0
  87. package/dist/types/inputs/dictation/text-dictation.d.ts +36 -0
  88. package/dist/types/inputs/dictation/types.d.ts +74 -0
  89. package/dist/types/inputs/icon-messages.d.ts +14 -0
  90. package/dist/types/inputs/icon-texts.d.ts +13 -0
  91. package/dist/types/inputs/index.d.ts +5 -0
  92. package/dist/types/layout/AnchoredPopover.d.ts +5 -0
  93. package/dist/types/layout/AppWorkspace.d.ts +14 -0
  94. package/dist/types/layout/app-workspace-controller.d.ts +2 -0
  95. package/dist/types/text-editor/TextEditor.d.ts +10 -1
  96. package/dist/types/text-editor/dictation.d.ts +20 -0
  97. package/dist/types/text-editor.d.ts +1 -0
  98. package/package.json +1 -1
@@ -54,7 +54,16 @@ export function ChoiceGroups(props) {
54
54
  width
55
55
  });
56
56
  };
57
-
57
+ const overflowEdges = () => {
58
+ const {
59
+ overflow,
60
+ left,
61
+ width
62
+ } = scrollbar();
63
+ if (!overflow || !viewport) return undefined;
64
+ const edges = [left > 0.5 ? "start" : "", left + width < viewport.clientWidth - 0.5 ? "end" : ""].filter(Boolean).join(" ");
65
+ return edges || undefined;
66
+ };
58
67
  // With no matching choice the first chip takes the tab stop, so the group stays reachable by keyboard.
59
68
  const tabStop = (value, index) => props.value === value || index === 0 && !props.choices.some(choice => choice.value === props.value);
60
69
  const choose = (index, focus = false) => {
@@ -149,14 +158,14 @@ export function ChoiceGroups(props) {
149
158
  })(), _el$9, _co$2);
150
159
  _$insert(_el$7, () => group.label, _el$1, _co$3);
151
160
  _$effect(_p$ => {
152
- var _v$7 = props.value === group.value,
153
- _v$8 = props.controls,
154
- _v$9 = props.disabled,
155
- _v$0 = tabStop(group.value, index()) ? 0 : -1;
156
- _v$7 !== _p$.e && _$setAttribute(_el$7, "aria-checked", _p$.e = _v$7);
157
- _v$8 !== _p$.t && _$setAttribute(_el$7, "aria-controls", _p$.t = _v$8);
158
- _v$9 !== _p$.a && _$setProperty(_el$7, "disabled", _p$.a = _v$9);
159
- _v$0 !== _p$.o && _$setAttribute(_el$7, "tabindex", _p$.o = _v$0);
161
+ var _v$8 = props.value === group.value,
162
+ _v$9 = props.controls,
163
+ _v$0 = props.disabled,
164
+ _v$1 = tabStop(group.value, index()) ? 0 : -1;
165
+ _v$8 !== _p$.e && _$setAttribute(_el$7, "aria-checked", _p$.e = _v$8);
166
+ _v$9 !== _p$.t && _$setAttribute(_el$7, "aria-controls", _p$.t = _v$9);
167
+ _v$0 !== _p$.a && _$setProperty(_el$7, "disabled", _p$.a = _v$0);
168
+ _v$1 !== _p$.o && _$setAttribute(_el$7, "tabindex", _p$.o = _v$1);
160
169
  return _p$;
161
170
  }, {
162
171
  e: undefined,
@@ -196,20 +205,23 @@ export function ChoiceGroups(props) {
196
205
  }
197
206
  }), _el$6, _co$);
198
207
  _$effect(_p$ => {
199
- var _v$3 = props.labelledBy ? undefined : props.ariaLabel,
200
- _v$4 = props.labelledBy,
201
- _v$5 = props.describedBy,
202
- _v$6 = props.disabled ? "true" : undefined;
203
- _v$3 !== _p$.e && _$setAttribute(_el$2, "aria-label", _p$.e = _v$3);
204
- _v$4 !== _p$.t && _$setAttribute(_el$2, "aria-labelledby", _p$.t = _v$4);
205
- _v$5 !== _p$.a && _$setAttribute(_el$2, "aria-describedby", _p$.a = _v$5);
206
- _v$6 !== _p$.o && _$setAttribute(_el$2, "aria-disabled", _p$.o = _v$6);
208
+ var _v$3 = overflowEdges(),
209
+ _v$4 = props.labelledBy ? undefined : props.ariaLabel,
210
+ _v$5 = props.labelledBy,
211
+ _v$6 = props.describedBy,
212
+ _v$7 = props.disabled ? "true" : undefined;
213
+ _v$3 !== _p$.e && _$setAttribute(_el$, "data-overflow", _p$.e = _v$3);
214
+ _v$4 !== _p$.t && _$setAttribute(_el$2, "aria-label", _p$.t = _v$4);
215
+ _v$5 !== _p$.a && _$setAttribute(_el$2, "aria-labelledby", _p$.a = _v$5);
216
+ _v$6 !== _p$.o && _$setAttribute(_el$2, "aria-describedby", _p$.o = _v$6);
217
+ _v$7 !== _p$.i && _$setAttribute(_el$2, "aria-disabled", _p$.i = _v$7);
207
218
  return _p$;
208
219
  }, {
209
220
  e: undefined,
210
221
  t: undefined,
211
222
  a: undefined,
212
- o: undefined
223
+ o: undefined,
224
+ i: undefined
213
225
  });
214
226
  _$runHydrationEvents();
215
227
  return _el$;
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["inputs/ChoiceGroups.tsx"],"sourcesContent":["import { createEffect, createSignal, For, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { suppressTextSelection } from \"../internal/text-selection\";\n\ntype ChoiceGroup = { value: string | null; label: string; icon?: string };\n\n/**\n * A single-choice row of chips that scrolls sideways instead of wrapping, so its height never changes. Select and\n * MultiSelect use it for their filters; `ChoiceChips` is the public field around it.\n */\nexport function ChoiceGroups(props: {\n choices: readonly ChoiceGroup[];\n value: string | null;\n onValueChange: (value: string | null) => void;\n ariaLabel?: string;\n /** The field label that names the group; replaces `ariaLabel`. */\n labelledBy?: string;\n describedBy?: string;\n controls?: string;\n disabled?: boolean;\n}): JSX.Element {\n let viewport: HTMLDivElement | undefined;\n let buttons: HTMLButtonElement[] = [];\n let dragOffset = 0;\n const [scrollbar, setScrollbar] = createSignal({ overflow: false, left: 0, width: 0 });\n\n const syncScrollbar = () => {\n if (!viewport) return;\n const { clientWidth, scrollLeft, scrollWidth } = viewport;\n if (clientWidth <= 0 || scrollWidth <= clientWidth) {\n setScrollbar({ overflow: false, left: 0, width: 0 });\n return;\n }\n const width = Math.min(clientWidth, Math.max(24, (clientWidth * clientWidth) / scrollWidth));\n const left = (scrollLeft / (scrollWidth - clientWidth)) * (clientWidth - width);\n setScrollbar({ overflow: true, left, width });\n };\n\n // With no matching choice the first chip takes the tab stop, so the group stays reachable by keyboard.\n const tabStop = (value: string | null, index: number) =>\n props.value === value || (index === 0 && !props.choices.some((choice) => choice.value === props.value));\n const choose = (index: number, focus = false) => {\n const choice = props.choices[index];\n if (!choice || props.disabled) return;\n props.onValueChange(choice.value);\n if (!focus) return;\n queueMicrotask(() => {\n buttons[index]?.focus();\n buttons[index]?.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n });\n };\n const move = (index: number, direction: 1 | -1) => choose((index + direction + props.choices.length) % props.choices.length, true);\n const focusEdge = (last: boolean) => choose(last ? props.choices.length - 1 : 0, true);\n\n const scrollFromPointer = (event: PointerEvent & { currentTarget: HTMLDivElement }) => {\n if (!viewport) return;\n const track = event.currentTarget;\n const { width } = scrollbar();\n const rect = track.getBoundingClientRect();\n const available = Math.max(1, rect.width - width);\n const thumbLeft = Math.min(available, Math.max(0, event.clientX - rect.left - dragOffset));\n viewport.scrollLeft = (thumbLeft / available) * (viewport.scrollWidth - viewport.clientWidth);\n syncScrollbar();\n };\n const startScrollbarDrag = (event: PointerEvent & { currentTarget: HTMLDivElement }) => {\n if (event.button !== 0) return;\n event.preventDefault();\n const track = event.currentTarget;\n const current = scrollbar();\n dragOffset =\n event.target === track\n ? current.width / 2\n : Math.min(current.width, Math.max(0, event.clientX - track.getBoundingClientRect().left - current.left));\n track.setPointerCapture(event.pointerId);\n // The track's own pointerup or pointercancel ends the hold.\n suppressTextSelection(event.pointerId);\n scrollFromPointer(event);\n };\n\n onMount(() => {\n syncScrollbar();\n const observer = typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(syncScrollbar);\n if (viewport) observer?.observe(viewport);\n onCleanup(() => observer?.disconnect());\n });\n createEffect(() => {\n props.choices.map((choice) => `${choice.value ?? \"\"}:${choice.label}`).join(\"|\");\n queueMicrotask(syncScrollbar);\n });\n\n return (\n <div class=\"k2b-choice-groups-shell\" onPointerEnter={syncScrollbar} onFocusIn={syncScrollbar}>\n <div\n ref={viewport}\n class=\"k2b-choice-groups\"\n role=\"radiogroup\"\n aria-label={props.labelledBy ? undefined : props.ariaLabel}\n aria-labelledby={props.labelledBy}\n aria-describedby={props.describedBy}\n aria-disabled={props.disabled ? \"true\" : undefined}\n onScroll={syncScrollbar}\n >\n <For each={props.choices}>\n {(group, index) => (\n <button\n ref={(element) => (buttons[index()] = element)}\n type=\"button\"\n role=\"radio\"\n aria-checked={props.value === group.value}\n aria-controls={props.controls}\n disabled={props.disabled}\n tabIndex={tabStop(group.value, index()) ? 0 : -1}\n onClick={() => choose(index())}\n onKeyDown={(event) => {\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n move(index(), 1);\n } else if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n move(index(), -1);\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focusEdge(event.key === \"End\");\n }\n }}\n >\n {group.icon && <i class={group.icon} aria-hidden=\"true\" />}\n {group.label}\n </button>\n )}\n </For>\n </div>\n <Show when={scrollbar().overflow}>\n <div\n class=\"k2b-choice-groups-scrollbar\"\n aria-hidden=\"true\"\n onPointerDown={startScrollbarDrag}\n onPointerMove={(event) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) scrollFromPointer(event);\n }}\n onPointerUp={(event) => event.currentTarget.releasePointerCapture(event.pointerId)}\n onPointerCancel={(event) => event.currentTarget.releasePointerCapture(event.pointerId)}\n >\n <span\n style={{\n \"--k2b-choice-scroll-left\": `${scrollbar().left}px`,\n \"--k2b-choice-scroll-width\": `${scrollbar().width}px`,\n }}\n />\n </div>\n </Show>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["inputs/ChoiceGroups.tsx"],"sourcesContent":["import { createEffect, createSignal, For, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { suppressTextSelection } from \"../internal/text-selection\";\n\ntype ChoiceGroup = { value: string | null; label: string; icon?: string };\n\n/**\n * A single-choice row of chips that scrolls sideways instead of wrapping, so its height never changes. Select and\n * MultiSelect use it for their filters; `ChoiceChips` is the public field around it.\n */\nexport function ChoiceGroups(props: {\n choices: readonly ChoiceGroup[];\n value: string | null;\n onValueChange: (value: string | null) => void;\n ariaLabel?: string;\n /** The field label that names the group; replaces `ariaLabel`. */\n labelledBy?: string;\n describedBy?: string;\n controls?: string;\n disabled?: boolean;\n}): JSX.Element {\n let viewport: HTMLDivElement | undefined;\n let buttons: HTMLButtonElement[] = [];\n let dragOffset = 0;\n const [scrollbar, setScrollbar] = createSignal({ overflow: false, left: 0, width: 0 });\n\n const syncScrollbar = () => {\n if (!viewport) return;\n const { clientWidth, scrollLeft, scrollWidth } = viewport;\n if (clientWidth <= 0 || scrollWidth <= clientWidth) {\n setScrollbar({ overflow: false, left: 0, width: 0 });\n return;\n }\n const width = Math.min(clientWidth, Math.max(24, (clientWidth * clientWidth) / scrollWidth));\n const left = (scrollLeft / (scrollWidth - clientWidth)) * (clientWidth - width);\n setScrollbar({ overflow: true, left, width });\n };\n\n const overflowEdges = () => {\n const { overflow, left, width } = scrollbar();\n if (!overflow || !viewport) return undefined;\n const edges = [left > 0.5 ? \"start\" : \"\", left + width < viewport.clientWidth - 0.5 ? \"end\" : \"\"].filter(Boolean).join(\" \");\n return edges || undefined;\n };\n // With no matching choice the first chip takes the tab stop, so the group stays reachable by keyboard.\n const tabStop = (value: string | null, index: number) =>\n props.value === value || (index === 0 && !props.choices.some((choice) => choice.value === props.value));\n const choose = (index: number, focus = false) => {\n const choice = props.choices[index];\n if (!choice || props.disabled) return;\n props.onValueChange(choice.value);\n if (!focus) return;\n queueMicrotask(() => {\n buttons[index]?.focus();\n buttons[index]?.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n });\n };\n const move = (index: number, direction: 1 | -1) => choose((index + direction + props.choices.length) % props.choices.length, true);\n const focusEdge = (last: boolean) => choose(last ? props.choices.length - 1 : 0, true);\n\n const scrollFromPointer = (event: PointerEvent & { currentTarget: HTMLDivElement }) => {\n if (!viewport) return;\n const track = event.currentTarget;\n const { width } = scrollbar();\n const rect = track.getBoundingClientRect();\n const available = Math.max(1, rect.width - width);\n const thumbLeft = Math.min(available, Math.max(0, event.clientX - rect.left - dragOffset));\n viewport.scrollLeft = (thumbLeft / available) * (viewport.scrollWidth - viewport.clientWidth);\n syncScrollbar();\n };\n const startScrollbarDrag = (event: PointerEvent & { currentTarget: HTMLDivElement }) => {\n if (event.button !== 0) return;\n event.preventDefault();\n const track = event.currentTarget;\n const current = scrollbar();\n dragOffset =\n event.target === track\n ? current.width / 2\n : Math.min(current.width, Math.max(0, event.clientX - track.getBoundingClientRect().left - current.left));\n track.setPointerCapture(event.pointerId);\n // The track's own pointerup or pointercancel ends the hold.\n suppressTextSelection(event.pointerId);\n scrollFromPointer(event);\n };\n\n onMount(() => {\n syncScrollbar();\n const observer = typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(syncScrollbar);\n if (viewport) observer?.observe(viewport);\n onCleanup(() => observer?.disconnect());\n });\n createEffect(() => {\n props.choices.map((choice) => `${choice.value ?? \"\"}:${choice.label}`).join(\"|\");\n queueMicrotask(syncScrollbar);\n });\n\n return (\n <div class=\"k2b-choice-groups-shell\" data-overflow={overflowEdges()} onPointerEnter={syncScrollbar} onFocusIn={syncScrollbar}>\n <div\n ref={viewport}\n class=\"k2b-choice-groups\"\n role=\"radiogroup\"\n aria-label={props.labelledBy ? undefined : props.ariaLabel}\n aria-labelledby={props.labelledBy}\n aria-describedby={props.describedBy}\n aria-disabled={props.disabled ? \"true\" : undefined}\n onScroll={syncScrollbar}\n >\n <For each={props.choices}>\n {(group, index) => (\n <button\n ref={(element) => (buttons[index()] = element)}\n type=\"button\"\n role=\"radio\"\n aria-checked={props.value === group.value}\n aria-controls={props.controls}\n disabled={props.disabled}\n tabIndex={tabStop(group.value, index()) ? 0 : -1}\n onClick={() => choose(index())}\n onKeyDown={(event) => {\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n move(index(), 1);\n } else if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n move(index(), -1);\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focusEdge(event.key === \"End\");\n }\n }}\n >\n {group.icon && <i class={group.icon} aria-hidden=\"true\" />}\n {group.label}\n </button>\n )}\n </For>\n </div>\n <Show when={scrollbar().overflow}>\n <div\n class=\"k2b-choice-groups-scrollbar\"\n aria-hidden=\"true\"\n onPointerDown={startScrollbarDrag}\n onPointerMove={(event) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) scrollFromPointer(event);\n }}\n onPointerUp={(event) => event.currentTarget.releasePointerCapture(event.pointerId)}\n onPointerCancel={(event) => event.currentTarget.releasePointerCapture(event.pointerId)}\n >\n <span\n style={{\n \"--k2b-choice-scroll-left\": `${scrollbar().left}px`,\n \"--k2b-choice-scroll-width\": `${scrollbar().width}px`,\n }}\n />\n </div>\n </Show>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -64,6 +64,8 @@ export function Select(props) {
64
64
  const [cache, setCache] = createSignal({});
65
65
  const [selectedGroup, setSelectedGroup] = createSignal(props.defaultGroup ?? null);
66
66
  const [selectedView, setSelectedView] = createSignal(props.defaultView ?? "list");
67
+ // Whether the person picked the group, rather than seeing the default one.
68
+ let groupChosen = false;
67
69
  let searchRef;
68
70
  let optionRefs = [];
69
71
  const value = () => resolveMaybeAccessor(props.value) ?? null;
@@ -123,6 +125,7 @@ export function Select(props) {
123
125
  };
124
126
  const move = direction => focus(nextEnabledChoiceIndex(listOptions(), focusedIndex(), direction));
125
127
  const chooseGroup = group => {
128
+ groupChosen = true;
126
129
  if (group === activeGroup()) return;
127
130
  setSelectedGroup(group);
128
131
  setFocusedIndex(nextEnabledChoiceIndex(listOptions(), -1, 1));
@@ -131,6 +134,9 @@ export function Select(props) {
131
134
  const open = () => {
132
135
  if (props.disabled) return;
133
136
  setQuery("");
137
+ // A static list that only left its default group for a search starts
138
+ // there again; a group the person picked, or a remote filter, stays.
139
+ if (!isAsync() && !groupChosen) setSelectedGroup(props.defaultGroup ?? null);
134
140
  if (isAsync()) loader.load("", true);
135
141
  const selectedIndex = listOptions().findIndex(option => option.value === (value() ?? CLEAR_VALUE));
136
142
  focus(selectedIndex >= 0 ? selectedIndex : nextEnabledChoiceIndex(listOptions(), -1, 1));
@@ -339,6 +345,10 @@ export function Select(props) {
339
345
  _el$0 = _el$9.firstChild,
340
346
  _el$1 = _el$0.nextSibling;
341
347
  _el$1.$$input = event => {
348
+ // A default group, such as "Recommended", is a starting view,
349
+ // not a filter: a static search leaves it for "All". A group
350
+ // the person chose keeps narrowing the results.
351
+ if (!isAsync() && !groupChosen && event.currentTarget.value) setSelectedGroup(null);
342
352
  setQuery(event.currentTarget.value);
343
353
  if (isAsync()) loader.load(event.currentTarget.value);
344
354
  focus(isAsync() ? -1 : nextEnabledChoiceIndex(options(), -1, 1));
@@ -541,18 +551,18 @@ export function Select(props) {
541
551
  })()
542
552
  }), _el$48, _co$1);
543
553
  _$effect(_p$ => {
544
- var _v$11 = `${listboxId}-${index()}`,
545
- _v$12 = option.label,
546
- _v$13 = option.value === (value() ?? CLEAR_VALUE),
547
- _v$14 = index() === focusedIndex() ? "true" : undefined,
548
- _v$15 = option.value === CLEAR_VALUE ? "true" : undefined,
549
- _v$16 = option.disabled;
550
- _v$11 !== _p$.e && _$setAttribute(_el$44, "id", _p$.e = _v$11);
551
- _v$12 !== _p$.t && _$setAttribute(_el$44, "aria-label", _p$.t = _v$12);
552
- _v$13 !== _p$.a && _$setAttribute(_el$44, "aria-selected", _p$.a = _v$13);
553
- _v$14 !== _p$.o && _$setAttribute(_el$44, "data-focused", _p$.o = _v$14);
554
- _v$15 !== _p$.i && _$setAttribute(_el$44, "data-clear", _p$.i = _v$15);
555
- _v$16 !== _p$.n && _$setProperty(_el$44, "disabled", _p$.n = _v$16);
554
+ var _v$12 = `${listboxId}-${index()}`,
555
+ _v$13 = option.label,
556
+ _v$14 = option.value === (value() ?? CLEAR_VALUE),
557
+ _v$15 = index() === focusedIndex() ? "true" : undefined,
558
+ _v$16 = option.value === CLEAR_VALUE ? "true" : undefined,
559
+ _v$17 = option.disabled;
560
+ _v$12 !== _p$.e && _$setAttribute(_el$44, "id", _p$.e = _v$12);
561
+ _v$13 !== _p$.t && _$setAttribute(_el$44, "aria-label", _p$.t = _v$13);
562
+ _v$14 !== _p$.a && _$setAttribute(_el$44, "aria-selected", _p$.a = _v$14);
563
+ _v$15 !== _p$.o && _$setAttribute(_el$44, "data-focused", _p$.o = _v$15);
564
+ _v$16 !== _p$.i && _$setAttribute(_el$44, "data-clear", _p$.i = _v$16);
565
+ _v$17 !== _p$.n && _$setProperty(_el$44, "disabled", _p$.n = _v$17);
556
566
  return _p$;
557
567
  }, {
558
568
  e: undefined,
@@ -571,16 +581,18 @@ export function Select(props) {
571
581
  _v$7 = error() ? "true" : undefined,
572
582
  _v$8 = selected() ? undefined : "true",
573
583
  _v$9 = `${popover.open() ? props.activeIcon ?? "ti ti-chevron-up" : props.icon ?? "ti ti-chevron-down"} k2b-choice-trigger__chevron`,
574
- _v$0 = typeof props.label === "string" ? props.label : props["aria-label"] ?? messages().options,
575
- _v$1 = activeView(),
576
- _v$10 = activeView() === "grid" ? props.gridSize ?? "md" : undefined;
584
+ _v$0 = (props.groups?.length ?? 0) > 0 || props.viewToggle ? "true" : undefined,
585
+ _v$1 = typeof props.label === "string" ? props.label : props["aria-label"] ?? messages().options,
586
+ _v$10 = activeView(),
587
+ _v$11 = activeView() === "grid" ? props.gridSize ?? "md" : undefined;
577
588
  _v$6 !== _p$.e && _$setAttribute(_el$, "data-appearance", _p$.e = _v$6);
578
589
  _v$7 !== _p$.t && _$setAttribute(_el$, "data-invalid", _p$.t = _v$7);
579
590
  _v$8 !== _p$.a && _$setAttribute(_el$3, "data-placeholder", _p$.a = _v$8);
580
591
  _v$9 !== _p$.o && _$className(_el$4, _p$.o = _v$9);
581
- _v$0 !== _p$.i && _$setAttribute(_el$8, "aria-label", _p$.i = _v$0);
582
- _v$1 !== _p$.n && _$setAttribute(_el$17, "data-view", _p$.n = _v$1);
583
- _v$10 !== _p$.s && _$setAttribute(_el$17, "data-grid-size", _p$.s = _v$10);
592
+ _v$0 !== _p$.i && _$setAttribute(_el$8, "data-toolbar", _p$.i = _v$0);
593
+ _v$1 !== _p$.n && _$setAttribute(_el$8, "aria-label", _p$.n = _v$1);
594
+ _v$10 !== _p$.s && _$setAttribute(_el$17, "data-view", _p$.s = _v$10);
595
+ _v$11 !== _p$.h && _$setAttribute(_el$17, "data-grid-size", _p$.h = _v$11);
584
596
  return _p$;
585
597
  }, {
586
598
  e: undefined,
@@ -589,7 +601,8 @@ export function Select(props) {
589
601
  o: undefined,
590
602
  i: undefined,
591
603
  n: undefined,
592
- s: undefined
604
+ s: undefined,
605
+ h: undefined
593
606
  });
594
607
  _$runHydrationEvents();
595
608
  return _el$;
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["inputs/Select.tsx"],"sourcesContent":["import { createMemo, createSignal, For, type JSX, Show } from \"solid-js\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { ChoiceGroups } from \"./ChoiceGroups\";\nimport { type ChoiceOption, createChoiceLoader, createChoicePopover, filterChoiceOptions, nextEnabledChoiceIndex } from \"./choice\";\nimport type { ValueFieldProps } from \"./field-contract\";\nimport { commitFieldValue, resolveMaybeAccessor } from \"./field-contract\";\nimport { useSelectMessages } from \"./select-messages\";\n\nexport type SelectOption = ChoiceOption<string>;\nexport type SelectGroup = {\n value: string;\n label: string;\n};\nexport type SelectView = \"list\" | \"grid\";\nexport type SelectGridSize = \"sm\" | \"md\" | \"lg\";\n/**\n * `field` draws the boxed form control. `plain` shows the value as text for\n * property rows: no box, no chevron, and a quiet surface on hover or while\n * open. Its surface and hit area cover the nearest positioned ancestor, such as\n * a `DescriptionList` row, so the whole row opens the picker.\n */\nexport type ChoiceAppearance = \"field\" | \"plain\";\nexport type SelectSourceOption =\n | string\n | {\n id: string;\n label?: string;\n description?: string;\n icon?: string;\n color?: string;\n groups?: readonly string[];\n }\n | SelectOption;\n\nexport type SelectProps = ValueFieldProps<string | null> & {\n placeholder?: string;\n icon?: string;\n activeIcon?: string;\n options?: SelectSourceOption[];\n fetchData?: (query: string, signal: AbortSignal, group: string | null) => Promise<SelectSourceOption[]>;\n loadOptions?: (query: string, signal: AbortSignal, group: string | null) => Promise<readonly ChoiceOption<string>[]>;\n selectedOption?: ChoiceOption<string>;\n selectedLabel?: () => string | undefined;\n fetchDebounceMs?: number;\n debounceMs?: number;\n searchable?: boolean;\n /** Optional synchronous filter for static options. */\n filterOptions?: (options: readonly SelectOption[], query: string) => readonly SelectOption[];\n /** Optional filters. An option may belong to more than one group. */\n groups?: readonly SelectGroup[];\n /** Group selected when the component is created. Omit to start with all options. */\n defaultGroup?: string;\n groupsAriaLabel?: string;\n allGroupLabel?: string;\n /** Show a local list/grid layout toggle in the dropdown. */\n viewToggle?: boolean;\n /** Initial dropdown layout when `viewToggle` is enabled. */\n defaultView?: SelectView;\n /** Tile density for the grid layout. */\n gridSize?: SelectGridSize;\n searchPlaceholder?: string;\n clearable?: boolean;\n name?: string;\n appearance?: ChoiceAppearance;\n /** Icon class shown before the placeholder while nothing is selected. */\n placeholderIcon?: string;\n};\n\ntype NormalizedOption = ChoiceOption<string>;\n/** The list entry that clears a plain select. It cannot collide with a real option value. */\nconst CLEAR_VALUE = \"\\u0000k2b-select-clear\";\n\nconst normalize = (option: SelectSourceOption): NormalizedOption =>\n typeof option === \"string\"\n ? { value: option, label: option }\n : \"value\" in option\n ? option\n : { ...option, value: option.id, label: option.label || option.id };\n\nexport function Select(props: SelectProps): JSX.Element {\n const messages = useUiMessages();\n const selectMessages = useSelectMessages();\n const meta = createFieldMeta(props.id);\n const listboxId = `${meta.controlId}-listbox`;\n const [query, setQuery] = createSignal(\"\");\n const [focusedIndex, setFocusedIndex] = createSignal(-1);\n const [cache, setCache] = createSignal<Record<string, NormalizedOption>>({});\n const [selectedGroup, setSelectedGroup] = createSignal<string | null>(props.defaultGroup ?? null);\n const [selectedView, setSelectedView] = createSignal<SelectView>(props.defaultView ?? \"list\");\n let searchRef: HTMLInputElement | undefined;\n let optionRefs: HTMLButtonElement[] = [];\n const value = () => resolveMaybeAccessor(props.value) ?? null;\n const error = () => resolveMaybeAccessor(props.error);\n const activeGroup = createMemo(() => {\n const current = selectedGroup();\n return current && props.groups?.some((group) => group.value === current) ? current : null;\n });\n const groupChoices = createMemo(() => [{ value: null, label: props.allGroupLabel ?? messages().all }, ...(props.groups ?? [])]);\n const activeView = () => (props.viewToggle ? selectedView() : \"list\");\n\n const loader = createChoiceLoader(\n () =>\n props.fetchData\n ? async (value, signal) => (await props.fetchData!(value, signal, activeGroup())).map(normalize)\n : props.loadOptions\n ? (value, signal) => props.loadOptions!(value, signal, activeGroup())\n : undefined,\n () => props.fetchDebounceMs ?? props.debounceMs ?? 200,\n );\n const isAsync = () => Boolean(props.fetchData || props.loadOptions);\n const isSearchable = () => isAsync() || Boolean(props.searchable);\n const sourceOptions = createMemo(() => (isAsync() ? loader.options() : (props.options ?? []).map(normalize)));\n const groupedOptions = createMemo(() => {\n const group = activeGroup();\n return !isAsync() && group ? sourceOptions().filter((option) => option.groups?.includes(group)) : sourceOptions();\n });\n // Remote loaders filter server-side; a static list has to be filtered here or\n // the search field would render but do nothing.\n const options = createMemo(() =>\n isAsync() || !props.searchable\n ? groupedOptions()\n : props.filterOptions\n ? [...props.filterOptions(groupedOptions(), query())]\n : filterChoiceOptions(groupedOptions(), query()),\n );\n const plain = () => props.appearance === \"plain\";\n // A plain select has no room for a clear button beside its value, so\n // clearing becomes the last list entry, named by the placeholder.\n const clearOption = createMemo<NormalizedOption | undefined>(() =>\n plain() && props.clearable && !query() ? { value: CLEAR_VALUE, label: props.placeholder ?? messages().clearSelection } : undefined,\n );\n const listOptions = createMemo(() => {\n const clear = clearOption();\n return clear && !loader.error() ? [...options(), clear] : options();\n });\n // Colour dots mark the options, so an empty plain value keeps the column with a hollow dot.\n const emptyDot = () => plain() && !props.placeholderIcon && sourceOptions().some((option) => option.color);\n const selected = createMemo(() => {\n const current = value();\n if (current === null) return undefined;\n // Resolve against the unfiltered list so typing in the search field never\n // blanks the trigger label of the current selection.\n return (\n sourceOptions().find((option) => option.value === current) ??\n cache()[current] ??\n (props.selectedOption?.value === current ? props.selectedOption : undefined) ?? {\n value: current,\n label: props.selectedLabel?.() ?? current,\n }\n );\n });\n const hasClearAction = () => Boolean(props.clearable && selected() && !props.disabled && !plain());\n const accessibleLabel = () =>\n props[\"aria-label\"] ?? (typeof props.label === \"string\" ? undefined : (props.placeholder ?? selectMessages().selectOption));\n const popover = createChoicePopover(() => Boolean(props.disabled));\n const focusedOption = () => listOptions()[focusedIndex()];\n const focus = (index: number) => {\n setFocusedIndex(index);\n optionRefs[index]?.scrollIntoView({ block: \"nearest\" });\n };\n const move = (direction: 1 | -1) => focus(nextEnabledChoiceIndex(listOptions(), focusedIndex(), direction));\n const chooseGroup = (group: string | null) => {\n if (group === activeGroup()) return;\n setSelectedGroup(group);\n setFocusedIndex(nextEnabledChoiceIndex(listOptions(), -1, 1));\n if (isAsync()) loader.load(query(), true);\n };\n const open = () => {\n if (props.disabled) return;\n setQuery(\"\");\n if (isAsync()) loader.load(\"\", true);\n const selectedIndex = listOptions().findIndex((option) => option.value === (value() ?? CLEAR_VALUE));\n focus(selectedIndex >= 0 ? selectedIndex : nextEnabledChoiceIndex(listOptions(), -1, 1));\n popover.show();\n if (isSearchable()) queueMicrotask(() => searchRef?.focus());\n };\n const close = (restoreFocus = false) => {\n // Hide the top-layer surface before any reactive cleanup or consumer\n // callback can rerender its contents. Selection must feel atomic: the old\n // listbox must never remain visible with the next value.\n popover.hide(restoreFocus);\n loader.cancel();\n setQuery(\"\");\n setFocusedIndex(-1);\n };\n const select = (option: NormalizedOption) => {\n if (option.disabled) return;\n close(true);\n if (option.value === CLEAR_VALUE) {\n commitFieldValue(props, null);\n return;\n }\n setCache({ ...cache(), [option.value]: option });\n commitFieldValue(props, option.value);\n };\n const onKeyDown = (event: KeyboardEvent) => {\n const inToolbar = Boolean((event.target as HTMLElement | null)?.closest?.(\".k2b-choice-toolbar\"));\n if (inToolbar && event.key !== \"Escape\" && event.key !== \"Tab\") return;\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n if (!popover.open()) open();\n else move(event.key === \"ArrowDown\" ? 1 : -1);\n } else if ((event.key === \"Enter\" || event.key === \" \") && !popover.open()) {\n event.preventDefault();\n open();\n } else if (event.key === \"Enter\" && focusedOption()) {\n event.preventDefault();\n select(focusedOption()!);\n } else if (event.key === \"Escape\" && popover.open()) {\n // Only swallow Escape while the list is open — a closed select must let\n // the key bubble to an enclosing dialog or drawer.\n event.preventDefault();\n close(true);\n } else if (event.key === \"Tab\" && popover.open()) close();\n };\n const clear = (event: MouseEvent) => {\n event.stopPropagation();\n commitFieldValue(props, null);\n popover.trigger()?.focus();\n };\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={error()}\n meta={meta}\n required={props.required}\n disabled={props.disabled}\n >\n <div class=\"k2b-choice-control\" data-appearance={props.appearance ?? \"field\"} data-invalid={error() ? \"true\" : undefined}>\n <button\n ref={popover.setTrigger}\n id={meta.controlId}\n type=\"button\"\n class=\"k2b-choice-trigger\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={popover.open()}\n aria-controls={listboxId}\n aria-activedescendant={focusedOption() ? `${listboxId}-${focusedIndex()}` : undefined}\n data-clearable={hasClearAction() ? \"true\" : undefined}\n {...fieldControlAria(meta, {\n ...props,\n \"aria-label\": accessibleLabel(),\n })}\n disabled={props.disabled}\n onClick={() => (popover.open() ? close() : open())}\n onKeyDown={onKeyDown}\n >\n <Show\n when={selected()}\n fallback={\n <Show\n when={props.placeholderIcon}\n fallback={<Show when={emptyDot()}>{<span class=\"k2b-choice-dot\" data-empty=\"true\" aria-hidden=\"true\" />}</Show>}\n >\n {(icon) => <i class={`${icon()} k2b-choice-trigger__placeholder-icon`} aria-hidden=\"true\" />}\n </Show>\n }\n >\n <Show\n when={selected()?.color}\n fallback={<Show when={selected()?.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>}\n >\n {(color) => <span class=\"k2b-choice-dot\" style={{ \"background-color\": color() }} aria-hidden=\"true\" />}\n </Show>\n </Show>\n <span class=\"k2b-choice-trigger__value\" data-placeholder={selected() ? undefined : \"true\"}>\n {selected()?.label ?? props.placeholder ?? messages().select}\n </span>\n <i\n class={`${popover.open() ? (props.activeIcon ?? \"ti ti-chevron-up\") : (props.icon ?? \"ti ti-chevron-down\")} k2b-choice-trigger__chevron`}\n aria-hidden=\"true\"\n />\n </button>\n <Show when={props.name}>{(name) => <input type=\"hidden\" name={name()} value={value() ?? \"\"} />}</Show>\n <Show when={hasClearAction()}>\n <button\n type=\"button\"\n class=\"k2b-choice-control__clear k2b-input-clear-action\"\n aria-label={messages().clearSelection}\n onClick={clear}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </Show>\n <div\n ref={popover.setPopover}\n popover=\"manual\"\n class=\"k2b-choice-popover\"\n role=\"group\"\n onKeyDown={onKeyDown}\n aria-label={typeof props.label === \"string\" ? props.label : (props[\"aria-label\"] ?? messages().options)}\n >\n <Show when={isSearchable()}>\n <div class=\"k2b-choice-search\">\n <i class=\"ti ti-search\" aria-hidden=\"true\" />\n <input\n ref={searchRef}\n type=\"search\"\n value={query()}\n placeholder={props.searchPlaceholder ?? messages().search}\n aria-label={props.searchPlaceholder ?? selectMessages().searchOptions}\n aria-controls={listboxId}\n aria-activedescendant={focusedOption() ? `${listboxId}-${focusedIndex()}` : undefined}\n onInput={(event) => {\n setQuery(event.currentTarget.value);\n if (isAsync()) loader.load(event.currentTarget.value);\n focus(isAsync() ? -1 : nextEnabledChoiceIndex(options(), -1, 1));\n }}\n />\n </div>\n </Show>\n <Show when={(props.groups?.length ?? 0) > 0 || props.viewToggle}>\n <div class=\"k2b-choice-toolbar\">\n <Show when={(props.groups?.length ?? 0) > 0}>\n <ChoiceGroups\n choices={groupChoices()}\n value={activeGroup()}\n onValueChange={chooseGroup}\n ariaLabel={props.groupsAriaLabel ?? selectMessages().filterOptions}\n controls={listboxId}\n />\n </Show>\n <Show when={props.viewToggle}>\n <button\n type=\"button\"\n class=\"k2b-choice-view-toggle\"\n aria-label={activeView() === \"list\" ? selectMessages().showGridView : selectMessages().showListView}\n aria-controls={listboxId}\n onClick={() => setSelectedView(activeView() === \"list\" ? \"grid\" : \"list\")}\n >\n <i class={activeView() === \"list\" ? \"ti ti-category-2\" : \"ti ti-list-details\"} aria-hidden=\"true\" />\n </button>\n </Show>\n </div>\n </Show>\n <div\n id={listboxId}\n class=\"k2b-choice-options\"\n role=\"listbox\"\n data-view={activeView()}\n data-grid-size={activeView() === \"grid\" ? (props.gridSize ?? \"md\") : undefined}\n >\n <Show when={loader.error()}>\n {(message) => (\n <div class=\"k2b-choice-status\" data-tone=\"danger\">\n <span>{message()}</span>\n <button type=\"button\" onClick={loader.retry}>\n {messages().retry}\n </button>\n </div>\n )}\n </Show>\n <Show when={loader.loading() && options().length === 0}>\n <div class=\"k2b-choice-status\">\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n <span>{messages().loading}</span>\n </div>\n </Show>\n <For\n each={loader.error() ? [] : listOptions()}\n fallback={\n <Show when={!loader.loading() && !loader.error()}>\n <div class=\"k2b-choice-status\">{isSearchable() ? messages().noResults : selectMessages().noOptions}</div>\n </Show>\n }\n >\n {(option, index) => (\n <button\n ref={(element) => (optionRefs[index()] = element)}\n type=\"button\"\n id={`${listboxId}-${index()}`}\n class=\"k2b-choice-option\"\n role=\"option\"\n aria-label={option.label}\n aria-selected={option.value === (value() ?? CLEAR_VALUE)}\n data-focused={index() === focusedIndex() ? \"true\" : undefined}\n data-clear={option.value === CLEAR_VALUE ? \"true\" : undefined}\n disabled={option.disabled}\n onPointerMove={() => focus(index())}\n onClick={() => select(option)}\n >\n <Show\n when={option.value === CLEAR_VALUE}\n fallback={\n <Show\n when={option.color}\n fallback={<Show when={option.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>}\n >\n {(color) => <span class=\"k2b-choice-dot\" style={{ \"background-color\": color() }} aria-hidden=\"true\" />}\n </Show>\n }\n >\n <Show\n when={props.placeholderIcon}\n fallback={<Show when={emptyDot()}>{<span class=\"k2b-choice-dot\" data-empty=\"true\" aria-hidden=\"true\" />}</Show>}\n >\n {(icon) => <i class={icon()} aria-hidden=\"true\" />}\n </Show>\n </Show>\n <span>\n <strong>{option.label}</strong>\n <Show when={option.description}>{(description) => <small>{description()}</small>}</Show>\n </span>\n </button>\n )}\n </For>\n </div>\n </div>\n </div>\n </Field>\n );\n}\n\nexport default Select;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["inputs/Select.tsx"],"sourcesContent":["import { createMemo, createSignal, For, type JSX, Show } from \"solid-js\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { ChoiceGroups } from \"./ChoiceGroups\";\nimport { type ChoiceOption, createChoiceLoader, createChoicePopover, filterChoiceOptions, nextEnabledChoiceIndex } from \"./choice\";\nimport type { ValueFieldProps } from \"./field-contract\";\nimport { commitFieldValue, resolveMaybeAccessor } from \"./field-contract\";\nimport { useSelectMessages } from \"./select-messages\";\n\nexport type SelectOption = ChoiceOption<string>;\nexport type SelectGroup = {\n value: string;\n label: string;\n};\nexport type SelectView = \"list\" | \"grid\";\nexport type SelectGridSize = \"sm\" | \"md\" | \"lg\";\n/**\n * `field` draws the boxed form control. `plain` shows the value as text for\n * property rows: no box, no chevron, and a quiet surface on hover or while\n * open. Its surface and hit area cover the nearest positioned ancestor, such as\n * a `DescriptionList` row, so the whole row opens the picker.\n */\nexport type ChoiceAppearance = \"field\" | \"plain\";\nexport type SelectSourceOption =\n | string\n | {\n id: string;\n label?: string;\n description?: string;\n icon?: string;\n color?: string;\n groups?: readonly string[];\n }\n | SelectOption;\n\nexport type SelectProps = ValueFieldProps<string | null> & {\n placeholder?: string;\n icon?: string;\n activeIcon?: string;\n options?: SelectSourceOption[];\n fetchData?: (query: string, signal: AbortSignal, group: string | null) => Promise<SelectSourceOption[]>;\n loadOptions?: (query: string, signal: AbortSignal, group: string | null) => Promise<readonly ChoiceOption<string>[]>;\n selectedOption?: ChoiceOption<string>;\n selectedLabel?: () => string | undefined;\n fetchDebounceMs?: number;\n debounceMs?: number;\n searchable?: boolean;\n /** Optional synchronous filter for static options. */\n filterOptions?: (options: readonly SelectOption[], query: string) => readonly SelectOption[];\n /** Optional filters. An option may belong to more than one group. */\n groups?: readonly SelectGroup[];\n /** Group selected when the component is created. Omit to start with all options. */\n defaultGroup?: string;\n groupsAriaLabel?: string;\n allGroupLabel?: string;\n /** Show a local list/grid layout toggle in the dropdown. */\n viewToggle?: boolean;\n /** Initial dropdown layout when `viewToggle` is enabled. */\n defaultView?: SelectView;\n /** Tile density for the grid layout. */\n gridSize?: SelectGridSize;\n searchPlaceholder?: string;\n clearable?: boolean;\n name?: string;\n appearance?: ChoiceAppearance;\n /** Icon class shown before the placeholder while nothing is selected. */\n placeholderIcon?: string;\n};\n\ntype NormalizedOption = ChoiceOption<string>;\n/** The list entry that clears a plain select. It cannot collide with a real option value. */\nconst CLEAR_VALUE = \"\\u0000k2b-select-clear\";\n\nconst normalize = (option: SelectSourceOption): NormalizedOption =>\n typeof option === \"string\"\n ? { value: option, label: option }\n : \"value\" in option\n ? option\n : { ...option, value: option.id, label: option.label || option.id };\n\nexport function Select(props: SelectProps): JSX.Element {\n const messages = useUiMessages();\n const selectMessages = useSelectMessages();\n const meta = createFieldMeta(props.id);\n const listboxId = `${meta.controlId}-listbox`;\n const [query, setQuery] = createSignal(\"\");\n const [focusedIndex, setFocusedIndex] = createSignal(-1);\n const [cache, setCache] = createSignal<Record<string, NormalizedOption>>({});\n const [selectedGroup, setSelectedGroup] = createSignal<string | null>(props.defaultGroup ?? null);\n const [selectedView, setSelectedView] = createSignal<SelectView>(props.defaultView ?? \"list\");\n // Whether the person picked the group, rather than seeing the default one.\n let groupChosen = false;\n let searchRef: HTMLInputElement | undefined;\n let optionRefs: HTMLButtonElement[] = [];\n const value = () => resolveMaybeAccessor(props.value) ?? null;\n const error = () => resolveMaybeAccessor(props.error);\n const activeGroup = createMemo(() => {\n const current = selectedGroup();\n return current && props.groups?.some((group) => group.value === current) ? current : null;\n });\n const groupChoices = createMemo(() => [{ value: null, label: props.allGroupLabel ?? messages().all }, ...(props.groups ?? [])]);\n const activeView = () => (props.viewToggle ? selectedView() : \"list\");\n\n const loader = createChoiceLoader(\n () =>\n props.fetchData\n ? async (value, signal) => (await props.fetchData!(value, signal, activeGroup())).map(normalize)\n : props.loadOptions\n ? (value, signal) => props.loadOptions!(value, signal, activeGroup())\n : undefined,\n () => props.fetchDebounceMs ?? props.debounceMs ?? 200,\n );\n const isAsync = () => Boolean(props.fetchData || props.loadOptions);\n const isSearchable = () => isAsync() || Boolean(props.searchable);\n const sourceOptions = createMemo(() => (isAsync() ? loader.options() : (props.options ?? []).map(normalize)));\n const groupedOptions = createMemo(() => {\n const group = activeGroup();\n return !isAsync() && group ? sourceOptions().filter((option) => option.groups?.includes(group)) : sourceOptions();\n });\n // Remote loaders filter server-side; a static list has to be filtered here or\n // the search field would render but do nothing.\n const options = createMemo(() =>\n isAsync() || !props.searchable\n ? groupedOptions()\n : props.filterOptions\n ? [...props.filterOptions(groupedOptions(), query())]\n : filterChoiceOptions(groupedOptions(), query()),\n );\n const plain = () => props.appearance === \"plain\";\n // A plain select has no room for a clear button beside its value, so\n // clearing becomes the last list entry, named by the placeholder.\n const clearOption = createMemo<NormalizedOption | undefined>(() =>\n plain() && props.clearable && !query() ? { value: CLEAR_VALUE, label: props.placeholder ?? messages().clearSelection } : undefined,\n );\n const listOptions = createMemo(() => {\n const clear = clearOption();\n return clear && !loader.error() ? [...options(), clear] : options();\n });\n // Colour dots mark the options, so an empty plain value keeps the column with a hollow dot.\n const emptyDot = () => plain() && !props.placeholderIcon && sourceOptions().some((option) => option.color);\n const selected = createMemo(() => {\n const current = value();\n if (current === null) return undefined;\n // Resolve against the unfiltered list so typing in the search field never\n // blanks the trigger label of the current selection.\n return (\n sourceOptions().find((option) => option.value === current) ??\n cache()[current] ??\n (props.selectedOption?.value === current ? props.selectedOption : undefined) ?? {\n value: current,\n label: props.selectedLabel?.() ?? current,\n }\n );\n });\n const hasClearAction = () => Boolean(props.clearable && selected() && !props.disabled && !plain());\n const accessibleLabel = () =>\n props[\"aria-label\"] ?? (typeof props.label === \"string\" ? undefined : (props.placeholder ?? selectMessages().selectOption));\n const popover = createChoicePopover(() => Boolean(props.disabled));\n const focusedOption = () => listOptions()[focusedIndex()];\n const focus = (index: number) => {\n setFocusedIndex(index);\n optionRefs[index]?.scrollIntoView({ block: \"nearest\" });\n };\n const move = (direction: 1 | -1) => focus(nextEnabledChoiceIndex(listOptions(), focusedIndex(), direction));\n const chooseGroup = (group: string | null) => {\n groupChosen = true;\n if (group === activeGroup()) return;\n setSelectedGroup(group);\n setFocusedIndex(nextEnabledChoiceIndex(listOptions(), -1, 1));\n if (isAsync()) loader.load(query(), true);\n };\n const open = () => {\n if (props.disabled) return;\n setQuery(\"\");\n // A static list that only left its default group for a search starts\n // there again; a group the person picked, or a remote filter, stays.\n if (!isAsync() && !groupChosen) setSelectedGroup(props.defaultGroup ?? null);\n if (isAsync()) loader.load(\"\", true);\n const selectedIndex = listOptions().findIndex((option) => option.value === (value() ?? CLEAR_VALUE));\n focus(selectedIndex >= 0 ? selectedIndex : nextEnabledChoiceIndex(listOptions(), -1, 1));\n popover.show();\n if (isSearchable()) queueMicrotask(() => searchRef?.focus());\n };\n const close = (restoreFocus = false) => {\n // Hide the top-layer surface before any reactive cleanup or consumer\n // callback can rerender its contents. Selection must feel atomic: the old\n // listbox must never remain visible with the next value.\n popover.hide(restoreFocus);\n loader.cancel();\n setQuery(\"\");\n setFocusedIndex(-1);\n };\n const select = (option: NormalizedOption) => {\n if (option.disabled) return;\n close(true);\n if (option.value === CLEAR_VALUE) {\n commitFieldValue(props, null);\n return;\n }\n setCache({ ...cache(), [option.value]: option });\n commitFieldValue(props, option.value);\n };\n const onKeyDown = (event: KeyboardEvent) => {\n const inToolbar = Boolean((event.target as HTMLElement | null)?.closest?.(\".k2b-choice-toolbar\"));\n if (inToolbar && event.key !== \"Escape\" && event.key !== \"Tab\") return;\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n if (!popover.open()) open();\n else move(event.key === \"ArrowDown\" ? 1 : -1);\n } else if ((event.key === \"Enter\" || event.key === \" \") && !popover.open()) {\n event.preventDefault();\n open();\n } else if (event.key === \"Enter\" && focusedOption()) {\n event.preventDefault();\n select(focusedOption()!);\n } else if (event.key === \"Escape\" && popover.open()) {\n // Only swallow Escape while the list is open — a closed select must let\n // the key bubble to an enclosing dialog or drawer.\n event.preventDefault();\n close(true);\n } else if (event.key === \"Tab\" && popover.open()) close();\n };\n const clear = (event: MouseEvent) => {\n event.stopPropagation();\n commitFieldValue(props, null);\n popover.trigger()?.focus();\n };\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={error()}\n meta={meta}\n required={props.required}\n disabled={props.disabled}\n >\n <div class=\"k2b-choice-control\" data-appearance={props.appearance ?? \"field\"} data-invalid={error() ? \"true\" : undefined}>\n <button\n ref={popover.setTrigger}\n id={meta.controlId}\n type=\"button\"\n class=\"k2b-choice-trigger\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={popover.open()}\n aria-controls={listboxId}\n aria-activedescendant={focusedOption() ? `${listboxId}-${focusedIndex()}` : undefined}\n data-clearable={hasClearAction() ? \"true\" : undefined}\n {...fieldControlAria(meta, {\n ...props,\n \"aria-label\": accessibleLabel(),\n })}\n disabled={props.disabled}\n onClick={() => (popover.open() ? close() : open())}\n onKeyDown={onKeyDown}\n >\n <Show\n when={selected()}\n fallback={\n <Show\n when={props.placeholderIcon}\n fallback={<Show when={emptyDot()}>{<span class=\"k2b-choice-dot\" data-empty=\"true\" aria-hidden=\"true\" />}</Show>}\n >\n {(icon) => <i class={`${icon()} k2b-choice-trigger__placeholder-icon`} aria-hidden=\"true\" />}\n </Show>\n }\n >\n <Show\n when={selected()?.color}\n fallback={<Show when={selected()?.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>}\n >\n {(color) => <span class=\"k2b-choice-dot\" style={{ \"background-color\": color() }} aria-hidden=\"true\" />}\n </Show>\n </Show>\n <span class=\"k2b-choice-trigger__value\" data-placeholder={selected() ? undefined : \"true\"}>\n {selected()?.label ?? props.placeholder ?? messages().select}\n </span>\n <i\n class={`${popover.open() ? (props.activeIcon ?? \"ti ti-chevron-up\") : (props.icon ?? \"ti ti-chevron-down\")} k2b-choice-trigger__chevron`}\n aria-hidden=\"true\"\n />\n </button>\n <Show when={props.name}>{(name) => <input type=\"hidden\" name={name()} value={value() ?? \"\"} />}</Show>\n <Show when={hasClearAction()}>\n <button\n type=\"button\"\n class=\"k2b-choice-control__clear k2b-input-clear-action\"\n aria-label={messages().clearSelection}\n onClick={clear}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </Show>\n <div\n ref={popover.setPopover}\n popover=\"manual\"\n class=\"k2b-choice-popover\"\n data-toolbar={(props.groups?.length ?? 0) > 0 || props.viewToggle ? \"true\" : undefined}\n role=\"group\"\n onKeyDown={onKeyDown}\n aria-label={typeof props.label === \"string\" ? props.label : (props[\"aria-label\"] ?? messages().options)}\n >\n <Show when={isSearchable()}>\n <div class=\"k2b-choice-search\">\n <i class=\"ti ti-search\" aria-hidden=\"true\" />\n <input\n ref={searchRef}\n type=\"search\"\n value={query()}\n placeholder={props.searchPlaceholder ?? messages().search}\n aria-label={props.searchPlaceholder ?? selectMessages().searchOptions}\n aria-controls={listboxId}\n aria-activedescendant={focusedOption() ? `${listboxId}-${focusedIndex()}` : undefined}\n onInput={(event) => {\n // A default group, such as \"Recommended\", is a starting view,\n // not a filter: a static search leaves it for \"All\". A group\n // the person chose keeps narrowing the results.\n if (!isAsync() && !groupChosen && event.currentTarget.value) setSelectedGroup(null);\n setQuery(event.currentTarget.value);\n if (isAsync()) loader.load(event.currentTarget.value);\n focus(isAsync() ? -1 : nextEnabledChoiceIndex(options(), -1, 1));\n }}\n />\n </div>\n </Show>\n <Show when={(props.groups?.length ?? 0) > 0 || props.viewToggle}>\n <div class=\"k2b-choice-toolbar\">\n <Show when={(props.groups?.length ?? 0) > 0}>\n <ChoiceGroups\n choices={groupChoices()}\n value={activeGroup()}\n onValueChange={chooseGroup}\n ariaLabel={props.groupsAriaLabel ?? selectMessages().filterOptions}\n controls={listboxId}\n />\n </Show>\n <Show when={props.viewToggle}>\n <button\n type=\"button\"\n class=\"k2b-choice-view-toggle\"\n aria-label={activeView() === \"list\" ? selectMessages().showGridView : selectMessages().showListView}\n aria-controls={listboxId}\n onClick={() => setSelectedView(activeView() === \"list\" ? \"grid\" : \"list\")}\n >\n <i class={activeView() === \"list\" ? \"ti ti-category-2\" : \"ti ti-list-details\"} aria-hidden=\"true\" />\n </button>\n </Show>\n </div>\n </Show>\n <div\n id={listboxId}\n class=\"k2b-choice-options\"\n role=\"listbox\"\n data-view={activeView()}\n data-grid-size={activeView() === \"grid\" ? (props.gridSize ?? \"md\") : undefined}\n >\n <Show when={loader.error()}>\n {(message) => (\n <div class=\"k2b-choice-status\" data-tone=\"danger\">\n <span>{message()}</span>\n <button type=\"button\" onClick={loader.retry}>\n {messages().retry}\n </button>\n </div>\n )}\n </Show>\n <Show when={loader.loading() && options().length === 0}>\n <div class=\"k2b-choice-status\">\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n <span>{messages().loading}</span>\n </div>\n </Show>\n <For\n each={loader.error() ? [] : listOptions()}\n fallback={\n <Show when={!loader.loading() && !loader.error()}>\n <div class=\"k2b-choice-status\">{isSearchable() ? messages().noResults : selectMessages().noOptions}</div>\n </Show>\n }\n >\n {(option, index) => (\n <button\n ref={(element) => (optionRefs[index()] = element)}\n type=\"button\"\n id={`${listboxId}-${index()}`}\n class=\"k2b-choice-option\"\n role=\"option\"\n aria-label={option.label}\n aria-selected={option.value === (value() ?? CLEAR_VALUE)}\n data-focused={index() === focusedIndex() ? \"true\" : undefined}\n data-clear={option.value === CLEAR_VALUE ? \"true\" : undefined}\n disabled={option.disabled}\n onPointerMove={() => focus(index())}\n onClick={() => select(option)}\n >\n <Show\n when={option.value === CLEAR_VALUE}\n fallback={\n <Show\n when={option.color}\n fallback={<Show when={option.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>}\n >\n {(color) => <span class=\"k2b-choice-dot\" style={{ \"background-color\": color() }} aria-hidden=\"true\" />}\n </Show>\n }\n >\n <Show\n when={props.placeholderIcon}\n fallback={<Show when={emptyDot()}>{<span class=\"k2b-choice-dot\" data-empty=\"true\" aria-hidden=\"true\" />}</Show>}\n >\n {(icon) => <i class={icon()} aria-hidden=\"true\" />}\n </Show>\n </Show>\n <span>\n <strong>{option.label}</strong>\n <Show when={option.description}>{(description) => <small>{description()}</small>}</Show>\n </span>\n </button>\n )}\n </For>\n </div>\n </div>\n </div>\n </Field>\n );\n}\n\nexport default Select;\n"],"mappings":"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","ignoreList":[]}
@@ -1,37 +1,66 @@
1
1
  import { createComponent as _$createComponent } from "solid-js/web";
2
2
  import { memo as _$memo } from "solid-js/web";
3
- import { fuzzy } from "@k2b/stdlib";
4
3
  import { createMemo } from "solid-js";
4
+ import { useLocale } from "../intl/locale";
5
5
  import { useUiMessages } from "../intl/messages";
6
6
  import { resolveMaybeAccessor } from "./field-contract";
7
- import { useIconMessages } from "./icon-messages";
8
- import { DEFAULT_ICON_GROUPS, DEFAULT_ICON_OPTIONS } from "./icon-options";
7
+ import { useIconLocale, useIconMessages } from "./icon-messages";
8
+ import { DEFAULT_ICON_GROUPS } from "./icon-options";
9
+ import { localizedIconOptions } from "./icon-texts";
9
10
  import { Select } from "./Select";
11
+ /** Lowercase without diacritics, so "gross" finds "Groß" and "uber" finds "Über". */
12
+ const fold = text => text.normalize("NFD").replace(/\p{Diacritic}/gu, "").replace(/ß/g, "ss").toLowerCase();
13
+ const words = text => fold(text).split(/[^\p{L}\p{N}$€%]+/u).filter(Boolean);
14
+
15
+ /**
16
+ * Every query word has to appear in the icon's names or keywords: as the start
17
+ * of a word, or anywhere in one once it has three letters, so German compounds
18
+ * such as "Kreditkarte" match "karte". A loose subsequence match let "gro" find
19
+ * "warninG eRrOr", so it is not used. Ranked by where the query hits: the label
20
+ * start, a label word, a keyword, then anywhere.
21
+ */
22
+ export const searchIconOptions = (source, query, limit) => {
23
+ const tokens = words(query);
24
+ if (tokens.length === 0) return [...source];
25
+ const ranked = [];
26
+ for (const option of source) {
27
+ const labelWords = words(String(option.label));
28
+ const keywordWords = (option.keywords ?? []).flatMap(words);
29
+ const all = [...labelWords, ...keywordWords];
30
+ let rank = 0;
31
+ for (const token of tokens) {
32
+ const tokenRank = labelWords.some(word => word.startsWith(token)) ? 1 : keywordWords.some(word => word.startsWith(token)) ? 2 : token.length >= 3 && all.some(word => word.includes(token)) ? 3 : undefined;
33
+ if (tokenRank === undefined) {
34
+ rank = -1;
35
+ break;
36
+ }
37
+ rank = Math.max(rank, tokenRank);
38
+ }
39
+ if (rank < 0) continue;
40
+ if (rank === 1 && labelWords[0]?.startsWith(tokens[0])) rank = 0;
41
+ ranked.push({
42
+ option,
43
+ rank
44
+ });
45
+ }
46
+ return ranked.sort((left, right) => left.rank - right.rank || String(left.option.label).localeCompare(String(right.option.label))).slice(0, limit).map(entry => entry.option);
47
+ };
10
48
  export function IconInput(props) {
11
49
  const messages = useUiMessages();
12
50
  const iconMessages = useIconMessages();
13
- const options = () => props.options ?? DEFAULT_ICON_OPTIONS;
14
- const groups = () => props.groups ?? (props.options === undefined ? DEFAULT_ICON_GROUPS : undefined);
15
- const filterOptions = (source, query) => {
16
- const normalized = query.trim().toLowerCase();
17
- if (!normalized) {
18
- return [...source].sort((left, right) => String(left.label).localeCompare(String(right.label), undefined, {
19
- sensitivity: "base"
20
- }));
21
- }
22
- return fuzzy.filter(normalized, source, {
23
- // Cloud's key is `[label, ...keywords]`. Including `value` as well put
24
- // the literal "ti ti-" in front of every entry, so short queries matched
25
- // the whole catalogue and fuzzy scores were skewed. The bare glyph name
26
- // is already the first keyword (see `icon()` in ./icon-options), so
27
- // nothing is lost by dropping it.
28
- key: option => {
29
- const keywords = "keywords" in option && Array.isArray(option.keywords) ? option.keywords.join(" ") : "";
30
- return `${String(option.label)} ${keywords}`.toLowerCase();
31
- },
32
- limit: props.searchLimit ?? 50
33
- }).map(match => match.item);
34
- };
51
+ const locale = useLocale();
52
+ // The bundled catalogue speaks the render locale and stays searchable by
53
+ // its English names, so a mixed team finds the same icon either way.
54
+ const iconLocale = useIconLocale();
55
+ const defaultOptions = createMemo(() => localizedIconOptions(iconLocale()));
56
+ const options = () => props.options ?? defaultOptions();
57
+ const groups = () => props.groups ?? (props.options === undefined ? DEFAULT_ICON_GROUPS.map(group => ({
58
+ value: group.value,
59
+ label: iconMessages()[group.value]
60
+ })) : undefined);
61
+ const filterOptions = (source, query) => query.trim() ? searchIconOptions(source, query, props.searchLimit ?? 50) : [...source].sort((left, right) => String(left.label).localeCompare(String(right.label), locale(), {
62
+ sensitivity: "base"
63
+ }));
35
64
  const selectedOption = createMemo(() => options().find(option => option.value === resolveMaybeAccessor(props.value)));
36
65
  return _$createComponent(Select, {
37
66
  get id() {
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["inputs/SpecialInputs.tsx"],"sourcesContent":["import { fuzzy } from \"@k2b/stdlib\";\nimport { createMemo, type JSX } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { ValueFieldProps } from \"./field-contract\";\nimport { resolveMaybeAccessor } from \"./field-contract\";\nimport { useIconMessages } from \"./icon-messages\";\nimport { DEFAULT_ICON_GROUPS, DEFAULT_ICON_OPTIONS } from \"./icon-options\";\nimport { Select, type SelectGridSize, type SelectGroup, type SelectOption, type SelectView } from \"./Select\";\n\nexport type IconOption = SelectOption & { keywords?: readonly string[] };\nexport type IconInputProps = ValueFieldProps<string | null> & {\n options?: readonly IconOption[];\n placeholder?: string;\n clearable?: boolean;\n searchLimit?: number;\n groups?: readonly SelectGroup[];\n defaultGroup?: string;\n groupsAriaLabel?: string;\n allGroupLabel?: string;\n viewToggle?: boolean;\n defaultView?: SelectView;\n gridSize?: SelectGridSize;\n name?: string;\n};\n\nexport function IconInput(props: IconInputProps): JSX.Element {\n const messages = useUiMessages();\n const iconMessages = useIconMessages();\n const options = () => props.options ?? DEFAULT_ICON_OPTIONS;\n const groups = () => props.groups ?? (props.options === undefined ? DEFAULT_ICON_GROUPS : undefined);\n const filterOptions = (source: readonly SelectOption[], query: string): readonly SelectOption[] => {\n const normalized = query.trim().toLowerCase();\n if (!normalized) {\n return [...source].sort((left, right) => String(left.label).localeCompare(String(right.label), undefined, { sensitivity: \"base\" }));\n }\n return fuzzy\n .filter(normalized, source, {\n // Cloud's key is `[label, ...keywords]`. Including `value` as well put\n // the literal \"ti ti-\" in front of every entry, so short queries matched\n // the whole catalogue and fuzzy scores were skewed. The bare glyph name\n // is already the first keyword (see `icon()` in ./icon-options), so\n // nothing is lost by dropping it.\n key: (option) => {\n const keywords = \"keywords\" in option && Array.isArray(option.keywords) ? option.keywords.join(\" \") : \"\";\n return `${String(option.label)} ${keywords}`.toLowerCase();\n },\n limit: props.searchLimit ?? 50,\n })\n .map((match) => match.item);\n };\n const selectedOption = createMemo(() => options().find((option) => option.value === resolveMaybeAccessor(props.value)));\n\n return (\n <Select\n id={props.id}\n name={props.name}\n class={props.class}\n label={props.label}\n description={props.description}\n error={props.error}\n aria-label={props[\"aria-label\"]}\n aria-describedby={props[\"aria-describedby\"]}\n placeholder={props.placeholder ?? iconMessages().pickIcon}\n disabled={props.disabled}\n required={props.required}\n clearable={props.clearable ?? true}\n value={resolveMaybeAccessor(props.value)}\n selectedOption={selectedOption()}\n onValueChange={props.onValueChange}\n onValueCommit={props.onValueCommit}\n options={[...options()]}\n groups={groups()}\n defaultGroup={props.defaultGroup ?? (props.options === undefined ? \"recommended\" : undefined)}\n groupsAriaLabel={props.groupsAriaLabel ?? iconMessages().filterIcons}\n allGroupLabel={props.allGroupLabel}\n viewToggle={props.viewToggle ?? true}\n defaultView={props.defaultView ?? \"grid\"}\n gridSize={props.gridSize ?? \"sm\"}\n searchable\n filterOptions={filterOptions}\n searchPlaceholder={messages().search}\n icon={selectedOption()?.icon ?? \"ti ti-icons\"}\n />\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["inputs/SpecialInputs.tsx"],"sourcesContent":["import { createMemo, type JSX } from \"solid-js\";\nimport { useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { ValueFieldProps } from \"./field-contract\";\nimport { resolveMaybeAccessor } from \"./field-contract\";\nimport { type IconGroupMessage, useIconLocale, useIconMessages } from \"./icon-messages\";\nimport { DEFAULT_ICON_GROUPS } from \"./icon-options\";\nimport { localizedIconOptions } from \"./icon-texts\";\nimport { Select, type SelectGridSize, type SelectGroup, type SelectOption, type SelectView } from \"./Select\";\n\nexport type IconOption = SelectOption & { keywords?: readonly string[] };\nexport type IconInputProps = ValueFieldProps<string | null> & {\n options?: readonly IconOption[];\n placeholder?: string;\n clearable?: boolean;\n searchLimit?: number;\n groups?: readonly SelectGroup[];\n defaultGroup?: string;\n groupsAriaLabel?: string;\n allGroupLabel?: string;\n viewToggle?: boolean;\n defaultView?: SelectView;\n gridSize?: SelectGridSize;\n name?: string;\n};\n\n/** Lowercase without diacritics, so \"gross\" finds \"Groß\" and \"uber\" finds \"Über\". */\nconst fold = (text: string) =>\n text\n .normalize(\"NFD\")\n .replace(/\\p{Diacritic}/gu, \"\")\n .replace(/ß/g, \"ss\")\n .toLowerCase();\nconst words = (text: string) =>\n fold(text)\n .split(/[^\\p{L}\\p{N}$€%]+/u)\n .filter(Boolean);\n\n/**\n * Every query word has to appear in the icon's names or keywords: as the start\n * of a word, or anywhere in one once it has three letters, so German compounds\n * such as \"Kreditkarte\" match \"karte\". A loose subsequence match let \"gro\" find\n * \"warninG eRrOr\", so it is not used. Ranked by where the query hits: the label\n * start, a label word, a keyword, then anywhere.\n */\nexport const searchIconOptions = <T extends IconOption>(source: readonly T[], query: string, limit: number): T[] => {\n const tokens = words(query);\n if (tokens.length === 0) return [...source];\n const ranked: { option: T; rank: number }[] = [];\n for (const option of source) {\n const labelWords = words(String(option.label));\n const keywordWords = (option.keywords ?? []).flatMap(words);\n const all = [...labelWords, ...keywordWords];\n let rank = 0;\n for (const token of tokens) {\n const tokenRank = labelWords.some((word) => word.startsWith(token))\n ? 1\n : keywordWords.some((word) => word.startsWith(token))\n ? 2\n : token.length >= 3 && all.some((word) => word.includes(token))\n ? 3\n : undefined;\n if (tokenRank === undefined) {\n rank = -1;\n break;\n }\n rank = Math.max(rank, tokenRank);\n }\n if (rank < 0) continue;\n if (rank === 1 && labelWords[0]?.startsWith(tokens[0]!)) rank = 0;\n ranked.push({ option, rank });\n }\n return ranked\n .sort((left, right) => left.rank - right.rank || String(left.option.label).localeCompare(String(right.option.label)))\n .slice(0, limit)\n .map((entry) => entry.option);\n};\n\nexport function IconInput(props: IconInputProps): JSX.Element {\n const messages = useUiMessages();\n const iconMessages = useIconMessages();\n const locale = useLocale();\n // The bundled catalogue speaks the render locale and stays searchable by\n // its English names, so a mixed team finds the same icon either way.\n const iconLocale = useIconLocale();\n const defaultOptions = createMemo(() => localizedIconOptions(iconLocale()));\n const options = () => props.options ?? defaultOptions();\n const groups = () =>\n props.groups ??\n (props.options === undefined\n ? DEFAULT_ICON_GROUPS.map((group) => ({ value: group.value, label: iconMessages()[group.value satisfies IconGroupMessage] }))\n : undefined);\n const filterOptions = (source: readonly SelectOption[], query: string): readonly SelectOption[] =>\n query.trim()\n ? searchIconOptions(source, query, props.searchLimit ?? 50)\n : [...source].sort((left, right) => String(left.label).localeCompare(String(right.label), locale(), { sensitivity: \"base\" }));\n const selectedOption = createMemo(() => options().find((option) => option.value === resolveMaybeAccessor(props.value)));\n\n return (\n <Select\n id={props.id}\n name={props.name}\n class={props.class}\n label={props.label}\n description={props.description}\n error={props.error}\n aria-label={props[\"aria-label\"]}\n aria-describedby={props[\"aria-describedby\"]}\n placeholder={props.placeholder ?? iconMessages().pickIcon}\n disabled={props.disabled}\n required={props.required}\n clearable={props.clearable ?? true}\n value={resolveMaybeAccessor(props.value)}\n selectedOption={selectedOption()}\n onValueChange={props.onValueChange}\n onValueCommit={props.onValueCommit}\n options={[...options()]}\n groups={groups()}\n defaultGroup={props.defaultGroup ?? (props.options === undefined ? \"recommended\" : undefined)}\n groupsAriaLabel={props.groupsAriaLabel ?? iconMessages().filterIcons}\n allGroupLabel={props.allGroupLabel}\n viewToggle={props.viewToggle ?? true}\n defaultView={props.defaultView ?? \"grid\"}\n gridSize={props.gridSize ?? \"sm\"}\n searchable\n filterOptions={filterOptions}\n searchPlaceholder={messages().search}\n icon={selectedOption()?.icon ?? \"ti ti-icons\"}\n />\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -124,8 +124,11 @@ export const placeChoicePopover = (trigger, popover, placement = {}) => {
124
124
  // panel that no longer lines up with the control it belongs to.
125
125
  const triggerWidth = Math.min(triggerRect.width, window.innerWidth - margin * 2);
126
126
  if (placement.width !== "own") popover.style.width = `${triggerWidth}px`;
127
+
128
+ // A stylesheet minimum, such as a popover with filter chips, can make it
129
+ // wider than the trigger, so the clamp below uses the rendered width.
127
130
  const popoverRect = popover.getBoundingClientRect();
128
- const width = placement.width === "own" ? popoverRect.width : triggerWidth;
131
+ const width = popoverRect.width;
129
132
  const left = Math.max(margin, Math.min(triggerRect.left, window.innerWidth - width - margin));
130
133
  const roomBelow = window.innerHeight - triggerRect.bottom - gap - margin;
131
134
  const roomAbove = triggerRect.top - gap - margin;