@threadlabs/looma 0.5.0 → 0.5.2

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 (313) hide show
  1. package/README.md +1 -1
  2. package/components/shared/input-modality.d.ts +8 -0
  3. package/components/shared/input-modality.js +2 -0
  4. package/components/ui-button/ui-button.html +42 -1
  5. package/components/ui-combobox/ui-combobox.html +12 -4
  6. package/components/ui-dialog/ui-dialog.html +13 -0
  7. package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +1 -1
  8. package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +1 -1
  9. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +6 -2
  10. package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +20 -4
  11. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +8 -4
  12. package/components/ui-form-field/ui-form-field.html +18 -7
  13. package/components/ui-icon/ui-icon.html +5 -1
  14. package/components/ui-icon-button/ui-icon-button.html +44 -1
  15. package/components/ui-popover/ui-popover.js +10 -2
  16. package/components/ui-search-shell/ui-search-shell.html +7 -0
  17. package/components/ui-search-shell/ui-search-shell.js +9 -0
  18. package/components/ui-tabs/ui-tabs.html +1 -1
  19. package/components/ui-toast-region/ui-toast-region.html +1 -1
  20. package/components/ui-tree-item/ui-tree-item.html +6 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +2 -2
  23. package/package.json +2 -2
  24. package/styles/ui-affordance-scope.css +1 -1
  25. package/styles/ui-avatar-group.css +1 -1
  26. package/styles/ui-avatar.css +1 -1
  27. package/styles/ui-badge.css +1 -1
  28. package/styles/ui-button.css +42 -2
  29. package/styles/ui-callout.css +1 -1
  30. package/styles/ui-checkbox.css +1 -1
  31. package/styles/ui-cluster.css +1 -1
  32. package/styles/ui-combobox.css +1 -1
  33. package/styles/ui-container.css +1 -1
  34. package/styles/ui-context-menu.css +1 -1
  35. package/styles/ui-dialog.css +18 -1
  36. package/styles/ui-disclosure.css +1 -1
  37. package/styles/ui-editable.css +1 -1
  38. package/styles/ui-editor-insert-table-grid.css +1 -1
  39. package/styles/ui-editor-mention-menu.css +1 -1
  40. package/styles/ui-editor-slash-menu.css +1 -1
  41. package/styles/ui-editor-table-context-menu.css +1 -1
  42. package/styles/ui-editor-table-overlay.css +1 -1
  43. package/styles/ui-editor-table-toolbar.css +1 -1
  44. package/styles/ui-editor-toolbar.css +1 -1
  45. package/styles/ui-floating-action-button.css +1 -1
  46. package/styles/ui-form-field.css +24 -10
  47. package/styles/ui-grid.css +1 -1
  48. package/styles/ui-icon-button.css +52 -2
  49. package/styles/ui-icon.css +1 -1
  50. package/styles/ui-input.css +1 -1
  51. package/styles/ui-menu-item.css +1 -1
  52. package/styles/ui-menu.css +1 -1
  53. package/styles/ui-popover.css +1 -1
  54. package/styles/ui-radio-group.css +1 -1
  55. package/styles/ui-radio.css +1 -1
  56. package/styles/ui-reel.css +1 -1
  57. package/styles/ui-search-result-row.css +1 -1
  58. package/styles/ui-search-shell.css +11 -2
  59. package/styles/ui-select.css +1 -1
  60. package/styles/ui-separator.css +1 -1
  61. package/styles/ui-sidebar.css +1 -1
  62. package/styles/ui-stack.css +1 -1
  63. package/styles/ui-switch.css +1 -1
  64. package/styles/ui-switcher.css +1 -1
  65. package/styles/ui-tabs.css +1 -1
  66. package/styles/ui-textarea.css +1 -1
  67. package/styles/ui-toast-region.css +1 -1
  68. package/styles/ui-tooltip.css +1 -1
  69. package/styles/ui-top-bar.css +1 -1
  70. package/styles/ui-tree-item.css +10 -2
  71. package/styles/ui-tree.css +1 -1
  72. package/vanilla/UiAffordanceScope.d.ts +1 -1
  73. package/vanilla/UiAffordanceScope.js +2 -2
  74. package/vanilla/UiAvatar.d.ts +1 -1
  75. package/vanilla/UiAvatar.js +2 -2
  76. package/vanilla/UiAvatarGroup.d.ts +1 -1
  77. package/vanilla/UiAvatarGroup.js +2 -2
  78. package/vanilla/UiBadge.d.ts +1 -1
  79. package/vanilla/UiBadge.js +2 -2
  80. package/vanilla/UiButton.d.ts +3 -1
  81. package/vanilla/UiButton.js +3 -3
  82. package/vanilla/UiCallout.d.ts +1 -1
  83. package/vanilla/UiCallout.js +2 -2
  84. package/vanilla/UiCheckbox.d.ts +1 -1
  85. package/vanilla/UiCheckbox.js +2 -2
  86. package/vanilla/UiCluster.d.ts +1 -1
  87. package/vanilla/UiCluster.js +2 -2
  88. package/vanilla/UiCombobox.d.ts +1 -1
  89. package/vanilla/UiCombobox.js +3 -3
  90. package/vanilla/UiContainer.d.ts +1 -1
  91. package/vanilla/UiContainer.js +2 -2
  92. package/vanilla/UiContextMenu.d.ts +1 -1
  93. package/vanilla/UiContextMenu.js +2 -2
  94. package/vanilla/UiDialog.d.ts +1 -1
  95. package/vanilla/UiDialog.js +2 -2
  96. package/vanilla/UiDisclosure.d.ts +1 -1
  97. package/vanilla/UiDisclosure.js +2 -2
  98. package/vanilla/UiEditable.d.ts +1 -1
  99. package/vanilla/UiEditable.js +2 -2
  100. package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
  101. package/vanilla/UiEditorInsertTableGrid.js +3 -3
  102. package/vanilla/UiEditorMentionMenu.d.ts +1 -1
  103. package/vanilla/UiEditorMentionMenu.js +3 -3
  104. package/vanilla/UiEditorSlashMenu.d.ts +1 -1
  105. package/vanilla/UiEditorSlashMenu.js +2 -2
  106. package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
  107. package/vanilla/UiEditorTableContextMenu.js +3 -3
  108. package/vanilla/UiEditorTableOverlay.d.ts +1 -1
  109. package/vanilla/UiEditorTableOverlay.js +3 -3
  110. package/vanilla/UiEditorTableToolbar.d.ts +1 -1
  111. package/vanilla/UiEditorTableToolbar.js +3 -3
  112. package/vanilla/UiEditorToolbar.d.ts +1 -1
  113. package/vanilla/UiEditorToolbar.js +2 -2
  114. package/vanilla/UiFloatingActionButton.d.ts +1 -1
  115. package/vanilla/UiFloatingActionButton.js +2 -2
  116. package/vanilla/UiFormField.d.ts +1 -1
  117. package/vanilla/UiFormField.js +15 -6
  118. package/vanilla/UiGrid.d.ts +1 -1
  119. package/vanilla/UiGrid.js +2 -2
  120. package/vanilla/UiIcon.d.ts +1 -1
  121. package/vanilla/UiIcon.js +3 -3
  122. package/vanilla/UiIconButton.d.ts +1 -1
  123. package/vanilla/UiIconButton.js +2 -2
  124. package/vanilla/UiInput.d.ts +1 -1
  125. package/vanilla/UiInput.js +2 -2
  126. package/vanilla/UiMenu.d.ts +1 -1
  127. package/vanilla/UiMenu.js +2 -2
  128. package/vanilla/UiMenuItem.d.ts +1 -1
  129. package/vanilla/UiMenuItem.js +2 -2
  130. package/vanilla/UiPopover.d.ts +1 -1
  131. package/vanilla/UiPopover.js +2 -2
  132. package/vanilla/UiRadio.d.ts +1 -1
  133. package/vanilla/UiRadio.js +2 -2
  134. package/vanilla/UiRadioGroup.d.ts +1 -1
  135. package/vanilla/UiRadioGroup.js +2 -2
  136. package/vanilla/UiReel.d.ts +1 -1
  137. package/vanilla/UiReel.js +2 -2
  138. package/vanilla/UiSearchResultRow.d.ts +1 -1
  139. package/vanilla/UiSearchResultRow.js +2 -2
  140. package/vanilla/UiSearchShell.d.ts +1 -1
  141. package/vanilla/UiSearchShell.js +2 -2
  142. package/vanilla/UiSelect.d.ts +1 -1
  143. package/vanilla/UiSelect.js +2 -2
  144. package/vanilla/UiSeparator.d.ts +1 -1
  145. package/vanilla/UiSeparator.js +2 -2
  146. package/vanilla/UiSidebar.d.ts +1 -1
  147. package/vanilla/UiSidebar.js +2 -2
  148. package/vanilla/UiStack.d.ts +1 -1
  149. package/vanilla/UiStack.js +2 -2
  150. package/vanilla/UiSwitch.d.ts +1 -1
  151. package/vanilla/UiSwitch.js +2 -2
  152. package/vanilla/UiSwitcher.d.ts +1 -1
  153. package/vanilla/UiSwitcher.js +2 -2
  154. package/vanilla/UiTabs.d.ts +1 -1
  155. package/vanilla/UiTabs.js +3 -3
  156. package/vanilla/UiTextarea.d.ts +1 -1
  157. package/vanilla/UiTextarea.js +2 -2
  158. package/vanilla/UiToastRegion.d.ts +1 -1
  159. package/vanilla/UiToastRegion.js +3 -3
  160. package/vanilla/UiTooltip.d.ts +1 -1
  161. package/vanilla/UiTooltip.js +2 -2
  162. package/vanilla/UiTopBar.d.ts +1 -1
  163. package/vanilla/UiTopBar.js +1 -1
  164. package/vanilla/UiTree.d.ts +1 -1
  165. package/vanilla/UiTree.js +2 -2
  166. package/vanilla/UiTreeItem.d.ts +1 -1
  167. package/vanilla/UiTreeItem.js +2 -2
  168. package/vue/UiAffordanceScope.d.ts +2 -2
  169. package/vue/UiAffordanceScope.vue +92 -73
  170. package/vue/UiAvatar.d.ts +7 -7
  171. package/vue/UiAvatar.vue +145 -105
  172. package/vue/UiAvatarGroup.d.ts +4 -4
  173. package/vue/UiAvatarGroup.vue +134 -118
  174. package/vue/UiBadge.d.ts +4 -4
  175. package/vue/UiBadge.vue +113 -114
  176. package/vue/UiButton.d.ts +10 -6
  177. package/vue/UiButton.vue +289 -220
  178. package/vue/UiCallout.d.ts +2 -2
  179. package/vue/UiCallout.vue +154 -87
  180. package/vue/UiCheckbox.d.ts +14 -10
  181. package/vue/UiCheckbox.vue +228 -162
  182. package/vue/UiCluster.d.ts +2 -2
  183. package/vue/UiCluster.vue +53 -60
  184. package/vue/UiCombobox.d.ts +36 -32
  185. package/vue/UiCombobox.vue +1005 -416
  186. package/vue/UiContainer.d.ts +2 -2
  187. package/vue/UiContainer.vue +48 -51
  188. package/vue/UiContextMenu.d.ts +6 -4
  189. package/vue/UiContextMenu.vue +205 -116
  190. package/vue/UiDialog.d.ts +11 -9
  191. package/vue/UiDialog.vue +287 -212
  192. package/vue/UiDisclosure.d.ts +8 -6
  193. package/vue/UiDisclosure.vue +248 -159
  194. package/vue/UiEditable.d.ts +16 -12
  195. package/vue/UiEditable.vue +325 -205
  196. package/vue/UiEditorInsertTableGrid.d.ts +8 -8
  197. package/vue/UiEditorInsertTableGrid.vue +216 -157
  198. package/vue/UiEditorMentionMenu.d.ts +9 -9
  199. package/vue/UiEditorMentionMenu.vue +265 -222
  200. package/vue/UiEditorSlashMenu.d.ts +7 -7
  201. package/vue/UiEditorSlashMenu.vue +286 -240
  202. package/vue/UiEditorTableContextMenu.d.ts +5 -5
  203. package/vue/UiEditorTableContextMenu.vue +306 -193
  204. package/vue/UiEditorTableOverlay.d.ts +2 -2
  205. package/vue/UiEditorTableOverlay.vue +609 -369
  206. package/vue/UiEditorTableToolbar.d.ts +7 -7
  207. package/vue/UiEditorTableToolbar.vue +443 -268
  208. package/vue/UiEditorToolbar.d.ts +2 -2
  209. package/vue/UiEditorToolbar.vue +134 -121
  210. package/vue/UiFloatingActionButton.d.ts +6 -6
  211. package/vue/UiFloatingActionButton.vue +100 -99
  212. package/vue/UiFormField.d.ts +6 -6
  213. package/vue/UiFormField.vue +112 -80
  214. package/vue/UiGrid.d.ts +2 -2
  215. package/vue/UiGrid.vue +51 -57
  216. package/vue/UiIcon.d.ts +2 -2
  217. package/vue/UiIcon.vue +118 -89
  218. package/vue/UiIconButton.d.ts +11 -11
  219. package/vue/UiIconButton.vue +285 -206
  220. package/vue/UiInput.d.ts +9 -9
  221. package/vue/UiInput.vue +153 -127
  222. package/vue/UiMenu.d.ts +8 -6
  223. package/vue/UiMenu.vue +217 -143
  224. package/vue/UiMenuItem.d.ts +4 -4
  225. package/vue/UiMenuItem.vue +52 -46
  226. package/vue/UiPopover.d.ts +8 -6
  227. package/vue/UiPopover.vue +197 -137
  228. package/vue/UiRadio.d.ts +14 -10
  229. package/vue/UiRadio.vue +183 -117
  230. package/vue/UiRadioGroup.d.ts +14 -12
  231. package/vue/UiRadioGroup.vue +172 -111
  232. package/vue/UiReel.d.ts +3 -3
  233. package/vue/UiReel.vue +77 -77
  234. package/vue/UiSearchResultRow.d.ts +4 -4
  235. package/vue/UiSearchResultRow.vue +124 -115
  236. package/vue/UiSearchShell.d.ts +10 -8
  237. package/vue/UiSearchShell.vue +245 -176
  238. package/vue/UiSelect.d.ts +9 -9
  239. package/vue/UiSelect.vue +162 -134
  240. package/vue/UiSeparator.d.ts +2 -2
  241. package/vue/UiSeparator.vue +22 -27
  242. package/vue/UiSidebar.d.ts +20 -18
  243. package/vue/UiSidebar.vue +312 -224
  244. package/vue/UiStack.d.ts +3 -3
  245. package/vue/UiStack.vue +64 -70
  246. package/vue/UiSwitch.d.ts +12 -8
  247. package/vue/UiSwitch.vue +218 -150
  248. package/vue/UiSwitcher.d.ts +3 -3
  249. package/vue/UiSwitcher.vue +73 -75
  250. package/vue/UiTabs.d.ts +10 -8
  251. package/vue/UiTabs.vue +251 -210
  252. package/vue/UiTextarea.d.ts +11 -11
  253. package/vue/UiTextarea.vue +155 -128
  254. package/vue/UiToastRegion.d.ts +10 -8
  255. package/vue/UiToastRegion.vue +261 -198
  256. package/vue/UiTooltip.d.ts +14 -12
  257. package/vue/UiTooltip.vue +241 -177
  258. package/vue/UiTopBar.vue +51 -42
  259. package/vue/UiTree.d.ts +8 -6
  260. package/vue/UiTree.vue +157 -70
  261. package/vue/UiTreeItem.d.ts +24 -22
  262. package/vue/UiTreeItem.vue +456 -339
  263. package/vue/chunks/UiAffordanceScope.js +9 -16
  264. package/vue/chunks/UiAvatar.js +23 -29
  265. package/vue/chunks/UiAvatarGroup.js +16 -39
  266. package/vue/chunks/UiBadge.js +3 -12
  267. package/vue/chunks/UiButton.js +15 -18
  268. package/vue/chunks/UiCallout.js +8 -17
  269. package/vue/chunks/UiCheckbox.js +37 -40
  270. package/vue/chunks/UiCluster.js +3 -12
  271. package/vue/chunks/UiCombobox.js +224 -266
  272. package/vue/chunks/UiContainer.js +3 -12
  273. package/vue/chunks/UiContextMenu.js +39 -34
  274. package/vue/chunks/UiDialog.js +36 -39
  275. package/vue/chunks/UiDisclosure.js +43 -48
  276. package/vue/chunks/UiEditable.js +55 -57
  277. package/vue/chunks/UiEditorInsertTableGrid.js +55 -73
  278. package/vue/chunks/UiEditorMentionMenu.js +40 -81
  279. package/vue/chunks/UiEditorSlashMenu.js +28 -52
  280. package/vue/chunks/UiEditorTableContextMenu.js +32 -56
  281. package/vue/chunks/UiEditorTableOverlay.js +58 -82
  282. package/vue/chunks/UiEditorTableToolbar.js +61 -85
  283. package/vue/chunks/UiEditorToolbar.js +4 -13
  284. package/vue/chunks/UiFloatingActionButton.js +7 -21
  285. package/vue/chunks/UiFormField.js +15 -12
  286. package/vue/chunks/UiGrid.js +3 -12
  287. package/vue/chunks/UiIcon.js +20 -43
  288. package/vue/chunks/UiIconButton.js +16 -28
  289. package/vue/chunks/UiInput.js +20 -25
  290. package/vue/chunks/UiMenu.js +29 -33
  291. package/vue/chunks/UiMenuItem.js +4 -10
  292. package/vue/chunks/UiPopover.js +28 -29
  293. package/vue/chunks/UiRadio.js +36 -39
  294. package/vue/chunks/UiRadioGroup.js +30 -34
  295. package/vue/chunks/UiReel.js +6 -15
  296. package/vue/chunks/UiSearchResultRow.js +6 -19
  297. package/vue/chunks/UiSearchShell.js +25 -28
  298. package/vue/chunks/UiSelect.js +20 -23
  299. package/vue/chunks/UiSeparator.js +2 -8
  300. package/vue/chunks/UiSidebar.js +39 -44
  301. package/vue/chunks/UiStack.js +6 -15
  302. package/vue/chunks/UiSwitch.js +35 -38
  303. package/vue/chunks/UiSwitcher.js +6 -15
  304. package/vue/chunks/UiTabs.js +47 -85
  305. package/vue/chunks/UiTextarea.js +21 -26
  306. package/vue/chunks/UiToastRegion.js +38 -72
  307. package/vue/chunks/UiTooltip.js +34 -35
  308. package/vue/chunks/UiTopBar.js +1 -1
  309. package/vue/chunks/UiTree.js +20 -15
  310. package/vue/chunks/UiTreeItem.js +85 -102
  311. package/vue/components.css +3994 -3764
  312. package/vue/index.d.ts +1 -0
  313. package/vue/index.js +2 -1
@@ -1,466 +1,1055 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.1 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import { computed, onBeforeUnmount, onMounted, ref, shallowRef, watchEffect } from "vue";
4
- import UiBadge from "./UiBadge.vue";
5
- import UiTooltip from "./UiTooltip.vue";
6
- import * as controllerModule from "../components/ui-combobox/ui-combobox.js";
3
+ import {
4
+ computed,
5
+ onBeforeUnmount,
6
+ onMounted,
7
+ ref,
8
+ shallowRef,
9
+ useTemplateRef,
10
+ watchEffect,
11
+ } from 'vue'
12
+ import * as controllerModule from '../components/ui-combobox/ui-combobox.js'
13
+ import UiBadge from './UiBadge.vue'
14
+ import UiTooltip from './UiTooltip.vue'
7
15
 
8
- defineOptions({ inheritAttrs: false });
16
+ defineOptions({ inheritAttrs: false })
9
17
 
10
- const hn = {
11
- t: (v: unknown): boolean => v === true || (typeof v === "string" ? v.length > 0 : typeof v === "number" ? v !== 0 && v === v : Array.isArray(v) ? v.length > 0 : v !== null && typeof v === "object" ? Object.keys(v).length > 0 : false),
12
- n: (v: unknown): number | undefined => typeof v === "number" && v === v ? v : undefined,
13
- op: (op: string, a: unknown, b: unknown): unknown => {
14
- const x = hn.n(a), y = hn.n(b);
15
- if (x === undefined || y === undefined) return undefined;
16
- switch (op) {
17
- case "<": return x < y; case "<=": return x <= y; case ">": return x > y; case ">=": return x >= y;
18
- case "+": return x + y; case "-": return x - y; case "*": return x * y; case "/": return x / y; case "%": return x % y;
19
- }
20
- return undefined;
21
- },
22
- text: (v: unknown): string => v === undefined || v === null ? "" : Array.isArray(v) ? v.map(hn.text).join(" ") : typeof v === "object" ? "" : String(v),
23
- attr: (v: unknown): any => v === undefined || v === null || v === false ? undefined : v === true ? "" : Array.isArray(v) ? v.map(hn.text).join(" ") : typeof v === "object" ? undefined : String(v),
24
- enumerated: (v: unknown): any => typeof v === "boolean" ? String(v) : hn.attr(v),
25
- call: (fn: string, ...args: unknown[]): any => {
26
- if (fn === "format") {
27
- let index = 1;
28
- return typeof args[0] === "string" ? args[0].replace(/%s/g, () => index < args.length ? hn.text(args[index++]) : "%s") : undefined;
29
- }
30
- const n = args.map(hn.n);
31
- if (n.some((value) => value === undefined)) return undefined;
32
- const v = n as number[];
33
- switch (fn) {
34
- case "abs": return v.length === 1 ? Math.abs(v[0]!) : undefined;
35
- case "round": return v.length === 1 ? Math.round(v[0]!) : undefined;
36
- case "min": return v.length > 0 ? Math.min(...v) : undefined;
37
- case "max": return v.length > 0 ? Math.max(...v) : undefined;
38
- case "clamp": return v.length === 3 ? Math.min(Math.max(v[0]!, v[1]!), v[2]!) : undefined;
39
- }
40
- return undefined;
18
+ const props = withDefaults(
19
+ defineProps<{
20
+ allowCreate?: boolean
21
+ allowFreeText?: boolean
22
+ clearable?: boolean
23
+ disabled?: boolean
24
+ disclosure?: boolean
25
+ help?: string
26
+ items?:
27
+ readonly ({
28
+ readonly id: string
29
+ readonly value: string
30
+ readonly label: string
31
+ readonly group?: string
32
+ readonly disabled?: boolean
33
+ })[]
34
+ label?: string
35
+ labelVisibility?: 'visible' | 'sr-only'
36
+ multiple?: boolean
37
+ name?: string
38
+ placeholder?: string
39
+ query?: string
40
+ readonly?: boolean
41
+ required?: boolean
42
+ size?: 'sm' | 'md'
43
+ tokenSeparators?: readonly (string)[]
44
+ value?: string | null
45
+ }>(),
46
+ {
47
+ allowCreate: false,
48
+ allowFreeText: false,
49
+ clearable: false,
50
+ disabled: false,
51
+ disclosure: false,
52
+ help: '',
53
+ label: '',
54
+ labelVisibility: 'visible',
55
+ multiple: false,
56
+ name: '',
57
+ placeholder: '',
58
+ readonly: false,
59
+ required: false,
60
+ size: 'md',
41
61
  },
42
- shape: (items: unknown, where: ((item: any) => unknown) | undefined, sort: readonly string[], limit: unknown): any[] => {
43
- let list = Array.isArray(items) ? items.slice() : [];
44
- if (where !== undefined) list = list.filter((item) => hn.t(where(item)));
45
- if (sort.length > 0) {
46
- const field = (item: unknown, path: string): unknown => item !== null && typeof item === "object" && !Array.isArray(item)
47
- ? path.split(".").reduce<unknown>((value, key) => (value as Record<string, unknown> | undefined)?.[key], item)
48
- : item;
49
- const compare = (a: unknown, b: unknown): number => typeof a === "number" && typeof b === "number" ? a - b : hn.text(a).localeCompare(hn.text(b));
50
- list.sort((a, b) => {
51
- for (const key of sort) {
52
- const descending = key.startsWith("-");
53
- const order = compare(field(a, descending ? key.slice(1) : key), field(b, descending ? key.slice(1) : key));
54
- if (order !== 0) return descending ? -order : order;
55
- }
56
- return 0;
57
- });
58
- }
59
- return typeof limit === "number" ? list.slice(0, Math.max(0, Math.trunc(limit))) : list;
60
- },
61
- };
62
-
63
- const props = withDefaults(defineProps<{
64
- allowCreate?: boolean | null;
65
- allowFreeText?: boolean | null;
66
- clearable?: boolean | null;
67
- disabled?: boolean | null;
68
- disclosure?: boolean | null;
69
- help?: string | null;
70
- items?: readonly ({ readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean })[] | null;
71
- label?: string | null;
72
- labelVisibility?: "visible" | "sr-only" | null;
73
- multiple?: boolean | null;
74
- name?: string | null;
75
- placeholder?: string | null;
76
- query?: string | null;
77
- readonly?: boolean | null;
78
- required?: boolean | null;
79
- size?: "sm" | "md" | null;
80
- tokenSeparators?: readonly (string)[] | null;
81
- value?: string | null;
82
- }>(), {
83
- allowCreate: false,
84
- allowFreeText: false,
85
- clearable: false,
86
- disabled: false,
87
- disclosure: false,
88
- help: "",
89
- label: "",
90
- labelVisibility: "visible",
91
- multiple: false,
92
- name: "",
93
- placeholder: "",
94
- readonly: false,
95
- required: false,
96
- size: "md",
97
- });
62
+ )
98
63
  const emit = defineEmits<{
99
- "query-change": [detail: { readonly query: string; readonly display: string; readonly trigger: "keyboard" | "pointer" | "programmatic" }];
100
- "value-change": [detail: { readonly value: string | null; readonly query: string; readonly option: { readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean } | null; readonly kind: "selection" | "clear" | "free-entry" | "create"; readonly trigger: "keyboard" | "pointer" | "programmatic" } | readonly ({ readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean })[]];
101
- "free-entry": [detail: { readonly value: string | null; readonly query: string; readonly option: { readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean } | null; readonly kind: "selection" | "clear" | "free-entry" | "create"; readonly trigger: "keyboard" | "pointer" | "programmatic" }];
102
- "create-entry": [detail: { readonly value: string | null; readonly query: string; readonly option: { readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean } | null; readonly kind: "selection" | "clear" | "free-entry" | "create"; readonly trigger: "keyboard" | "pointer" | "programmatic" }];
103
- "validation-change": [detail: { readonly status: "pristine" | "pending" | "valid" | "warning" | "error"; readonly touched: boolean; readonly dirty: boolean; readonly issues: readonly ({ readonly message: string; readonly path?: readonly (unknown)[]; readonly severity?: "error" | "warning" })[]; readonly output?: unknown }];
104
- "options-change": [detail: readonly ({ readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean })[]];
105
- "add-item": [detail: { readonly item: { readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean }; readonly index: number; readonly trigger: "keyboard" | "pointer" | "programmatic" }];
106
- "remove-item": [detail: { readonly item: { readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean }; readonly index: number; readonly trigger: "keyboard" | "pointer" | "programmatic" }];
107
- "create-item": [detail: { readonly query: string; readonly trigger: "keyboard" | "pointer" | "programmatic" }];
108
- }>();
109
- const root = ref<HTMLElement | null>(null);
110
- const refs: Record<string, Element | undefined> = {};
111
- const state_raw = ref<any>("");
112
- const state_display = ref<any>("");
113
- const state_selected = ref<any>(null);
114
- const state_expanded = ref<any>(false);
115
- const state_rows = ref<any>([]);
116
- const state_active = ref<any>(hn.op("-", 0, 1));
117
- const state_loading = ref<any>(false);
118
- const state_helpOpen = ref<any>(false);
119
- const state_lookupError = ref<any>("");
120
- const state_validation = ref<any>(({ "status": "pristine", "touched": false, "dirty": false, "issues": [] }));
121
- const state_uid = ref<any>("");
122
- const state_groups = ref<any>([]);
123
- const state_creatable = ref<any>(false);
124
- const state_createIndex = ref<any>(0);
125
- const state_message = ref<any>("");
126
- const state_statusText = ref<any>("");
127
- const state_validationStatus = ref<any>("pristine");
64
+ 'update:query': [value: string]
65
+ 'update:value': [value: string | null]
66
+ 'query-change': [
67
+ detail: {
68
+ readonly query: string
69
+ readonly display: string
70
+ readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
71
+ },
72
+ ]
73
+ 'value-change': [
74
+ detail:
75
+ | {
76
+ readonly value: string | null
77
+ readonly query: string
78
+ readonly option: {
79
+ readonly id: string
80
+ readonly value: string
81
+ readonly label: string
82
+ readonly group?: string
83
+ readonly disabled?: boolean
84
+ } | null
85
+ readonly kind: 'selection' | 'clear' | 'free-entry' | 'create'
86
+ readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
87
+ }
88
+ | readonly ({
89
+ readonly id: string
90
+ readonly value: string
91
+ readonly label: string
92
+ readonly group?: string
93
+ readonly disabled?: boolean
94
+ })[],
95
+ ]
96
+ 'free-entry': [
97
+ detail: {
98
+ readonly value: string | null
99
+ readonly query: string
100
+ readonly option: {
101
+ readonly id: string
102
+ readonly value: string
103
+ readonly label: string
104
+ readonly group?: string
105
+ readonly disabled?: boolean
106
+ } | null
107
+ readonly kind: 'selection' | 'clear' | 'free-entry' | 'create'
108
+ readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
109
+ },
110
+ ]
111
+ 'create-entry': [
112
+ detail: {
113
+ readonly value: string | null
114
+ readonly query: string
115
+ readonly option: {
116
+ readonly id: string
117
+ readonly value: string
118
+ readonly label: string
119
+ readonly group?: string
120
+ readonly disabled?: boolean
121
+ } | null
122
+ readonly kind: 'selection' | 'clear' | 'free-entry' | 'create'
123
+ readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
124
+ },
125
+ ]
126
+ 'validation-change': [
127
+ detail: {
128
+ readonly status: 'pristine' | 'pending' | 'valid' | 'warning' | 'error'
129
+ readonly touched: boolean
130
+ readonly dirty: boolean
131
+ readonly issues:
132
+ readonly ({
133
+ readonly message: string
134
+ readonly path?: readonly (unknown)[]
135
+ readonly severity?: 'error' | 'warning'
136
+ })[]
137
+ readonly output?: unknown
138
+ },
139
+ ]
140
+ 'options-change': [
141
+ detail:
142
+ readonly ({
143
+ readonly id: string
144
+ readonly value: string
145
+ readonly label: string
146
+ readonly group?: string
147
+ readonly disabled?: boolean
148
+ })[],
149
+ ]
150
+ 'add-item': [
151
+ detail: {
152
+ readonly item: {
153
+ readonly id: string
154
+ readonly value: string
155
+ readonly label: string
156
+ readonly group?: string
157
+ readonly disabled?: boolean
158
+ }
159
+ readonly index: number
160
+ readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
161
+ },
162
+ ]
163
+ 'remove-item': [
164
+ detail: {
165
+ readonly item: {
166
+ readonly id: string
167
+ readonly value: string
168
+ readonly label: string
169
+ readonly group?: string
170
+ readonly disabled?: boolean
171
+ }
172
+ readonly index: number
173
+ readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
174
+ },
175
+ ]
176
+ 'create-item': [
177
+ detail: { readonly query: string; readonly trigger: 'keyboard' | 'pointer' | 'programmatic' },
178
+ ]
179
+ }>()
180
+
181
+ const root = ref<HTMLElement | null>(null)
182
+ const fieldElement = useTemplateRef<HTMLElement>('field')
183
+ const inputElement = useTemplateRef<HTMLElement>('input')
184
+ const popupElement = useTemplateRef<HTMLElement>('popup')
185
+ const listboxElement = useTemplateRef<HTMLElement>('listbox')
186
+ const optionsElement = useTemplateRef<HTMLElement>('options')
187
+ const raw = ref('')
188
+ const display = ref('')
189
+ const selected = ref<string | null>(null)
190
+ const expanded = ref(false)
191
+ const rows = ref<{ id: string; value: string; label: string; group?: string; disabled: boolean }[]>(
192
+ [],
193
+ )
194
+ const active = ref<number | null>(-1)
195
+ const loading = ref(false)
196
+ const helpOpen = ref(false)
197
+ const lookupError = ref('')
198
+ const validation = ref<
199
+ {
200
+ status: 'pristine' | 'pending' | 'valid' | 'warning' | 'error'
201
+ touched: boolean
202
+ dirty: boolean
203
+ issues: { message: string }[]
204
+ [name: string]: any
205
+ }
206
+ >({ status: 'pristine', touched: false, dirty: false, issues: [] })
207
+ const uid = ref('')
208
+ const groups = ref<
209
+ {
210
+ name: string
211
+ role: 'group' | 'presentation'
212
+ label: string | null
213
+ rows: {
214
+ id: string
215
+ value: string
216
+ label: string
217
+ group?: string
218
+ disabled: boolean
219
+ index: number
220
+ }[]
221
+ }[]
222
+ >([])
223
+ const creatable = ref(false)
224
+ const createIndex = ref(0)
225
+ const message = ref('')
226
+ const statusText = ref('')
227
+ const validationStatus = ref('pristine')
228
+
229
+ /** The values the styles' :host-state() rules test. */
230
+ const hostState = computed(() =>
231
+ [
232
+ props.size && `size size=${props.size}`,
233
+ validationStatus.value && 'validationStatus',
234
+ `validationStatus=${encodeURIComponent(validationStatus.value)}`,
235
+ props.multiple && 'multiple',
236
+ ].filter(Boolean).join(' ')
237
+ )
128
238
 
129
239
  /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
130
- const dispatch = (name: string, detail?: unknown): boolean => {
131
- const declared = {"query-change":{"bubbles":true,"composed":true,"cancelable":false},"value-change":{"bubbles":true,"composed":true,"cancelable":false},"free-entry":{"bubbles":true,"composed":true,"cancelable":false},"create-entry":{"bubbles":true,"composed":true,"cancelable":false},"validation-change":{"bubbles":true,"composed":true,"cancelable":false},"options-change":{"bubbles":true,"composed":true,"cancelable":false},"add-item":{"bubbles":true,"composed":true,"cancelable":false},"remove-item":{"bubbles":true,"composed":true,"cancelable":false},"create-item":{"bubbles":true,"composed":true,"cancelable":false}} as Record<string, EventInit | undefined>;
240
+ function dispatch(name: string, detail?: unknown): boolean {
241
+ const declared: Record<string, EventInit | undefined> = {
242
+ 'query-change': { bubbles: true, composed: true, cancelable: false },
243
+ 'value-change': { bubbles: true, composed: true, cancelable: false },
244
+ 'free-entry': { bubbles: true, composed: true, cancelable: false },
245
+ 'create-entry': { bubbles: true, composed: true, cancelable: false },
246
+ 'validation-change': { bubbles: true, composed: true, cancelable: false },
247
+ 'options-change': { bubbles: true, composed: true, cancelable: false },
248
+ 'add-item': { bubbles: true, composed: true, cancelable: false },
249
+ 'remove-item': { bubbles: true, composed: true, cancelable: false },
250
+ 'create-item': { bubbles: true, composed: true, cancelable: false },
251
+ }
132
252
  const checks: Record<string, (detail: unknown) => boolean> = {
133
- "query-change": (detail: unknown) => (detail !== null && typeof detail === "object" && !Array.isArray(detail) && typeof (detail as Record<string, unknown>)["query"] === "string" && typeof (detail as Record<string, unknown>)["display"] === "string" && ((detail as Record<string, unknown>)["trigger"] === "keyboard" || (detail as Record<string, unknown>)["trigger"] === "pointer" || (detail as Record<string, unknown>)["trigger"] === "programmatic") && Object.keys(detail as object).every((key) => ["query","display","trigger"].includes(key))),
134
- "value-change": (detail: unknown) => ((detail !== null && typeof detail === "object" && !Array.isArray(detail) && (typeof (detail as Record<string, unknown>)["value"] === "string" || (detail as Record<string, unknown>)["value"] === null) && typeof (detail as Record<string, unknown>)["query"] === "string" && (((detail as Record<string, unknown>)["option"] !== null && typeof (detail as Record<string, unknown>)["option"] === "object" && !Array.isArray((detail as Record<string, unknown>)["option"]) && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["id"] === "string" && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["value"] === "string" && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["label"] === "string" && (((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["group"] === undefined || typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["group"] === "string") && (((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["disabled"] === undefined || typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["disabled"] === "boolean") && Object.keys((detail as Record<string, unknown>)["option"] as object).every((key) => ["id","value","label","group","disabled"].includes(key))) || (detail as Record<string, unknown>)["option"] === null) && ((detail as Record<string, unknown>)["kind"] === "selection" || (detail as Record<string, unknown>)["kind"] === "clear" || (detail as Record<string, unknown>)["kind"] === "free-entry" || (detail as Record<string, unknown>)["kind"] === "create") && ((detail as Record<string, unknown>)["trigger"] === "keyboard" || (detail as Record<string, unknown>)["trigger"] === "pointer" || (detail as Record<string, unknown>)["trigger"] === "programmatic") && Object.keys(detail as object).every((key) => ["value","query","option","kind","trigger"].includes(key))) || (Array.isArray(detail) && (detail as unknown[]).every((item: unknown) => (item !== null && typeof item === "object" && !Array.isArray(item) && typeof (item as Record<string, unknown>)["id"] === "string" && typeof (item as Record<string, unknown>)["value"] === "string" && typeof (item as Record<string, unknown>)["label"] === "string" && ((item as Record<string, unknown>)["group"] === undefined || typeof (item as Record<string, unknown>)["group"] === "string") && ((item as Record<string, unknown>)["disabled"] === undefined || typeof (item as Record<string, unknown>)["disabled"] === "boolean") && Object.keys(item as object).every((key) => ["id","value","label","group","disabled"].includes(key)))))),
135
- "free-entry": (detail: unknown) => (detail !== null && typeof detail === "object" && !Array.isArray(detail) && (typeof (detail as Record<string, unknown>)["value"] === "string" || (detail as Record<string, unknown>)["value"] === null) && typeof (detail as Record<string, unknown>)["query"] === "string" && (((detail as Record<string, unknown>)["option"] !== null && typeof (detail as Record<string, unknown>)["option"] === "object" && !Array.isArray((detail as Record<string, unknown>)["option"]) && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["id"] === "string" && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["value"] === "string" && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["label"] === "string" && (((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["group"] === undefined || typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["group"] === "string") && (((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["disabled"] === undefined || typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["disabled"] === "boolean") && Object.keys((detail as Record<string, unknown>)["option"] as object).every((key) => ["id","value","label","group","disabled"].includes(key))) || (detail as Record<string, unknown>)["option"] === null) && ((detail as Record<string, unknown>)["kind"] === "selection" || (detail as Record<string, unknown>)["kind"] === "clear" || (detail as Record<string, unknown>)["kind"] === "free-entry" || (detail as Record<string, unknown>)["kind"] === "create") && ((detail as Record<string, unknown>)["trigger"] === "keyboard" || (detail as Record<string, unknown>)["trigger"] === "pointer" || (detail as Record<string, unknown>)["trigger"] === "programmatic") && Object.keys(detail as object).every((key) => ["value","query","option","kind","trigger"].includes(key))),
136
- "create-entry": (detail: unknown) => (detail !== null && typeof detail === "object" && !Array.isArray(detail) && (typeof (detail as Record<string, unknown>)["value"] === "string" || (detail as Record<string, unknown>)["value"] === null) && typeof (detail as Record<string, unknown>)["query"] === "string" && (((detail as Record<string, unknown>)["option"] !== null && typeof (detail as Record<string, unknown>)["option"] === "object" && !Array.isArray((detail as Record<string, unknown>)["option"]) && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["id"] === "string" && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["value"] === "string" && typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["label"] === "string" && (((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["group"] === undefined || typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["group"] === "string") && (((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["disabled"] === undefined || typeof ((detail as Record<string, unknown>)["option"] as Record<string, unknown>)["disabled"] === "boolean") && Object.keys((detail as Record<string, unknown>)["option"] as object).every((key) => ["id","value","label","group","disabled"].includes(key))) || (detail as Record<string, unknown>)["option"] === null) && ((detail as Record<string, unknown>)["kind"] === "selection" || (detail as Record<string, unknown>)["kind"] === "clear" || (detail as Record<string, unknown>)["kind"] === "free-entry" || (detail as Record<string, unknown>)["kind"] === "create") && ((detail as Record<string, unknown>)["trigger"] === "keyboard" || (detail as Record<string, unknown>)["trigger"] === "pointer" || (detail as Record<string, unknown>)["trigger"] === "programmatic") && Object.keys(detail as object).every((key) => ["value","query","option","kind","trigger"].includes(key))),
137
- "validation-change": (detail: unknown) => (detail !== null && typeof detail === "object" && !Array.isArray(detail) && ((detail as Record<string, unknown>)["status"] === "pristine" || (detail as Record<string, unknown>)["status"] === "pending" || (detail as Record<string, unknown>)["status"] === "valid" || (detail as Record<string, unknown>)["status"] === "warning" || (detail as Record<string, unknown>)["status"] === "error") && typeof (detail as Record<string, unknown>)["touched"] === "boolean" && typeof (detail as Record<string, unknown>)["dirty"] === "boolean" && (Array.isArray((detail as Record<string, unknown>)["issues"]) && ((detail as Record<string, unknown>)["issues"] as unknown[]).every((item: unknown) => (item !== null && typeof item === "object" && !Array.isArray(item) && typeof (item as Record<string, unknown>)["message"] === "string" && ((item as Record<string, unknown>)["path"] === undefined || (Array.isArray((item as Record<string, unknown>)["path"]) && ((item as Record<string, unknown>)["path"] as unknown[]).every((item: unknown) => true))) && ((item as Record<string, unknown>)["severity"] === undefined || ((item as Record<string, unknown>)["severity"] === "error" || (item as Record<string, unknown>)["severity"] === "warning")) && Object.keys(item as object).every((key) => ["message","path","severity"].includes(key))))) && ((detail as Record<string, unknown>)["output"] === undefined || true) && Object.keys(detail as object).every((key) => ["status","touched","dirty","issues","output"].includes(key))),
138
- "options-change": (detail: unknown) => (Array.isArray(detail) && (detail as unknown[]).every((item: unknown) => (item !== null && typeof item === "object" && !Array.isArray(item) && typeof (item as Record<string, unknown>)["id"] === "string" && typeof (item as Record<string, unknown>)["value"] === "string" && typeof (item as Record<string, unknown>)["label"] === "string" && ((item as Record<string, unknown>)["group"] === undefined || typeof (item as Record<string, unknown>)["group"] === "string") && ((item as Record<string, unknown>)["disabled"] === undefined || typeof (item as Record<string, unknown>)["disabled"] === "boolean") && Object.keys(item as object).every((key) => ["id","value","label","group","disabled"].includes(key))))),
139
- "add-item": (detail: unknown) => (detail !== null && typeof detail === "object" && !Array.isArray(detail) && ((detail as Record<string, unknown>)["item"] !== null && typeof (detail as Record<string, unknown>)["item"] === "object" && !Array.isArray((detail as Record<string, unknown>)["item"]) && typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["id"] === "string" && typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["value"] === "string" && typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["label"] === "string" && (((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["group"] === undefined || typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["group"] === "string") && (((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["disabled"] === undefined || typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["disabled"] === "boolean") && Object.keys((detail as Record<string, unknown>)["item"] as object).every((key) => ["id","value","label","group","disabled"].includes(key))) && Number.isInteger((detail as Record<string, unknown>)["index"]) && ((detail as Record<string, unknown>)["trigger"] === "keyboard" || (detail as Record<string, unknown>)["trigger"] === "pointer" || (detail as Record<string, unknown>)["trigger"] === "programmatic") && Object.keys(detail as object).every((key) => ["item","index","trigger"].includes(key))),
140
- "remove-item": (detail: unknown) => (detail !== null && typeof detail === "object" && !Array.isArray(detail) && ((detail as Record<string, unknown>)["item"] !== null && typeof (detail as Record<string, unknown>)["item"] === "object" && !Array.isArray((detail as Record<string, unknown>)["item"]) && typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["id"] === "string" && typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["value"] === "string" && typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["label"] === "string" && (((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["group"] === undefined || typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["group"] === "string") && (((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["disabled"] === undefined || typeof ((detail as Record<string, unknown>)["item"] as Record<string, unknown>)["disabled"] === "boolean") && Object.keys((detail as Record<string, unknown>)["item"] as object).every((key) => ["id","value","label","group","disabled"].includes(key))) && Number.isInteger((detail as Record<string, unknown>)["index"]) && ((detail as Record<string, unknown>)["trigger"] === "keyboard" || (detail as Record<string, unknown>)["trigger"] === "pointer" || (detail as Record<string, unknown>)["trigger"] === "programmatic") && Object.keys(detail as object).every((key) => ["item","index","trigger"].includes(key))),
141
- "create-item": (detail: unknown) => (detail !== null && typeof detail === "object" && !Array.isArray(detail) && typeof (detail as Record<string, unknown>)["query"] === "string" && ((detail as Record<string, unknown>)["trigger"] === "keyboard" || (detail as Record<string, unknown>)["trigger"] === "pointer" || (detail as Record<string, unknown>)["trigger"] === "programmatic") && Object.keys(detail as object).every((key) => ["query","trigger"].includes(key))),
142
- };
253
+ 'query-change': (detail) =>
254
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
255
+ && typeof (detail as Record<string, unknown>)['query'] === 'string'
256
+ && typeof (detail as Record<string, unknown>)['display'] === 'string'
257
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
258
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
259
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
260
+ && Object.keys(detail as object).every((key) =>
261
+ ['query', 'display', 'trigger'].includes(key)
262
+ ),
263
+ 'value-change': (detail) =>
264
+ (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
265
+ && (typeof (detail as Record<string, unknown>)['value'] === 'string'
266
+ || (detail as Record<string, unknown>)['value'] === null)
267
+ && typeof (detail as Record<string, unknown>)['query'] === 'string'
268
+ && (((detail as Record<string, unknown>)['option'] !== null
269
+ && typeof (detail as Record<string, unknown>)['option'] === 'object'
270
+ && !Array.isArray((detail as Record<string, unknown>)['option'])
271
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['id']
272
+ === 'string'
273
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
274
+ 'value'
275
+ ] === 'string'
276
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
277
+ 'label'
278
+ ] === 'string'
279
+ && (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['group']
280
+ === undefined
281
+ || typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
282
+ 'group'
283
+ ] === 'string')
284
+ && (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['disabled']
285
+ === undefined
286
+ || typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
287
+ 'disabled'
288
+ ] === 'boolean')
289
+ && Object.keys((detail as Record<string, unknown>)['option'] as object).every((key) =>
290
+ ['id', 'value', 'label', 'group', 'disabled'].includes(key)
291
+ )) || (detail as Record<string, unknown>)['option'] === null)
292
+ && ((detail as Record<string, unknown>)['kind'] === 'selection'
293
+ || (detail as Record<string, unknown>)['kind'] === 'clear'
294
+ || (detail as Record<string, unknown>)['kind'] === 'free-entry'
295
+ || (detail as Record<string, unknown>)['kind'] === 'create')
296
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
297
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
298
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
299
+ && Object.keys(detail as object).every((key) =>
300
+ ['value', 'query', 'option', 'kind', 'trigger'].includes(key)
301
+ ))
302
+ || (Array.isArray(detail)
303
+ && (detail as unknown[]).every((
304
+ item: unknown,
305
+ ) => (item !== null && typeof item === 'object' && !Array.isArray(item)
306
+ && typeof (item as Record<string, unknown>)['id'] === 'string'
307
+ && typeof (item as Record<string, unknown>)['value'] === 'string'
308
+ && typeof (item as Record<string, unknown>)['label'] === 'string'
309
+ && ((item as Record<string, unknown>)['group'] === undefined
310
+ || typeof (item as Record<string, unknown>)['group'] === 'string')
311
+ && ((item as Record<string, unknown>)['disabled'] === undefined
312
+ || typeof (item as Record<string, unknown>)['disabled'] === 'boolean')
313
+ && Object.keys(item as object).every((key) =>
314
+ ['id', 'value', 'label', 'group', 'disabled'].includes(key)
315
+ ))
316
+ )),
317
+ 'free-entry': (detail) =>
318
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
319
+ && (typeof (detail as Record<string, unknown>)['value'] === 'string'
320
+ || (detail as Record<string, unknown>)['value'] === null)
321
+ && typeof (detail as Record<string, unknown>)['query'] === 'string'
322
+ && (((detail as Record<string, unknown>)['option'] !== null
323
+ && typeof (detail as Record<string, unknown>)['option'] === 'object'
324
+ && !Array.isArray((detail as Record<string, unknown>)['option'])
325
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['id']
326
+ === 'string'
327
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
328
+ 'value'
329
+ ] === 'string'
330
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
331
+ 'label'
332
+ ] === 'string'
333
+ && (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['group']
334
+ === undefined
335
+ || typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
336
+ 'group'
337
+ ] === 'string')
338
+ && (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['disabled']
339
+ === undefined
340
+ || typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
341
+ 'disabled'
342
+ ] === 'boolean')
343
+ && Object.keys((detail as Record<string, unknown>)['option'] as object).every((key) =>
344
+ ['id', 'value', 'label', 'group', 'disabled'].includes(key)
345
+ )) || (detail as Record<string, unknown>)['option'] === null)
346
+ && ((detail as Record<string, unknown>)['kind'] === 'selection'
347
+ || (detail as Record<string, unknown>)['kind'] === 'clear'
348
+ || (detail as Record<string, unknown>)['kind'] === 'free-entry'
349
+ || (detail as Record<string, unknown>)['kind'] === 'create')
350
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
351
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
352
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
353
+ && Object.keys(detail as object).every((key) =>
354
+ ['value', 'query', 'option', 'kind', 'trigger'].includes(key)
355
+ ),
356
+ 'create-entry': (detail) =>
357
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
358
+ && (typeof (detail as Record<string, unknown>)['value'] === 'string'
359
+ || (detail as Record<string, unknown>)['value'] === null)
360
+ && typeof (detail as Record<string, unknown>)['query'] === 'string'
361
+ && (((detail as Record<string, unknown>)['option'] !== null
362
+ && typeof (detail as Record<string, unknown>)['option'] === 'object'
363
+ && !Array.isArray((detail as Record<string, unknown>)['option'])
364
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['id']
365
+ === 'string'
366
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
367
+ 'value'
368
+ ] === 'string'
369
+ && typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
370
+ 'label'
371
+ ] === 'string'
372
+ && (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['group']
373
+ === undefined
374
+ || typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
375
+ 'group'
376
+ ] === 'string')
377
+ && (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['disabled']
378
+ === undefined
379
+ || typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
380
+ 'disabled'
381
+ ] === 'boolean')
382
+ && Object.keys((detail as Record<string, unknown>)['option'] as object).every((key) =>
383
+ ['id', 'value', 'label', 'group', 'disabled'].includes(key)
384
+ )) || (detail as Record<string, unknown>)['option'] === null)
385
+ && ((detail as Record<string, unknown>)['kind'] === 'selection'
386
+ || (detail as Record<string, unknown>)['kind'] === 'clear'
387
+ || (detail as Record<string, unknown>)['kind'] === 'free-entry'
388
+ || (detail as Record<string, unknown>)['kind'] === 'create')
389
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
390
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
391
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
392
+ && Object.keys(detail as object).every((key) =>
393
+ ['value', 'query', 'option', 'kind', 'trigger'].includes(key)
394
+ ),
395
+ 'validation-change': (detail) =>
396
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
397
+ && ((detail as Record<string, unknown>)['status'] === 'pristine'
398
+ || (detail as Record<string, unknown>)['status'] === 'pending'
399
+ || (detail as Record<string, unknown>)['status'] === 'valid'
400
+ || (detail as Record<string, unknown>)['status'] === 'warning'
401
+ || (detail as Record<string, unknown>)['status'] === 'error')
402
+ && typeof (detail as Record<string, unknown>)['touched'] === 'boolean'
403
+ && typeof (detail as Record<string, unknown>)['dirty'] === 'boolean'
404
+ && (Array.isArray((detail as Record<string, unknown>)['issues'])
405
+ && ((detail as Record<string, unknown>)['issues'] as unknown[]).every((
406
+ item: unknown,
407
+ ) => (item !== null && typeof item === 'object' && !Array.isArray(item)
408
+ && typeof (item as Record<string, unknown>)['message'] === 'string'
409
+ && ((item as Record<string, unknown>)['path'] === undefined
410
+ || (Array.isArray((item as Record<string, unknown>)['path'])
411
+ && ((item as Record<string, unknown>)['path'] as unknown[]).every((item: unknown) =>
412
+ true
413
+ )))
414
+ && ((item as Record<string, unknown>)['severity'] === undefined
415
+ || ((item as Record<string, unknown>)['severity'] === 'error'
416
+ || (item as Record<string, unknown>)['severity'] === 'warning'))
417
+ && Object.keys(item as object).every((key) =>
418
+ ['message', 'path', 'severity'].includes(key)
419
+ ))
420
+ ))
421
+ && ((detail as Record<string, unknown>)['output'] === undefined || true)
422
+ && Object.keys(detail as object).every((key) =>
423
+ ['status', 'touched', 'dirty', 'issues', 'output'].includes(key)
424
+ ),
425
+ 'options-change': (detail) =>
426
+ Array.isArray(detail)
427
+ && (detail as unknown[]).every((
428
+ item: unknown,
429
+ ) => (item !== null && typeof item === 'object' && !Array.isArray(item)
430
+ && typeof (item as Record<string, unknown>)['id'] === 'string'
431
+ && typeof (item as Record<string, unknown>)['value'] === 'string'
432
+ && typeof (item as Record<string, unknown>)['label'] === 'string'
433
+ && ((item as Record<string, unknown>)['group'] === undefined
434
+ || typeof (item as Record<string, unknown>)['group'] === 'string')
435
+ && ((item as Record<string, unknown>)['disabled'] === undefined
436
+ || typeof (item as Record<string, unknown>)['disabled'] === 'boolean')
437
+ && Object.keys(item as object).every((key) =>
438
+ ['id', 'value', 'label', 'group', 'disabled'].includes(key)
439
+ ))
440
+ ),
441
+ 'add-item': (detail) =>
442
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
443
+ && ((detail as Record<string, unknown>)['item'] !== null
444
+ && typeof (detail as Record<string, unknown>)['item'] === 'object'
445
+ && !Array.isArray((detail as Record<string, unknown>)['item'])
446
+ && typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['id']
447
+ === 'string'
448
+ && typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['value']
449
+ === 'string'
450
+ && typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['label']
451
+ === 'string'
452
+ && (((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['group']
453
+ === undefined
454
+ || typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)[
455
+ 'group'
456
+ ] === 'string')
457
+ && (((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['disabled']
458
+ === undefined
459
+ || typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)[
460
+ 'disabled'
461
+ ] === 'boolean')
462
+ && Object.keys((detail as Record<string, unknown>)['item'] as object).every((key) =>
463
+ ['id', 'value', 'label', 'group', 'disabled'].includes(key)
464
+ ))
465
+ && Number.isInteger((detail as Record<string, unknown>)['index'])
466
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
467
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
468
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
469
+ && Object.keys(detail as object).every((key) =>
470
+ ['item', 'index', 'trigger'].includes(key)
471
+ ),
472
+ 'remove-item': (detail) =>
473
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
474
+ && ((detail as Record<string, unknown>)['item'] !== null
475
+ && typeof (detail as Record<string, unknown>)['item'] === 'object'
476
+ && !Array.isArray((detail as Record<string, unknown>)['item'])
477
+ && typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['id']
478
+ === 'string'
479
+ && typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['value']
480
+ === 'string'
481
+ && typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['label']
482
+ === 'string'
483
+ && (((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['group']
484
+ === undefined
485
+ || typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)[
486
+ 'group'
487
+ ] === 'string')
488
+ && (((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['disabled']
489
+ === undefined
490
+ || typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)[
491
+ 'disabled'
492
+ ] === 'boolean')
493
+ && Object.keys((detail as Record<string, unknown>)['item'] as object).every((key) =>
494
+ ['id', 'value', 'label', 'group', 'disabled'].includes(key)
495
+ ))
496
+ && Number.isInteger((detail as Record<string, unknown>)['index'])
497
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
498
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
499
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
500
+ && Object.keys(detail as object).every((key) =>
501
+ ['item', 'index', 'trigger'].includes(key)
502
+ ),
503
+ 'create-item': (detail) =>
504
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
505
+ && typeof (detail as Record<string, unknown>)['query'] === 'string'
506
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
507
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
508
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
509
+ && Object.keys(detail as object).every((key) => ['query', 'trigger'].includes(key)),
510
+ }
143
511
  if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
144
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`);
512
+ throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
145
513
  }
146
- (emit as (name: string, detail: unknown) => void)(name, detail);
147
- return root.value?.dispatchEvent(new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail })) ?? true;
148
- };
149
-
150
- /** The resolved values the styles' :host-state() rules test. */
151
- const hostState = computed(() => (["size","validationStatus","multiple"] as const).flatMap((name) => {
152
- const value = read(name);
153
- const tokens: string[] = hn.t(value) ? [name] : [];
154
- if (typeof value === "string" || typeof value === "number") tokens.push(`${name}=${encodeURIComponent(String(value))}`);
155
- return tokens;
156
- }).join(" "));
514
+ const emitEvent = emit as (name: string, detail: unknown) => void
515
+ emitEvent(name, detail)
516
+ if (detail !== null && typeof detail === 'object' && 'query' in detail) {
517
+ emitEvent('update:query', (detail as Record<string, unknown>)['query'])
518
+ }
519
+ if (detail !== null && typeof detail === 'object' && 'value' in detail) {
520
+ emitEvent('update:value', (detail as Record<string, unknown>)['value'])
521
+ }
522
+ return root.value?.dispatchEvent(
523
+ new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
524
+ ) ?? true
525
+ }
157
526
 
158
527
  function read(name: string): unknown {
159
- if (name === "raw") return state_raw.value;
160
- if (name === "display") return state_display.value;
161
- if (name === "selected") return state_selected.value;
162
- if (name === "expanded") return state_expanded.value;
163
- if (name === "rows") return state_rows.value;
164
- if (name === "active") return state_active.value;
165
- if (name === "loading") return state_loading.value;
166
- if (name === "helpOpen") return state_helpOpen.value;
167
- if (name === "lookupError") return state_lookupError.value;
168
- if (name === "validation") return state_validation.value;
169
- if (name === "uid") return state_uid.value;
170
- if (name === "groups") return state_groups.value;
171
- if (name === "creatable") return state_creatable.value;
172
- if (name === "createIndex") return state_createIndex.value;
173
- if (name === "message") return state_message.value;
174
- if (name === "statusText") return state_statusText.value;
175
- if (name === "validationStatus") return state_validationStatus.value;
176
- return (props as Record<string, unknown>)[name];
528
+ if (name === 'raw') return raw.value
529
+ if (name === 'display') return display.value
530
+ if (name === 'selected') return selected.value
531
+ if (name === 'expanded') return expanded.value
532
+ if (name === 'rows') return rows.value
533
+ if (name === 'active') return active.value
534
+ if (name === 'loading') return loading.value
535
+ if (name === 'helpOpen') return helpOpen.value
536
+ if (name === 'lookupError') return lookupError.value
537
+ if (name === 'validation') return validation.value
538
+ if (name === 'uid') return uid.value
539
+ if (name === 'groups') return groups.value
540
+ if (name === 'creatable') return creatable.value
541
+ if (name === 'createIndex') return createIndex.value
542
+ if (name === 'message') return message.value
543
+ if (name === 'statusText') return statusText.value
544
+ if (name === 'validationStatus') return validationStatus.value
545
+ return (props as Record<string, unknown>)[name]
177
546
  }
178
547
 
179
548
  function write(name: string, value: unknown): boolean {
180
- if (name === "raw") { state_raw.value = value; return true; }
181
- if (name === "display") { state_display.value = value; return true; }
182
- if (name === "selected") { state_selected.value = value; return true; }
183
- if (name === "expanded") { state_expanded.value = value; return true; }
184
- if (name === "rows") { state_rows.value = value; return true; }
185
- if (name === "active") { state_active.value = value; return true; }
186
- if (name === "loading") { state_loading.value = value; return true; }
187
- if (name === "helpOpen") { state_helpOpen.value = value; return true; }
188
- if (name === "lookupError") { state_lookupError.value = value; return true; }
189
- if (name === "validation") { state_validation.value = value; return true; }
190
- if (name === "uid") { state_uid.value = value; return true; }
191
- if (name === "groups") { state_groups.value = value; return true; }
192
- if (name === "creatable") { state_creatable.value = value; return true; }
193
- if (name === "createIndex") { state_createIndex.value = value; return true; }
194
- if (name === "message") { state_message.value = value; return true; }
195
- if (name === "statusText") { state_statusText.value = value; return true; }
196
- if (name === "validationStatus") { state_validationStatus.value = value; return true; }
197
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`);
549
+ if (name === 'raw') {
550
+ raw.value = value as never
551
+ return true
552
+ }
553
+ if (name === 'display') {
554
+ display.value = value as never
555
+ return true
556
+ }
557
+ if (name === 'selected') {
558
+ selected.value = value as never
559
+ return true
560
+ }
561
+ if (name === 'expanded') {
562
+ expanded.value = value as never
563
+ return true
564
+ }
565
+ if (name === 'rows') {
566
+ rows.value = value as never
567
+ return true
568
+ }
569
+ if (name === 'active') {
570
+ active.value = value as never
571
+ return true
572
+ }
573
+ if (name === 'loading') {
574
+ loading.value = value as never
575
+ return true
576
+ }
577
+ if (name === 'helpOpen') {
578
+ helpOpen.value = value as never
579
+ return true
580
+ }
581
+ if (name === 'lookupError') {
582
+ lookupError.value = value as never
583
+ return true
584
+ }
585
+ if (name === 'validation') {
586
+ validation.value = value as never
587
+ return true
588
+ }
589
+ if (name === 'uid') {
590
+ uid.value = value as never
591
+ return true
592
+ }
593
+ if (name === 'groups') {
594
+ groups.value = value as never
595
+ return true
596
+ }
597
+ if (name === 'creatable') {
598
+ creatable.value = value as never
599
+ return true
600
+ }
601
+ if (name === 'createIndex') {
602
+ createIndex.value = value as never
603
+ return true
604
+ }
605
+ if (name === 'message') {
606
+ message.value = value as never
607
+ return true
608
+ }
609
+ if (name === 'statusText') {
610
+ statusText.value = value as never
611
+ return true
612
+ }
613
+ if (name === 'validationStatus') {
614
+ validationStatus.value = value as never
615
+ return true
616
+ }
617
+ throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
198
618
  }
199
619
 
200
- const stops: Array<() => void> = [];
620
+ const stops: Array<() => void> = []
201
621
  const host = {
202
- get element(): Element { return root.value as Element; },
622
+ get element(): Element {
623
+ return root.value as Element
624
+ },
203
625
  state: new Proxy({} as Record<string, unknown>, {
204
- get: (_target, name) => typeof name === "string" ? read(name) : undefined,
205
- set: (_target, name, value) => typeof name === "string" && write(name, value),
626
+ get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
627
+ set: (_target, name, value) => typeof name === 'string' && write(name, value),
206
628
  }),
207
- refs: refs as Readonly<Record<string, Element>>,
629
+ refs: {
630
+ get field(): Element {
631
+ return fieldElement.value as Element
632
+ },
633
+ get input(): Element {
634
+ return inputElement.value as Element
635
+ },
636
+ get popup(): Element {
637
+ return popupElement.value as Element
638
+ },
639
+ get listbox(): Element {
640
+ return listboxElement.value as Element
641
+ },
642
+ get options(): Element {
643
+ return optionsElement.value as Element
644
+ },
645
+ } as Readonly<Record<string, Element>>,
208
646
  elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
209
647
  get: (_target, name) => {
210
- if (typeof name !== "string" || root.value === null) return undefined;
211
- const form = root.value instanceof HTMLFormElement ? root.value : root.value.querySelector("form");
212
- return form?.elements.namedItem(name) ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined;
648
+ if (typeof name !== 'string' || root.value === null) return undefined
649
+ const form = root.value instanceof HTMLFormElement
650
+ ? root.value
651
+ : root.value.querySelector('form')
652
+ return form?.elements.namedItem(name)
653
+ ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
213
654
  },
214
655
  }),
215
656
  signal<T>(initialValue: T) {
216
- const value = shallowRef(initialValue);
657
+ const value = shallowRef(initialValue)
217
658
  return {
218
659
  get: (): T => value.value,
219
- set: (next: T): void => { if (!Object.is(value.value, next)) value.value = next; },
220
- update: (next: (current: T) => T): void => { const updated = next(value.value); if (!Object.is(value.value, updated)) value.value = updated; },
221
- };
660
+ set: (next: T): void => {
661
+ if (!Object.is(value.value, next)) value.value = next
662
+ },
663
+ update: (next: (current: T) => T): void => {
664
+ const updated = next(value.value)
665
+ if (!Object.is(value.value, updated)) value.value = updated
666
+ },
667
+ }
222
668
  },
223
669
  computed<T>(compute: () => T) {
224
- const value = computed(compute);
225
- return { get: (): T => value.value };
670
+ const value = computed(compute)
671
+ return { get: (): T => value.value }
226
672
  },
227
673
  effect(run: () => void | (() => void)): () => void {
228
674
  const stop = watchEffect((onCleanup) => {
229
- const cleanup = run();
230
- if (typeof cleanup === "function") onCleanup(cleanup);
231
- }, { flush: "post" });
232
- stops.push(stop);
233
- return stop;
675
+ const cleanup = run()
676
+ if (typeof cleanup === 'function') onCleanup(cleanup)
677
+ }, { flush: 'post' })
678
+ stops.push(stop)
679
+ return stop
234
680
  },
235
681
  on(event: string, listener: EventListener): () => void {
236
- const element = root.value;
237
- element?.addEventListener(event, listener);
238
- const off = (): void => element?.removeEventListener(event, listener);
239
- stops.push(off);
240
- return off;
682
+ const element = root.value
683
+ element?.addEventListener(event, listener)
684
+ const off = (): void => element?.removeEventListener(event, listener)
685
+ stops.push(off)
686
+ return off
241
687
  },
242
688
  dispatch,
243
- };
689
+ }
244
690
 
245
- let cleanup: void | (() => void);
246
- let ready: Promise<void> | undefined;
691
+ let cleanup: void | (() => void)
692
+ let ready: Promise<void> | undefined
247
693
  onMounted(() => {
248
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => { cleanup = result; });
249
- });
694
+ ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
695
+ cleanup = result
696
+ })
697
+ })
250
698
  onBeforeUnmount(() => {
251
- for (const stop of stops.splice(0)) stop();
252
- if (typeof cleanup === "function") cleanup();
253
- });
699
+ for (const stop of stops.splice(0)) stop()
700
+ if (typeof cleanup === 'function') cleanup()
701
+ })
254
702
  defineExpose({
255
- validate: async (...args: unknown[]) => { await ready; return (controllerModule as Record<string, (...values: unknown[]) => unknown>)["validate"]!(host, ...args); },
256
- focusInput: async (...args: unknown[]) => { await ready; return (controllerModule as Record<string, (...values: unknown[]) => unknown>)["focusInput"]!(host, ...args); },
257
- });
703
+ validate: async (...args: unknown[]) => {
704
+ await ready
705
+ return (controllerModule as Record<string, (...values: unknown[]) => unknown>)['validate']!(
706
+ host,
707
+ ...args,
708
+ )
709
+ },
710
+ focusInput: async (...args: unknown[]) => {
711
+ await ready
712
+ return (controllerModule as Record<string, (...values: unknown[]) => unknown>)['focusInput']!(
713
+ host,
714
+ ...args,
715
+ )
716
+ },
717
+ })
258
718
  </script>
259
719
 
260
720
  <template>
261
- <div data-component="ui-combobox" v-bind="$attrs" :data-ui-combobox-state="hostState || undefined" ref="root"><label :for="hn.attr(hn.call('format', '%s-input', state_uid))" :class="{ 'sr-only': hn.t((props.labelVisibility === 'sr-only')) }">{{ hn.text(props.label) }}<template v-if="hn.t(props.required)">
262
- *</template></label><div class="field" :ref="(element) => { refs['field'] = element as Element }"><slot name="start"></slot><template v-if="hn.t(props.multiple)"><template v-for="(item, index) in hn.shape(props.items, undefined, [], undefined)" :key="(item)?.id"><button class="item" type="button" tabindex="-1" :data-index="hn.attr(index)" :disabled="hn.attr((hn.t((hn.t(props.disabled) || hn.t(props.readonly))) || hn.t((item)?.disabled)))" :aria-label="hn.enumerated(hn.call('format', '%s, press Delete or Backspace to remove', (item)?.label))"><slot :name="hn.call('format', 'item-%s', (item)?.id)"><UiBadge>{{ hn.text((item)?.label) }}</UiBadge></slot></button></template></template><input role="combobox" aria-autocomplete="list" autocomplete="off" :id="hn.attr(hn.call('format', '%s-input', state_uid))" :aria-controls="hn.enumerated(hn.call('format', '%s-listbox', state_uid))" :aria-expanded="hn.enumerated(state_expanded)" :aria-invalid="hn.enumerated((state_validationStatus === 'error'))" :aria-busy="hn.enumerated((state_validationStatus === 'pending'))" :value.prop="(state_display) as any" :placeholder="hn.attr(props.placeholder)" :name="hn.attr(props.name)" :disabled="hn.attr(props.disabled)" :readonly="hn.attr(props.readonly)" :required="hn.attr(props.required)" :ref="(element) => { refs['input'] = element as Element }"><template v-if="hn.t(props.clearable)"><button type="button" data-combobox-action="clear" aria-label="Clear"><svg class="affordance-icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M7 7l10 10M17 7 7 17"></path></svg></button></template><template v-if="hn.t(props.help)"><button type="button" aria-label="Help" :id="hn.attr(hn.call('format', '%s-help', state_uid))" :disabled="hn.attr(props.disabled)"><span aria-hidden="true">?</span></button></template><template v-if="hn.t(props.disclosure)"><button type="button" data-combobox-action="disclosure" tabindex="-1" aria-label="Show suggestions" :aria-controls="hn.enumerated(hn.call('format', '%s-listbox', state_uid))"><svg class="affordance-icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"></path></svg></button></template></div><template v-if="hn.t(props.help)"><UiTooltip :id="hn.call('format', '%s-help-text', state_uid)" :for="hn.call('format', '%s-help', state_uid)">{{ hn.text(props.help) }}</UiTooltip></template><div class="popup" :hidden="hn.attr(!hn.t(state_expanded))" :ref="(element) => { refs['popup'] = element as Element }"><div role="listbox" :id="hn.attr(hn.call('format', '%s-listbox', state_uid))" :aria-label="hn.enumerated(hn.call('format', '%s suggestions', props.label))" :aria-busy="hn.enumerated(state_loading)" :ref="(element) => { refs['listbox'] = element as Element }"><template v-for="(group, index) in hn.shape(state_groups, undefined, [], undefined)" :key="(group)?.name"><div :role="hn.attr((group)?.role)" :aria-label="hn.enumerated((group)?.label)"><template v-if="hn.t((group)?.name)"><div class="group">{{ hn.text((group)?.name) }}</div></template><template v-for="(row, index) in hn.shape((group)?.rows, undefined, [], undefined)" :key="(row)?.id"><div class="option" role="option" :id="hn.attr(hn.call('format', '%s-option-%s', state_uid, (row)?.index))" :aria-selected="hn.enumerated(((row)?.value === state_selected))" :aria-disabled="hn.enumerated((row)?.disabled)" :data-index="hn.attr((row)?.index)" :class="{ 'active': hn.t(((row)?.index === state_active)) }"><slot :name="hn.call('format', 'option-%s', (row)?.id)"><span class="primary">{{ hn.text((row)?.label) }}</span></slot></div></template></div></template><template v-if="hn.t(state_creatable)"><div class="option" role="option" aria-selected="false" :id="hn.attr(hn.call('format', '%s-option-%s', state_uid, state_createIndex))" :data-index="hn.attr(state_createIndex)" :class="{ 'active': hn.t((state_createIndex === state_active)) }">{{ hn.text(hn.call("format", "Create “%s”", state_raw)) }}</div></template><template v-if="hn.t(state_message)"><div class="message">{{ hn.text(state_message) }}</div></template></div><slot name="footer"></slot></div><div class="message" :id="hn.attr(hn.call('format', '%s-validation', state_uid))" :hidden="hn.attr(!hn.t(((state_validation)?.issues)?.length))"><template v-for="(issue, index) in hn.shape((state_validation)?.issues, undefined, [], undefined)" :key="index"><div>{{ hn.text((issue)?.message) }}</div></template></div><div class="sr-only" role="status" aria-live="polite" aria-atomic="true">{{ hn.text(state_statusText) }}</div><div class="authored-options" hidden="" aria-hidden="true" :ref="(element) => { refs['options'] = element as Element }"><slot></slot></div></div>
721
+ <div
722
+ data-component="ui-combobox"
723
+ v-bind="$attrs"
724
+ :data-ui-combobox-state="hostState || undefined"
725
+ ref="root"
726
+ >
727
+ <label :for="`${uid}-input`" :class="{ 'sr-only': labelVisibility === 'sr-only' }">{{ label }}
728
+ <template v-if="required">
729
+ *</template></label>
730
+ <div class="field" ref="field">
731
+ <slot name="start" />
732
+ <template v-if="multiple"><button
733
+ v-for="(item, index) in items"
734
+ :key="item.id"
735
+ class="item"
736
+ type="button"
737
+ tabindex="-1"
738
+ :data-index="index"
739
+ :disabled="disabled || readonly || item.disabled"
740
+ :aria-label="`${item.label}, press Delete or Backspace to remove`"
741
+ >
742
+ <slot :name="`item-${item.id}`"><UiBadge>{{ item.label }}</UiBadge></slot>
743
+ </button></template>
744
+ <input
745
+ role="combobox"
746
+ aria-autocomplete="list"
747
+ autocomplete="off"
748
+ :id="`${uid}-input`"
749
+ :aria-controls="`${uid}-listbox`"
750
+ :aria-expanded="expanded"
751
+ :aria-invalid="validationStatus === 'error'"
752
+ :aria-busy="validationStatus === 'pending'"
753
+ :value.prop="display"
754
+ :placeholder="placeholder"
755
+ :name="name"
756
+ :disabled="disabled"
757
+ :readonly="readonly"
758
+ :required="required"
759
+ ref="input"
760
+ >
761
+ <button v-if="clearable" type="button" data-combobox-action="clear" aria-label="Clear">
762
+ <svg
763
+ class="affordance-icon"
764
+ aria-hidden="true"
765
+ viewBox="0 0 24 24"
766
+ fill="none"
767
+ stroke="currentColor"
768
+ stroke-width="2"
769
+ stroke-linecap="round"
770
+ >
771
+ <path d="M7 7l10 10M17 7 7 17"></path>
772
+ </svg>
773
+ </button>
774
+ <button v-if="help" type="button" aria-label="Help" :id="`${uid}-help`" :disabled="disabled">
775
+ <span aria-hidden="true">?</span>
776
+ </button>
777
+ <button
778
+ v-if="disclosure"
779
+ type="button"
780
+ data-combobox-action="disclosure"
781
+ tabindex="-1"
782
+ aria-label="Show suggestions"
783
+ :aria-controls="`${uid}-listbox`"
784
+ >
785
+ <svg
786
+ class="affordance-icon"
787
+ aria-hidden="true"
788
+ viewBox="0 0 24 24"
789
+ fill="none"
790
+ stroke="currentColor"
791
+ stroke-width="2.25"
792
+ stroke-linecap="round"
793
+ stroke-linejoin="round"
794
+ >
795
+ <path d="m6 9 6 6 6-6"></path>
796
+ </svg>
797
+ </button>
798
+ </div>
799
+ <UiTooltip v-if="help" :id="`${uid}-help-text`" :for="`${uid}-help`">{{ help }}</UiTooltip>
800
+ <div class="popup" :hidden="!expanded" ref="popup">
801
+ <div
802
+ role="listbox"
803
+ :id="`${uid}-listbox`"
804
+ :aria-label="`${label} suggestions`"
805
+ :aria-busy="loading"
806
+ ref="listbox"
807
+ >
808
+ <div
809
+ v-for="group in groups"
810
+ :key="group.name"
811
+ :role="group.role"
812
+ :aria-label="group.label ?? undefined"
813
+ >
814
+ <div v-if="group.name" class="group">{{ group.name }}</div>
815
+ <div
816
+ v-for="row in group.rows"
817
+ :key="row.id"
818
+ class="option"
819
+ role="option"
820
+ :id="`${uid}-option-${row.index}`"
821
+ :aria-selected="row.value === selected"
822
+ :aria-disabled="row.disabled"
823
+ :data-index="row.index"
824
+ :class="{ active: row.index === active }"
825
+ >
826
+ <slot :name="`option-${row.id}`"><span class="primary">{{ row.label }}</span></slot>
827
+ </div>
828
+ </div>
829
+ <div
830
+ v-if="creatable"
831
+ class="option"
832
+ role="option"
833
+ aria-selected="false"
834
+ :id="`${uid}-option-${createIndex}`"
835
+ :data-index="createIndex"
836
+ :class="{ active: createIndex === active }"
837
+ >
838
+ {{ `Create “${raw}”` }}
839
+ </div>
840
+ <div v-if="message" class="message">{{ message }}</div>
841
+ </div>
842
+ <slot name="footer" />
843
+ </div>
844
+ <div class="message" :id="`${uid}-validation`" :hidden="!validation.issues.length">
845
+ <div v-for="(issue, index) in validation.issues" :key="index">{{ issue.message }}</div>
846
+ </div>
847
+ <div class="sr-only" role="status" aria-live="polite" aria-atomic="true">{{ statusText }}</div>
848
+ <div class="authored-options" hidden="" aria-hidden="true" ref="options"><slot /></div>
849
+ </div>
263
850
  </template>
264
851
 
265
852
  <style scoped>
266
853
  [data-component~="ui-combobox"] {
267
- display: grid;
268
- gap: var(--ui-space-1);
269
- min-inline-size: 0;
270
- color: var(--ui-text-primary);
271
- font: inherit;
272
- }
273
- label {
274
- color: var(--ui-field-label-color, var(--ui-text-primary));
275
- font-size: var(--ui-field-label-size, 0.875rem);
276
- font-weight: var(--ui-field-label-weight, 500);
277
- }
278
- .field {
279
- display: flex;
280
- min-inline-size: 0;
281
- border: 1px solid var(--ui-control-border, var(--ui-border-default));
282
- border-radius: var(--ui-radius-2);
283
- background: var(--ui-control-surface, var(--ui-surface-default));
284
- box-shadow: var(--ui-control-inset);
285
- transition: border-color var(--ui-motion-fast) var(--ui-motion-ease), box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
286
- }
287
- .field:focus-within {
288
- border-color: var(--ui-control-focus, var(--ui-accent-solid));
289
- box-shadow:
290
- var(--ui-control-inset),
291
- var(--ui-control-focus-halo-shadow);
292
- }
293
- input::selection {
294
- background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
295
- color: inherit;
296
- }
297
- input {
298
- appearance: none;
299
- width: 100%;
300
- min-inline-size: 0;
301
- min-block-size: calc(var(--ui-control-size-md, 2.5rem) - 2px);
302
- box-sizing: border-box;
303
- border: 0;
304
- border-radius: inherit;
305
- background: transparent;
306
- color: inherit;
307
- font: inherit;
308
- line-height: var(--ui-line-height-md);
309
- padding: var(--ui-space-2) var(--ui-space-3);
310
- margin: 0;
311
- outline: none;
312
- }
313
- [data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input {
314
- min-block-size: calc(var(--ui-field-compact-size, var(--ui-control-size-sm, 2rem)) - 2px);
315
- padding: var(--ui-space-1) var(--ui-space-2);
316
- }
317
- button {
318
- appearance: none;
319
- display: inline-grid;
320
- place-items: center;
321
- align-self: stretch;
322
- border: 0;
323
- border-radius: var(--ui-radius-2);
324
- background: transparent;
325
- color: var(--ui-field-affordance-color, var(--ui-text-secondary));
326
- font: inherit;
327
- font-weight: var(--ui-field-affordance-weight, 400);
328
- min-inline-size: 2rem;
329
- padding: 0 var(--ui-space-1);
330
- cursor: pointer;
331
- }
332
- .affordance-icon {
333
- display: block;
334
- inline-size: var(--ui-icon-size-sm, 1rem);
335
- block-size: var(--ui-icon-size-sm, 1rem);
336
- }
337
- button:hover:enabled {
338
- background: var(--ui-surface-muted);
339
- color: var(--ui-text-primary);
340
- }
341
- button:focus-visible {
342
- outline: none;
343
- background: var(--ui-surface-muted);
344
- box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);
345
- }
346
- input:disabled, button:disabled {
347
- color: var(--ui-text-muted);
348
- cursor: not-allowed;
349
- }
350
- .field:has(input:disabled) {
351
- background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
352
- }
353
- [data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field {
354
- border-color: var(--ui-danger-solid, var(--ui-accent-active));
355
- }
356
- .popup {
357
- box-sizing: border-box;
358
- min-inline-size: 12rem;
359
- max-inline-size: calc(100vw - 1rem);
360
- max-block-size: var(--ui-combobox-max-block-size, 18rem);
361
- overflow: auto;
362
- margin: 0;
363
- padding: var(--ui-space-1);
364
- border: 1px solid var(--ui-border-default);
365
- border-radius: var(--ui-radius-2);
366
- background: var(--ui-surface-elevated);
367
- color: var(--ui-text-primary);
368
- box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));
369
- }
370
- [hidden] {
371
- display: none;
372
- }
373
- .option {
374
- padding: var(--ui-space-2) var(--ui-space-3);
375
- border-radius: var(--ui-radius-1);
376
- cursor: pointer;
377
- overflow-wrap: anywhere;
378
- }
379
- .option:hover, .option.active {
380
- background: var(--ui-surface-muted);
381
- outline: 1px solid var(--ui-focus-ring, currentColor);
382
- outline-offset: -1px;
383
- }
384
- .option[aria-disabled="true"] {
385
- color: var(--ui-text-muted);
386
- cursor: not-allowed;
387
- }
388
- .primary {
389
- display: block;
390
- color: var(--ui-option-primary-color, var(--ui-text-primary));
391
- font-weight: var(--ui-option-primary-weight, 500);
392
- }
393
- .message, .group {
394
- color: var(--ui-field-message-color, var(--ui-text-secondary));
395
- font-weight: var(--ui-field-message-weight, 400);
396
- font-size: var(--ui-font-size-sm);
397
- line-height: var(--ui-line-height-md);
398
- overflow-wrap: anywhere;
399
- }
400
- .group, .popup .message {
401
- padding: var(--ui-space-2) var(--ui-space-3);
402
- }
403
- .sr-only {
404
- position: absolute;
405
- inline-size: 1px;
406
- block-size: 1px;
407
- overflow: hidden;
408
- clip-path: inset(50%);
409
- white-space: nowrap;
410
- }
411
- @media (pointer: coarse) {
412
- button {
413
- min-inline-size: 2.75rem;
414
- min-block-size: 2.75rem;
415
- }
416
- }
417
- @media (forced-colors: active) {
418
- .field, .popup {
419
- border-color: CanvasText;
420
- }
421
- .option.active {
422
- outline-color: Highlight;
423
- }
424
- }
854
+ display: grid;
855
+ gap: var(--ui-space-1);
856
+ min-inline-size: 0;
857
+ color: var(--ui-text-primary);
858
+ font: inherit;
859
+ }
860
+ label {
861
+ color: var(--ui-field-label-color, var(--ui-text-primary));
862
+ font-size: var(--ui-field-label-size, 0.875rem);
863
+ font-weight: var(--ui-field-label-weight, 500);
864
+ }
865
+ .field {
866
+ display: flex;
867
+ min-inline-size: 0;
868
+ border: 1px solid var(--ui-control-border, var(--ui-border-default));
869
+ border-radius: var(--ui-radius-2);
870
+ background: var(--ui-control-surface, var(--ui-surface-default));
871
+ box-shadow: var(--ui-control-inset);
872
+ transition:
873
+ border-color var(--ui-motion-fast) var(--ui-motion-ease),
874
+ box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
875
+ }
876
+ .field:focus-within {
877
+ border-color: var(--ui-control-focus, var(--ui-accent-solid));
878
+ box-shadow:
879
+ var(--ui-control-inset),
880
+ var(--ui-control-focus-halo-shadow);
881
+ }
882
+ input::selection {
883
+ background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
884
+ color: inherit;
885
+ }
886
+ input {
887
+ appearance: none;
888
+ width: 100%;
889
+ min-inline-size: 0;
890
+ min-block-size: calc(var(--ui-control-size-md, 2.5rem) - 2px);
891
+ box-sizing: border-box;
892
+ border: 0;
893
+ border-radius: inherit;
894
+ background: transparent;
895
+ color: inherit;
896
+ font: inherit;
897
+ line-height: var(--ui-line-height-md);
898
+ padding: var(--ui-space-2) var(--ui-space-3);
899
+ margin: 0;
900
+ outline: none;
901
+ }
902
+ [data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input {
903
+ min-block-size: calc(var(--ui-field-compact-size, var(--ui-control-size-sm, 2rem)) - 2px);
904
+ padding: var(--ui-space-1) var(--ui-space-2);
905
+ }
906
+ button {
907
+ appearance: none;
908
+ display: inline-grid;
909
+ place-items: center;
910
+ align-self: stretch;
911
+ border: 0;
912
+ border-radius: var(--ui-radius-2);
913
+ background: transparent;
914
+ color: var(--ui-field-affordance-color, var(--ui-text-secondary));
915
+ font: inherit;
916
+ font-weight: var(--ui-field-affordance-weight, 400);
917
+ min-inline-size: 2rem;
918
+ padding: 0 var(--ui-space-1);
919
+ cursor: pointer;
920
+ }
921
+ .affordance-icon {
922
+ display: block;
923
+ inline-size: var(--ui-icon-size-sm, 1rem);
924
+ block-size: var(--ui-icon-size-sm, 1rem);
925
+ }
926
+ button:hover:enabled {
927
+ background: var(--ui-surface-muted);
928
+ color: var(--ui-text-primary);
929
+ }
930
+ button:focus-visible {
931
+ outline: none;
932
+ background: var(--ui-surface-muted);
933
+ box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);
934
+ }
935
+ input:disabled, button:disabled {
936
+ color: var(--ui-text-muted);
937
+ cursor: not-allowed;
938
+ }
939
+ .field:has(input:disabled) {
940
+ background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
941
+ }
942
+ [data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field {
943
+ border-color: var(--ui-danger-solid, var(--ui-accent-active));
944
+ }
945
+ .popup {
946
+ box-sizing: border-box;
947
+ min-inline-size: 12rem;
948
+ max-inline-size: calc(100vw - 1rem);
949
+ max-block-size: var(--ui-combobox-max-block-size, 18rem);
950
+ overflow: auto;
951
+ margin: 0;
952
+ padding: var(--ui-space-1);
953
+ border: 1px solid var(--ui-border-default);
954
+ border-radius: var(--ui-radius-2);
955
+ background: var(--ui-surface-elevated);
956
+ color: var(--ui-text-primary);
957
+ box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));
958
+ }
959
+ [hidden] {
960
+ display: none;
961
+ }
962
+ .option {
963
+ padding: var(--ui-space-2) var(--ui-space-3);
964
+ border-radius: var(--ui-radius-1);
965
+ cursor: pointer;
966
+ overflow-wrap: anywhere;
967
+ }
968
+ .option:hover, .option.active {
969
+ background: var(--ui-surface-muted);
970
+ outline: 1px solid var(--ui-focus-ring, currentColor);
971
+ outline-offset: -1px;
972
+ }
973
+ .option[aria-disabled="true"] {
974
+ color: var(--ui-text-muted);
975
+ cursor: not-allowed;
976
+ }
977
+ .primary {
978
+ display: block;
979
+ color: var(--ui-option-primary-color, var(--ui-text-primary));
980
+ font-weight: var(--ui-option-primary-weight, 500);
981
+ }
982
+ .message, .group {
983
+ color: var(--ui-field-message-color, var(--ui-text-secondary));
984
+ font-weight: var(--ui-field-message-weight, 400);
985
+ font-size: var(--ui-font-size-sm);
986
+ line-height: var(--ui-line-height-md);
987
+ overflow-wrap: anywhere;
988
+ }
989
+ .group, .popup .message {
990
+ padding: var(--ui-space-2) var(--ui-space-3);
991
+ }
992
+ .sr-only {
993
+ position: absolute;
994
+ inline-size: 1px;
995
+ block-size: 1px;
996
+ overflow: hidden;
997
+ clip-path: inset(50%);
998
+ white-space: nowrap;
999
+ }
1000
+ @media (pointer: coarse) {
1001
+ button {
1002
+ min-inline-size: 2.75rem;
1003
+ min-block-size: 2.75rem;
1004
+ }
1005
+ }
1006
+ @media (forced-colors: active) {
1007
+ .field, .popup {
1008
+ border-color: CanvasText;
1009
+ }
1010
+ .option.active {
1011
+ outline-color: Highlight;
1012
+ }
1013
+ }
425
1014
 
426
- /* Multiple mode: chips wrap before the cursor on one flexible field line. */
427
- [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .field {
428
- flex-wrap: wrap;
429
- align-items: center;
430
- gap: var(--ui-space-1);
431
- min-block-size: var(--ui-multi-combobox-min-block-size, 2.5rem);
432
- padding: var(--ui-space-1);
433
- }
434
- [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] input {
435
- flex: 1 0 var(--ui-multi-combobox-input-min-inline-size, 5rem);
436
- width: auto;
437
- min-block-size: 1.75rem;
438
- padding: var(--ui-space-0-5) var(--ui-space-1);
439
- }
440
- .item {
441
- appearance: none;
442
- display: inline-flex;
443
- min-inline-size: 0;
444
- max-inline-size: min(100%, var(--ui-multi-combobox-item-max-inline-size, 12rem));
445
- overflow: hidden;
446
- padding: 0;
447
- border: 0;
448
- border-radius: var(--ui-radius-1);
449
- background: transparent;
450
- color: inherit;
451
- font: inherit;
452
- cursor: default;
453
- }
454
- .item:focus-visible {
455
- outline: 2px solid var(--ui-focus-ring, currentColor);
456
- outline-offset: 1px;
457
- }
458
- .item:disabled {
459
- opacity: 0.6;
460
- }
1015
+ /* Multiple mode: chips wrap before the cursor on one flexible field line. */
1016
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .field {
1017
+ flex-wrap: wrap;
1018
+ align-items: center;
1019
+ gap: var(--ui-space-1);
1020
+ min-block-size: var(--ui-multi-combobox-min-block-size, 2.5rem);
1021
+ padding: var(--ui-space-1);
1022
+ }
1023
+ [data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] input {
1024
+ flex: 1 0 var(--ui-multi-combobox-input-min-inline-size, 5rem);
1025
+ width: auto;
1026
+ min-block-size: 1.75rem;
1027
+ padding: var(--ui-space-0-5) var(--ui-space-1);
1028
+ }
1029
+ .item {
1030
+ appearance: none;
1031
+ display: inline-flex;
1032
+ min-inline-size: 0;
1033
+ max-inline-size: min(100%, var(--ui-multi-combobox-item-max-inline-size, 12rem));
1034
+ overflow: hidden;
1035
+ padding: 0;
1036
+ border: 0;
1037
+ border-radius: var(--ui-radius-1);
1038
+ background: transparent;
1039
+ color: inherit;
1040
+ font: inherit;
1041
+ cursor: default;
1042
+ }
1043
+ .item:focus-visible {
1044
+ outline: 2px solid var(--ui-focus-ring, currentColor);
1045
+ outline-offset: 1px;
1046
+ }
1047
+ .item:disabled {
1048
+ opacity: 0.6;
1049
+ }
461
1050
 
462
- /* A component that sets its display still honours the hidden attribute on its root. */
463
- [data-component~="ui-combobox"][hidden] {
464
- display: none;
465
- }
1051
+ /* A component that sets its display still honours the hidden attribute on its root. */
1052
+ [data-component~="ui-combobox"][hidden] {
1053
+ display: none;
1054
+ }
466
1055
  </style>