@threadlabs/looma 0.14.8 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/components/shared/icons.js +5 -0
  2. package/components/shared/menu-navigation.js +49 -0
  3. package/components/shared/overlay.js +33 -60
  4. package/components/ui-avatar/ui-avatar.html +19 -2
  5. package/components/ui-avatar/ui-avatar.js +7 -1
  6. package/components/ui-avatar-group/ui-avatar-group.html +8 -3
  7. package/components/ui-avatar-group/ui-avatar-group.js +6 -2
  8. package/components/ui-badge/ui-badge.html +70 -4
  9. package/components/ui-button/ui-button.html +21 -5
  10. package/components/ui-button/ui-button.js +10 -0
  11. package/components/ui-callout/ui-callout.html +13 -5
  12. package/components/ui-checkbox/ui-checkbox.html +11 -0
  13. package/components/ui-combobox/ui-combobox.html +46 -10
  14. package/components/ui-combobox/ui-combobox.js +5 -5
  15. package/components/ui-context-menu/ui-context-menu.html +33 -5
  16. package/components/ui-context-menu/ui-context-menu.js +26 -17
  17. package/components/ui-dialog/ui-dialog.html +51 -8
  18. package/components/ui-dialog/ui-dialog.js +28 -7
  19. package/components/ui-disclosure/ui-disclosure.html +14 -5
  20. package/components/ui-disclosure/ui-disclosure.js +51 -4
  21. package/components/ui-editable/ui-editable.html +17 -3
  22. package/components/ui-editable/ui-editable.js +7 -0
  23. package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +48 -14
  24. package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.js +40 -6
  25. package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +22 -9
  26. package/components/ui-editor-mention-menu/ui-editor-mention-menu.js +33 -11
  27. package/components/ui-editor-mention-menu-item/ui-editor-mention-menu-item.html +67 -0
  28. package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +33 -30
  29. package/components/ui-editor-slash-menu/ui-editor-slash-menu.js +42 -8
  30. package/components/ui-editor-slash-menu-group/ui-editor-slash-menu-group.html +31 -0
  31. package/components/ui-editor-slash-menu-item/ui-editor-slash-menu-item.html +75 -0
  32. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +16 -5
  33. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.js +10 -2
  34. package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +5 -5
  35. package/components/ui-editor-table-overlay/ui-editor-table-overlay.js +5 -2
  36. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +14 -4
  37. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.js +2 -2
  38. package/components/ui-editor-toolbar/ui-editor-toolbar.html +1 -1
  39. package/components/ui-editor-toolbar/ui-editor-toolbar.js +46 -0
  40. package/components/ui-floating-action-button/ui-floating-action-button.html +1 -1
  41. package/components/ui-form-field/ui-form-field.html +16 -3
  42. package/components/ui-form-field/ui-form-field.js +1 -1
  43. package/components/ui-grid/ui-grid.html +17 -2
  44. package/components/ui-icon/ui-icon.html +5 -0
  45. package/components/ui-icon-button/ui-icon-button.html +25 -6
  46. package/components/ui-icon-button/ui-icon-button.js +11 -1
  47. package/components/ui-input/ui-input.html +3 -3
  48. package/components/ui-input-group/ui-input-group.html +18 -4
  49. package/components/ui-listbox/ui-listbox.html +81 -0
  50. package/components/ui-listbox/ui-listbox.js +27 -0
  51. package/components/ui-menu/ui-menu.html +33 -5
  52. package/components/ui-menu/ui-menu.js +18 -12
  53. package/components/ui-menu-group/ui-menu-group.html +27 -0
  54. package/components/ui-menu-item/ui-menu-item.html +80 -8
  55. package/components/ui-menu-item/ui-menu-item.js +47 -0
  56. package/components/ui-popover/ui-popover.html +33 -5
  57. package/components/ui-popover/ui-popover.js +9 -1
  58. package/components/ui-radio-group/ui-radio-group.html +13 -1
  59. package/components/ui-search-shell/ui-search-shell.html +6 -6
  60. package/components/ui-search-shell/ui-search-shell.js +21 -5
  61. package/components/ui-select/ui-select.html +14 -4
  62. package/components/ui-switch/ui-switch.html +2 -2
  63. package/components/ui-switcher/ui-switcher.html +8 -1
  64. package/components/ui-switcher/ui-switcher.js +15 -0
  65. package/components/ui-tabs/ui-tabs.html +17 -12
  66. package/components/ui-tabs/ui-tabs.js +43 -7
  67. package/components/ui-textarea/ui-textarea.html +28 -5
  68. package/components/ui-toast/ui-toast.html +88 -0
  69. package/components/ui-toast/ui-toast.js +68 -0
  70. package/components/ui-toast-region/ui-toast-region.html +102 -19
  71. package/components/ui-toast-region/ui-toast-region.js +10 -18
  72. package/components/ui-tooltip/ui-tooltip.html +51 -7
  73. package/components/ui-tooltip/ui-tooltip.js +29 -3
  74. package/components/ui-tree/ui-tree.html +12 -0
  75. package/components/ui-tree/ui-tree.js +191 -12
  76. package/components/ui-tree-item/ui-tree-item.html +87 -8
  77. package/components/ui-tree-item/ui-tree-item.js +3 -1
  78. package/dist/index.js +38 -32
  79. package/editor/chunks/extensions.js +82 -2
  80. package/editor/extensions/table-commands.d.ts +8 -0
  81. package/editor/icons.d.ts +5 -0
  82. package/editor/index.js +7 -2
  83. package/editor/insert-table-grid.d.ts +1 -1
  84. package/editor/mention-menu.d.ts +2 -0
  85. package/editor/slash-menu.d.ts +3 -0
  86. package/editor/table-context-menu.d.ts +1 -1
  87. package/editor/table-overlay.d.ts +2 -2
  88. package/package.json +1 -1
  89. package/styles/ui-avatar-group.css +1 -2
  90. package/styles/ui-avatar.css +11 -1
  91. package/styles/ui-badge.css +73 -1
  92. package/styles/ui-button.css +9 -1
  93. package/styles/ui-callout.css +1 -1
  94. package/styles/ui-checkbox.css +9 -0
  95. package/styles/ui-combobox.css +38 -7
  96. package/styles/ui-context-menu.css +32 -4
  97. package/styles/ui-dialog.css +42 -5
  98. package/styles/ui-editor-insert-table-grid.css +48 -11
  99. package/styles/ui-editor-mention-menu-item.css +57 -0
  100. package/styles/ui-editor-mention-menu.css +11 -1
  101. package/styles/ui-editor-slash-menu-group.css +21 -0
  102. package/styles/ui-editor-slash-menu-item.css +62 -0
  103. package/styles/ui-editor-slash-menu.css +10 -21
  104. package/styles/ui-editor-table-context-menu.css +1 -1
  105. package/styles/ui-floating-action-button.css +1 -1
  106. package/styles/ui-form-field.css +14 -1
  107. package/styles/ui-grid.css +14 -1
  108. package/styles/ui-icon-button.css +17 -5
  109. package/styles/ui-input-group.css +18 -4
  110. package/styles/ui-input.css +3 -3
  111. package/styles/ui-listbox.css +69 -0
  112. package/styles/ui-menu-group.css +19 -0
  113. package/styles/ui-menu-item.css +48 -9
  114. package/styles/ui-menu.css +32 -4
  115. package/styles/ui-popover.css +28 -4
  116. package/styles/ui-radio-group.css +9 -0
  117. package/styles/ui-search-shell.css +5 -5
  118. package/styles/ui-select.css +14 -4
  119. package/styles/ui-switch.css +2 -2
  120. package/styles/ui-switcher.css +4 -0
  121. package/styles/ui-textarea.css +27 -4
  122. package/styles/ui-toast-region.css +88 -4
  123. package/styles/ui-toast.css +74 -0
  124. package/styles/ui-tooltip.css +46 -6
  125. package/styles/ui-tree-item.css +72 -4
  126. package/styles/ui-tree.css +8 -0
  127. package/tokens.css +3 -0
  128. package/vanilla/UiAvatar.d.ts +2 -0
  129. package/vanilla/UiAvatar.js +8 -1
  130. package/vanilla/UiAvatarGroup.d.ts +2 -0
  131. package/vanilla/UiAvatarGroup.js +1 -1
  132. package/vanilla/UiBadge.d.ts +1 -1
  133. package/vanilla/UiBadge.js +1 -1
  134. package/vanilla/UiButton.d.ts +1 -0
  135. package/vanilla/UiButton.js +22 -6
  136. package/vanilla/UiCallout.d.ts +1 -1
  137. package/vanilla/UiCallout.js +1 -1
  138. package/vanilla/UiCheckbox.d.ts +1 -0
  139. package/vanilla/UiCheckbox.js +12 -9
  140. package/vanilla/UiCombobox.d.ts +3 -0
  141. package/vanilla/UiCombobox.js +30 -15
  142. package/vanilla/UiContextMenu.d.ts +1 -1
  143. package/vanilla/UiContextMenu.js +1 -1
  144. package/vanilla/UiDialog.d.ts +5 -2
  145. package/vanilla/UiDialog.js +1 -1
  146. package/vanilla/UiDisclosure.d.ts +2 -0
  147. package/vanilla/UiDisclosure.js +32 -18
  148. package/vanilla/UiEditable.d.ts +5 -0
  149. package/vanilla/UiEditable.js +7 -3
  150. package/vanilla/UiEditorInsertTableGrid.js +1 -6
  151. package/vanilla/UiEditorMentionMenu.d.ts +4 -2
  152. package/vanilla/UiEditorMentionMenu.js +49 -31
  153. package/vanilla/UiEditorMentionMenuItem.d.ts +16 -0
  154. package/vanilla/UiEditorMentionMenuItem.js +56 -0
  155. package/vanilla/UiEditorSlashMenu.d.ts +4 -3
  156. package/vanilla/UiEditorSlashMenu.js +59 -46
  157. package/vanilla/UiEditorSlashMenuGroup.d.ts +14 -0
  158. package/vanilla/UiEditorSlashMenuGroup.js +48 -0
  159. package/vanilla/UiEditorSlashMenuItem.d.ts +18 -0
  160. package/vanilla/UiEditorSlashMenuItem.js +57 -0
  161. package/vanilla/UiEditorTableContextMenu.d.ts +5 -2
  162. package/vanilla/UiEditorTableContextMenu.js +1 -2
  163. package/vanilla/UiEditorTableOverlay.d.ts +1 -1
  164. package/vanilla/UiEditorTableOverlay.js +5 -5
  165. package/vanilla/UiEditorTableToolbar.d.ts +4 -2
  166. package/vanilla/UiEditorTableToolbar.js +1 -2
  167. package/vanilla/UiEditorToolbar.js +2 -0
  168. package/vanilla/UiGrid.d.ts +1 -0
  169. package/vanilla/UiGrid.js +8 -7
  170. package/vanilla/UiIcon.js +1 -1
  171. package/vanilla/UiIconButton.d.ts +1 -0
  172. package/vanilla/UiIconButton.js +11 -2
  173. package/vanilla/UiListbox.d.ts +20 -0
  174. package/vanilla/UiListbox.js +45 -0
  175. package/vanilla/UiMenu.d.ts +1 -1
  176. package/vanilla/UiMenu.js +1 -1
  177. package/vanilla/UiMenuGroup.d.ts +14 -0
  178. package/vanilla/UiMenuGroup.js +35 -0
  179. package/vanilla/UiMenuItem.d.ts +5 -1
  180. package/vanilla/UiMenuItem.js +91 -30
  181. package/vanilla/UiPopover.d.ts +1 -1
  182. package/vanilla/UiPopover.js +1 -1
  183. package/vanilla/UiRadioGroup.d.ts +1 -0
  184. package/vanilla/UiRadioGroup.js +6 -3
  185. package/vanilla/UiSwitcher.d.ts +1 -0
  186. package/vanilla/UiSwitcher.js +7 -9
  187. package/vanilla/UiTabs.d.ts +1 -0
  188. package/vanilla/UiTabs.js +9 -1
  189. package/vanilla/UiTextarea.d.ts +1 -0
  190. package/vanilla/UiTextarea.js +4 -1
  191. package/vanilla/UiToast.d.ts +16 -0
  192. package/vanilla/UiToast.js +53 -0
  193. package/vanilla/UiToastRegion.d.ts +1 -4
  194. package/vanilla/UiToastRegion.js +3 -11
  195. package/vanilla/UiTooltip.d.ts +1 -1
  196. package/vanilla/UiTooltip.js +1 -1
  197. package/vanilla/UiTree.d.ts +2 -0
  198. package/vanilla/UiTree.js +1 -1
  199. package/vanilla/UiTreeItem.d.ts +1 -0
  200. package/vanilla/UiTreeItem.js +45 -31
  201. package/vanilla/index.js +6 -0
  202. package/vue/UiAvatar.d.ts +4 -0
  203. package/vue/UiAvatar.vue +23 -3
  204. package/vue/UiAvatarGroup.d.ts +3 -0
  205. package/vue/UiAvatarGroup.vue +7 -4
  206. package/vue/UiBadge.d.ts +2 -2
  207. package/vue/UiBadge.vue +74 -2
  208. package/vue/UiButton.d.ts +5 -3
  209. package/vue/UiButton.vue +41 -7
  210. package/vue/UiCallout.d.ts +2 -2
  211. package/vue/UiCallout.vue +3 -2
  212. package/vue/UiCheckbox.d.ts +2 -0
  213. package/vue/UiCheckbox.vue +16 -0
  214. package/vue/UiCombobox.d.ts +11 -3
  215. package/vue/UiCombobox.vue +60 -11
  216. package/vue/UiContextMenu.d.ts +2 -0
  217. package/vue/UiContextMenu.vue +47 -6
  218. package/vue/UiDialog.d.ts +18 -4
  219. package/vue/UiDialog.vue +86 -11
  220. package/vue/UiDisclosure.d.ts +8 -2
  221. package/vue/UiDisclosure.vue +38 -14
  222. package/vue/UiEditable.d.ts +10 -0
  223. package/vue/UiEditable.vue +14 -2
  224. package/vue/UiEditorInsertTableGrid.vue +52 -15
  225. package/vue/UiEditorMentionMenu.d.ts +24 -2
  226. package/vue/UiEditorMentionMenu.vue +27 -11
  227. package/vue/UiEditorMentionMenuItem.d.ts +24 -0
  228. package/vue/UiEditorMentionMenuItem.js +2 -0
  229. package/vue/UiEditorMentionMenuItem.vue +88 -0
  230. package/vue/UiEditorSlashMenu.d.ts +24 -1
  231. package/vue/UiEditorSlashMenu.vue +33 -33
  232. package/vue/UiEditorSlashMenuGroup.d.ts +18 -0
  233. package/vue/UiEditorSlashMenuGroup.js +2 -0
  234. package/vue/UiEditorSlashMenuGroup.vue +43 -0
  235. package/vue/UiEditorSlashMenuItem.d.ts +26 -0
  236. package/vue/UiEditorSlashMenuItem.js +2 -0
  237. package/vue/UiEditorSlashMenuItem.vue +101 -0
  238. package/vue/UiEditorTableContextMenu.d.ts +9 -3
  239. package/vue/UiEditorTableContextMenu.vue +53 -3
  240. package/vue/UiEditorTableOverlay.d.ts +2 -2
  241. package/vue/UiEditorTableOverlay.vue +8 -6
  242. package/vue/UiEditorTableToolbar.d.ts +7 -3
  243. package/vue/UiEditorTableToolbar.vue +50 -2
  244. package/vue/UiEditorToolbar.vue +14 -1
  245. package/vue/UiFloatingActionButton.vue +1 -1
  246. package/vue/UiFormField.vue +28 -3
  247. package/vue/UiGrid.d.ts +1 -0
  248. package/vue/UiGrid.vue +26 -2
  249. package/vue/UiIcon.vue +16 -0
  250. package/vue/UiIconButton.d.ts +5 -3
  251. package/vue/UiIconButton.vue +40 -6
  252. package/vue/UiInput.vue +10 -3
  253. package/vue/UiInputGroup.vue +32 -11
  254. package/vue/UiListbox.d.ts +33 -0
  255. package/vue/UiListbox.js +2 -0
  256. package/vue/UiListbox.vue +131 -0
  257. package/vue/UiMenu.d.ts +2 -0
  258. package/vue/UiMenu.vue +43 -6
  259. package/vue/UiMenuGroup.d.ts +18 -0
  260. package/vue/UiMenuGroup.js +2 -0
  261. package/vue/UiMenuGroup.vue +39 -0
  262. package/vue/UiMenuItem.d.ts +34 -2
  263. package/vue/UiMenuItem.vue +145 -9
  264. package/vue/UiPopover.d.ts +2 -2
  265. package/vue/UiPopover.vue +44 -5
  266. package/vue/UiRadioGroup.d.ts +2 -0
  267. package/vue/UiRadioGroup.vue +17 -0
  268. package/vue/UiSearchShell.vue +12 -5
  269. package/vue/UiSelect.vue +18 -4
  270. package/vue/UiSwitch.vue +2 -2
  271. package/vue/UiSwitcher.d.ts +1 -0
  272. package/vue/UiSwitcher.vue +22 -1
  273. package/vue/UiTabs.d.ts +6 -2
  274. package/vue/UiTabs.vue +14 -12
  275. package/vue/UiTextarea.d.ts +2 -0
  276. package/vue/UiTextarea.vue +32 -4
  277. package/vue/UiToast.d.ts +34 -0
  278. package/vue/UiToast.js +2 -0
  279. package/vue/UiToast.vue +173 -0
  280. package/vue/UiToastRegion.d.ts +2 -18
  281. package/vue/UiToastRegion.vue +123 -48
  282. package/vue/UiTooltip.d.ts +2 -2
  283. package/vue/UiTooltip.vue +67 -12
  284. package/vue/UiTree.d.ts +10 -0
  285. package/vue/UiTree.vue +27 -0
  286. package/vue/UiTreeItem.d.ts +2 -0
  287. package/vue/UiTreeItem.vue +96 -4
  288. package/vue/chunks/UiAvatar.js +19 -5
  289. package/vue/chunks/UiAvatarGroup.js +10 -4
  290. package/vue/chunks/UiBadge.js +1 -1
  291. package/vue/chunks/UiButton.js +58 -11
  292. package/vue/chunks/UiCallout.js +2 -2
  293. package/vue/chunks/UiCheckbox.js +12 -2
  294. package/vue/chunks/UiCombobox.js +29 -13
  295. package/vue/chunks/UiContextMenu.js +6 -2
  296. package/vue/chunks/UiDialog.js +25 -8
  297. package/vue/chunks/UiDisclosure.js +36 -12
  298. package/vue/chunks/UiEditable.js +22 -8
  299. package/vue/chunks/UiEditorInsertTableGrid.js +11 -14
  300. package/vue/chunks/UiEditorMentionMenu.js +30 -19
  301. package/vue/chunks/UiEditorMentionMenuItem.js +36 -0
  302. package/vue/chunks/UiEditorSlashMenu.js +33 -35
  303. package/vue/chunks/UiEditorSlashMenuGroup.js +26 -0
  304. package/vue/chunks/UiEditorSlashMenuItem.js +51 -0
  305. package/vue/chunks/UiEditorTableContextMenu.js +39 -5
  306. package/vue/chunks/UiEditorTableOverlay.js +6 -6
  307. package/vue/chunks/UiEditorTableToolbar.js +37 -4
  308. package/vue/chunks/UiEditorToolbar.js +18 -4
  309. package/vue/chunks/UiFloatingActionButton.js +1 -1
  310. package/vue/chunks/UiFormField.js +13 -9
  311. package/vue/chunks/UiGrid.js +6 -2
  312. package/vue/chunks/UiIcon.js +40 -2
  313. package/vue/chunks/UiIconButton.js +35 -4
  314. package/vue/chunks/UiInput.js +1 -1
  315. package/vue/chunks/UiInputGroup.js +1 -1
  316. package/vue/chunks/UiListbox.js +70 -0
  317. package/vue/chunks/UiMenu.js +6 -2
  318. package/vue/chunks/UiMenuGroup.js +25 -0
  319. package/vue/chunks/UiMenuItem.js +128 -7
  320. package/vue/chunks/UiPopover.js +1 -1
  321. package/vue/chunks/UiRadioGroup.js +8 -2
  322. package/vue/chunks/UiSearchShell.js +1 -1
  323. package/vue/chunks/UiSelect.js +1 -1
  324. package/vue/chunks/UiSwitch.js +1 -1
  325. package/vue/chunks/UiSwitcher.js +20 -3
  326. package/vue/chunks/UiTabs.js +4 -3
  327. package/vue/chunks/UiTextarea.js +7 -2
  328. package/vue/chunks/UiToast.js +81 -0
  329. package/vue/chunks/UiToastRegion.js +25 -49
  330. package/vue/chunks/UiTooltip.js +3 -7
  331. package/vue/chunks/UiTree.js +8 -4
  332. package/vue/chunks/UiTreeItem.js +28 -10
  333. package/vue/components.css +1840 -851
  334. package/vue/editor/index.js +263 -2
  335. package/vue/index.d.ts +6 -0
  336. package/vue/index.js +9 -3
@@ -10,11 +10,14 @@ const props = withDefaults(
10
10
  defineProps<{
11
11
  label?: string
12
12
  max?: number
13
+ overflowLabel?: string
13
14
  size?: 'sm' | 'md'
15
+ total?: number
14
16
  }>(),
15
17
  {
16
18
  label: 'People',
17
19
  max: 5,
20
+ overflowLabel: '{count} more',
18
21
  size: 'md',
19
22
  },
20
23
  )
@@ -22,6 +25,7 @@ const props = withDefaults(
22
25
  const root = ref<HTMLElement | null>(null)
23
26
  const overflowElement = useTemplateRef<HTMLElement>('overflow')
24
27
  const overflowCount = ref(0)
28
+ const overflowAnnouncement = ref('')
25
29
 
26
30
  /** The values the styles' :host-state() rules test. */
27
31
  const hostState = computed(() =>
@@ -37,7 +41,7 @@ useComponentHost(controllerModule.default, {
37
41
  dispatch,
38
42
  props,
39
43
  refs: { overflow: overflowElement },
40
- state: { overflowCount },
44
+ state: { overflowCount, overflowAnnouncement },
41
45
  })
42
46
  </script>
43
47
 
@@ -55,7 +59,7 @@ useComponentHost(controllerModule.default, {
55
59
  class="overflow"
56
60
  role="img"
57
61
  :hidden="!overflowCount"
58
- :aria-label="`${overflowCount} more`"
62
+ :aria-label="overflowAnnouncement"
59
63
  ref="overflow"
60
64
  >{{ `+${overflowCount}` }}</span>
61
65
  </div>
@@ -93,7 +97,6 @@ useComponentHost(controllerModule.default, {
93
97
  :slotted(*) {
94
98
  margin-inline-start: -0.5rem;
95
99
  flex-shrink: 0;
96
- border-radius: 999px;
97
100
  }
98
101
 
99
102
  :slotted(*:first-child) {
@@ -107,7 +110,7 @@ useComponentHost(controllerModule.default, {
107
110
  justify-content: center;
108
111
  inline-size: 2.5rem;
109
112
  block-size: 2.5rem;
110
- border-radius: 999px;
113
+ border-radius: var(--ui-radius-round);
111
114
  border: 1px solid var(--ui-border-strong);
112
115
  background: var(--ui-surface-elevated);
113
116
  color: var(--ui-text-primary);
package/vue/UiBadge.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  type __VLS_Props = {
2
2
  shape?: 'pill' | 'tag';
3
3
  tone?: 'neutral' | 'accent' | 'info' | 'success' | 'warning' | 'danger';
4
- variant?: 'solid' | 'subtle';
4
+ variant?: 'solid' | 'subtle' | 'outline';
5
5
  };
6
6
  declare var __VLS_1: {};
7
7
  type __VLS_Slots = {} & {
@@ -10,7 +10,7 @@ type __VLS_Slots = {} & {
10
10
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
11
11
  shape: "pill" | "tag";
12
12
  tone: "neutral" | "accent" | "info" | "success" | "warning" | "danger";
13
- variant: "solid" | "subtle";
13
+ variant: "solid" | "subtle" | "outline";
14
14
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
15
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
16
16
  declare const _default: typeof __VLS_export;
package/vue/UiBadge.vue CHANGED
@@ -8,7 +8,7 @@ const props = withDefaults(
8
8
  defineProps<{
9
9
  shape?: 'pill' | 'tag'
10
10
  tone?: 'neutral' | 'accent' | 'info' | 'success' | 'warning' | 'danger'
11
- variant?: 'solid' | 'subtle'
11
+ variant?: 'solid' | 'subtle' | 'outline'
12
12
  }>(),
13
13
  {
14
14
  shape: 'pill',
@@ -83,6 +83,7 @@ const hostState = computed(() =>
83
83
  --_badge-text: var(--ui-text-secondary);
84
84
  /* Every tone's edge is its fill, so it is unseen until forced colors draw it. */
85
85
  --_badge-border: var(--ui-surface-subtle);
86
+ --_badge-outline-surface: var(--ui-badge-surface, var(--_badge-surface));
86
87
 
87
88
  display: inline-flex;
88
89
  align-items: center;
@@ -92,7 +93,7 @@ const hostState = computed(() =>
92
93
  var(--ui-badge-padding-inline, var(--ui-space-2));
93
94
  border: 1px solid var(--ui-badge-border, var(--_badge-border));
94
95
  border-radius: var(--ui-radius-round);
95
- background: var(--ui-badge-surface, var(--_badge-surface));
96
+ background: var(--_badge-outline-surface);
96
97
  color: var(--ui-badge-text, var(--_badge-text));
97
98
  font-family: var(--ui-font-family-sans);
98
99
  font-size: var(--ui-badge-font-size, var(--ui-font-size-sm));
@@ -175,6 +176,37 @@ const hostState = computed(() =>
175
176
  --_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));
176
177
  }
177
178
 
179
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"] {
180
+ --_badge-surface: var(--ui-surface-default);
181
+ --_badge-border: var(--ui-border-strong);
182
+ --_badge-text: var(--ui-text-secondary);
183
+ }
184
+
185
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="tone=accent"] {
186
+ --_badge-border: var(--ui-accent-solid);
187
+ --_badge-text: var(--ui-accent-subtle-text, var(--ui-accent-solid));
188
+ }
189
+
190
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="tone=danger"] {
191
+ --_badge-border: var(--ui-danger-solid);
192
+ --_badge-text: var(--ui-danger-subtle-text, var(--ui-danger-solid));
193
+ }
194
+
195
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="tone=success"] {
196
+ --_badge-border: var(--ui-success-solid);
197
+ --_badge-text: var(--ui-success-subtle-text, var(--ui-success-solid));
198
+ }
199
+
200
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="tone=warning"] {
201
+ --_badge-border: var(--ui-warning-solid);
202
+ --_badge-text: var(--ui-warning-subtle-text, var(--ui-warning-solid));
203
+ }
204
+
205
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="tone=info"] {
206
+ --_badge-border: var(--ui-info-solid);
207
+ --_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));
208
+ }
209
+
178
210
  /* A tag is flat at the start and points at the end. The point is cut from the box, so it has no
179
211
  outline to follow: the edge is the fill. The end padding grows by the point's depth so the
180
212
  label never runs into it. */
@@ -201,6 +233,46 @@ const hostState = computed(() =>
201
233
  clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);
202
234
  }
203
235
 
236
+ /* The tag clips its point, including the native border. Draw the outer shape in the border
237
+ colour and an inset inner shape in the surface colour to keep a visible diagonal edge. */
238
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="shape=tag"] {
239
+ position: relative;
240
+ isolation: isolate;
241
+ background: var(--ui-badge-border, var(--_badge-border));
242
+ }
243
+
244
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="shape=tag"]::before {
245
+ content: "";
246
+ position: absolute;
247
+ inset: 1px;
248
+ z-index: -1;
249
+ background: var(--_badge-outline-surface);
250
+ clip-path: polygon(
251
+ 0 0,
252
+ calc(100% - var(--_badge-point)) 0,
253
+ 100% 50%,
254
+ calc(100% - var(--_badge-point)) 100%,
255
+ 0 100%
256
+ );
257
+ pointer-events: none;
258
+ }
259
+
260
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="shape=tag"]:dir(rtl)::before {
261
+ clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);
262
+ }
263
+
264
+ @media (forced-colors: active) {
265
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="shape=tag"] {
266
+ forced-color-adjust: none;
267
+ background: CanvasText;
268
+ color: CanvasText;
269
+ }
270
+
271
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=outline"][data-ui-badge-state~="shape=tag"]::before {
272
+ background: Canvas;
273
+ }
274
+ }
275
+
204
276
  /* A component that sets its display still honours the hidden attribute on its root. */
205
277
  [data-component~="ui-badge"][hidden] {
206
278
  display: none;
package/vue/UiButton.d.ts CHANGED
@@ -3,6 +3,7 @@ type __VLS_Props = {
3
3
  as?: 'button' | 'a';
4
4
  disabled?: boolean;
5
5
  href?: string;
6
+ pending?: boolean;
6
7
  rel?: string;
7
8
  size?: 'sm' | 'md' | 'lg';
8
9
  stretch?: boolean;
@@ -11,11 +12,11 @@ type __VLS_Props = {
11
12
  type?: 'button' | 'submit' | 'reset';
12
13
  variant?: 'outline' | 'solid' | 'danger' | 'ghost' | 'link';
13
14
  };
14
- declare var __VLS_1: {}, __VLS_3: {};
15
+ declare var __VLS_6: {}, __VLS_13: {};
15
16
  type __VLS_Slots = {} & {
16
- default?: (props: typeof __VLS_1) => any;
17
+ default?: (props: typeof __VLS_6) => any;
17
18
  } & {
18
- default?: (props: typeof __VLS_3) => any;
19
+ default?: (props: typeof __VLS_13) => any;
19
20
  };
20
21
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
21
22
  type: "button" | "submit" | "reset";
@@ -25,6 +26,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
25
26
  align: "center" | "start";
26
27
  as: "button" | "a";
27
28
  disabled: boolean;
29
+ pending: boolean;
28
30
  stretch: boolean;
29
31
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
30
32
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
package/vue/UiButton.vue CHANGED
@@ -1,6 +1,9 @@
1
1
  <!-- Generated by HTML Next 1.0.0-alpha.7 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import { computed } from 'vue'
3
+ import { computed, ref } from 'vue'
4
+ import * as controllerModule from '../components/ui-button/ui-button.js'
5
+ import { createDispatch, useComponentHost } from './host'
6
+ import UiSpinner from './UiSpinner.vue'
4
7
 
5
8
  defineOptions({ inheritAttrs: false })
6
9
 
@@ -10,6 +13,7 @@ const props = withDefaults(
10
13
  as?: 'button' | 'a'
11
14
  disabled?: boolean
12
15
  href?: string
16
+ pending?: boolean
13
17
  rel?: string
14
18
  size?: 'sm' | 'md' | 'lg'
15
19
  stretch?: boolean
@@ -22,6 +26,7 @@ const props = withDefaults(
22
26
  align: 'center',
23
27
  as: 'button',
24
28
  disabled: false,
29
+ pending: false,
25
30
  size: 'md',
26
31
  stretch: false,
27
32
  tone: 'accent',
@@ -30,6 +35,8 @@ const props = withDefaults(
30
35
  },
31
36
  )
32
37
 
38
+ const root = ref<HTMLElement | null>(null)
39
+
33
40
  /** The values the styles' :host-state() rules test. */
34
41
  const hostState = computed(() =>
35
42
  [
@@ -38,9 +45,18 @@ const hostState = computed(() =>
38
45
  props.size && `size size=${props.size}`,
39
46
  props.variant && `variant variant=${props.variant}`,
40
47
  props.tone && `tone tone=${props.tone}`,
48
+ props.pending && 'pending',
41
49
  ].filter(Boolean).join(' ')
42
50
  )
43
51
 
52
+ const dispatch = createDispatch(root)
53
+
54
+ useComponentHost(controllerModule.default, {
55
+ root,
56
+ dispatch,
57
+ props,
58
+ })
59
+
44
60
  function text(value: unknown): string {
45
61
  if (Array.isArray(value)) return value.map(text).join(' ')
46
62
  return value === null || value === undefined || typeof value === 'object' ? '' : String(value)
@@ -60,22 +76,32 @@ function attribute(value: unknown): any {
60
76
  v-if="as === 'a'"
61
77
  data-component="ui-button"
62
78
  v-bind="$attrs"
63
- :href="attribute(({ true: null, false: href })[`${disabled}`])"
79
+ :href="attribute(({ true: null, false: href })[`${disabled || pending}`])"
64
80
  :target="target"
65
81
  :rel="rel"
66
- :aria-disabled="typeof (({ true: 'true', false: null })[`${Boolean(disabled && href)}`]) === 'boolean'
67
- ? String(({ true: 'true', false: null })[`${Boolean(disabled && href)}`])
68
- : attribute(({ true: 'true', false: null })[`${Boolean(disabled && href)}`])"
82
+ :aria-disabled="typeof (({ true: 'true', false: null })[`${disabled || pending}`]) === 'boolean'
83
+ ? String(({ true: 'true', false: null })[`${disabled || pending}`])
84
+ : attribute(({ true: 'true', false: null })[`${disabled || pending}`])"
85
+ :aria-busy="pending"
86
+ :tabindex="attribute(({ true: '0', false: null })[`${pending && !disabled}`])"
69
87
  :data-ui-button-state="hostState || undefined"
70
- ><slot /></a>
88
+ ref="root"
89
+ ><UiSpinner v-if="pending" size="sm" class="pending-spinner" />
90
+ <slot /></a>
71
91
  <button
72
92
  v-else
73
93
  data-component="ui-button"
74
94
  v-bind="$attrs"
75
95
  :type="type"
76
96
  :disabled="disabled"
97
+ :aria-disabled="typeof (({ true: 'true', false: null })[`${pending}`]) === 'boolean'
98
+ ? String(({ true: 'true', false: null })[`${pending}`])
99
+ : attribute(({ true: 'true', false: null })[`${pending}`])"
100
+ :aria-busy="pending"
77
101
  :data-ui-button-state="hostState || undefined"
102
+ ref="root"
78
103
  >
104
+ <UiSpinner v-if="pending" size="sm" class="pending-spinner" />
79
105
  <slot />
80
106
  </button>
81
107
  </template>
@@ -187,7 +213,7 @@ function attribute(value: unknown): any {
187
213
  border-style: solid;
188
214
  border-width: 1px;
189
215
  border-color: var(--ui-button-border, var(--_tone));
190
- border-radius: var(--ui-button-radius, var(--ui-radius-md));
216
+ border-radius: var(--ui-button-radius, var(--ui-action-radius, var(--ui-radius-md)));
191
217
  background-color: var(--ui-button-surface, oklch(from var(--_tone) l c h / 5%));
192
218
  color: var(--ui-button-text, var(--_tone-text));
193
219
  font: inherit;
@@ -206,6 +232,10 @@ function attribute(value: unknown): any {
206
232
  margin: 0;
207
233
  }
208
234
 
235
+ .pending-spinner {
236
+ margin-inline-end: var(--ui-space-2);
237
+ }
238
+
209
239
  @supports (text-box-trim: trim-both) {
210
240
  [data-component~="ui-button"] {
211
241
  text-box-trim: trim-both;
@@ -348,6 +378,10 @@ function attribute(value: unknown): any {
348
378
  box-shadow: none;
349
379
  }
350
380
 
381
+ [data-component~="ui-button"][data-ui-button-state~="pending"]:focus-visible {
382
+ box-shadow: var(--ui-focus-halo);
383
+ }
384
+
351
385
  /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:
352
386
  it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
353
387
  the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
@@ -1,12 +1,12 @@
1
1
  type __VLS_Props = {
2
- tone?: 'info' | 'note' | 'warning' | 'success' | 'danger';
2
+ tone?: 'info' | 'neutral' | 'note' | 'warning' | 'success' | 'danger';
3
3
  };
4
4
  declare var __VLS_1: {};
5
5
  type __VLS_Slots = {} & {
6
6
  default?: (props: typeof __VLS_1) => any;
7
7
  };
8
8
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
9
- tone: "info" | "note" | "warning" | "success" | "danger";
9
+ tone: "info" | "neutral" | "note" | "warning" | "success" | "danger";
10
10
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
11
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
12
12
  declare const _default: typeof __VLS_export;
package/vue/UiCallout.vue CHANGED
@@ -6,7 +6,7 @@ defineOptions({ inheritAttrs: false })
6
6
 
7
7
  const props = withDefaults(
8
8
  defineProps<{
9
- tone?: 'info' | 'note' | 'warning' | 'success' | 'danger'
9
+ tone?: 'info' | 'neutral' | 'note' | 'warning' | 'success' | 'danger'
10
10
  }>(),
11
11
  {
12
12
  tone: 'info',
@@ -42,7 +42,7 @@ const hostState = computed(() =>
42
42
  <path d="M12 8h.01"></path>
43
43
  </svg>
44
44
  <svg
45
- v-if="tone === 'note'"
45
+ v-if="tone === 'neutral' || tone === 'note'"
46
46
  viewBox="0 0 24 24"
47
47
  fill="none"
48
48
  stroke="currentColor"
@@ -191,6 +191,7 @@ const hostState = computed(() =>
191
191
  min-inline-size: 0;
192
192
  }
193
193
 
194
+ [data-component~="ui-callout"][data-ui-callout-state~="tone=neutral"],
194
195
  [data-component~="ui-callout"][data-ui-callout-state~="tone=note"] {
195
196
  --_callout-surface: var(--ui-surface-muted);
196
197
  --_callout-border: var(--ui-border-strong);
@@ -2,6 +2,7 @@ type __VLS_Props = {
2
2
  checked?: boolean;
3
3
  disabled?: boolean;
4
4
  indeterminate?: boolean;
5
+ invalid?: boolean;
5
6
  name?: string;
6
7
  required?: boolean;
7
8
  size?: 'sm' | 'md' | 'lg';
@@ -31,6 +32,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
31
32
  "onUpdate:value"?: ((value: string) => any) | undefined;
32
33
  }>, {
33
34
  name: string;
35
+ invalid: boolean;
34
36
  size: "sm" | "md" | "lg";
35
37
  value: string;
36
38
  disabled: boolean;
@@ -11,6 +11,7 @@ const props = withDefaults(
11
11
  checked?: boolean
12
12
  disabled?: boolean
13
13
  indeterminate?: boolean
14
+ invalid?: boolean
14
15
  name?: string
15
16
  required?: boolean
16
17
  size?: 'sm' | 'md' | 'lg'
@@ -20,6 +21,7 @@ const props = withDefaults(
20
21
  checked: false,
21
22
  disabled: false,
22
23
  indeterminate: false,
24
+ invalid: false,
23
25
  name: '',
24
26
  required: false,
25
27
  size: 'md',
@@ -46,6 +48,7 @@ const internalChecked = ref(false)
46
48
  /** The values the styles' :host-state() rules test. */
47
49
  const hostState = computed(() =>
48
50
  [
51
+ props.invalid && 'invalid',
49
52
  props.disabled && 'disabled',
50
53
  props.size && `size size=${props.size}`,
51
54
  ].filter(Boolean).join(' ')
@@ -86,6 +89,7 @@ useComponentHost(controllerModule.default, {
86
89
  :checked.prop="internalChecked"
87
90
  :indeterminate.prop="indeterminate"
88
91
  :disabled="disabled"
92
+ :aria-invalid="invalid"
89
93
  :required="required"
90
94
  :name="name"
91
95
  :value="value"
@@ -103,6 +107,10 @@ useComponentHost(controllerModule.default, {
103
107
  syntax: "*";
104
108
  inherits: false;
105
109
  }
110
+ @property --ui-checkbox-invalid-border {
111
+ syntax: "*";
112
+ inherits: false;
113
+ }
106
114
  @property --ui-checkbox-size {
107
115
  syntax: "*";
108
116
  inherits: false;
@@ -111,6 +119,10 @@ useComponentHost(controllerModule.default, {
111
119
  [data-component~="ui-checkbox"] {
112
120
  /* Hooks do not inherit, so the parts below read them from the root. */
113
121
  --_ui-checkbox-size: var(--ui-checkbox-size);
122
+ --_ui-checkbox-invalid-border: var(
123
+ --ui-checkbox-invalid-border,
124
+ var(--ui-field-danger, var(--ui-danger-solid))
125
+ );
114
126
 
115
127
  display: inline-flex;
116
128
  align-items: flex-start;
@@ -208,6 +220,10 @@ input:focus-visible {
208
220
  outline-offset: 2px;
209
221
  }
210
222
 
223
+ [data-component~="ui-checkbox"][data-ui-checkbox-state~="invalid"] input {
224
+ border-color: var(--_ui-checkbox-invalid-border);
225
+ }
226
+
211
227
  [data-component~="ui-checkbox"][data-ui-checkbox-state~="disabled"] {
212
228
  color: var(--ui-disabled-text);
213
229
  cursor: not-allowed;
@@ -6,6 +6,7 @@ type __VLS_Props = {
6
6
  disclosure?: boolean;
7
7
  filter?: 'label' | 'none';
8
8
  help?: string;
9
+ invalid?: boolean;
9
10
  items?: readonly ({
10
11
  readonly id: string;
11
12
  readonly value: string;
@@ -20,8 +21,10 @@ type __VLS_Props = {
20
21
  })[];
21
22
  label?: string;
22
23
  labelVisibility?: 'visible' | 'sr-only';
24
+ loading?: boolean;
23
25
  multiple?: boolean;
24
26
  name?: string;
27
+ openOnFocus?: boolean;
25
28
  placeholder?: string;
26
29
  query?: string;
27
30
  readonly?: boolean;
@@ -31,7 +34,7 @@ type __VLS_Props = {
31
34
  tokenSeparators?: readonly (string)[];
32
35
  value?: string | null;
33
36
  };
34
- declare var __VLS_1: {}, __VLS_4: `item-${string}`, __VLS_5: {}, __VLS_20: `option-${string}`, __VLS_21: {}, __VLS_29: {}, __VLS_31: {};
37
+ declare var __VLS_1: {}, __VLS_4: `item-${string}`, __VLS_5: {}, __VLS_20: `option-${string}`, __VLS_21: {}, __VLS_29: {}, __VLS_31: {}, __VLS_33: {};
35
38
  type __VLS_Slots = {} & {
36
39
  [K in NonNullable<typeof __VLS_4>]?: (props: typeof __VLS_5) => any;
37
40
  } & {
@@ -39,9 +42,11 @@ type __VLS_Slots = {} & {
39
42
  } & {
40
43
  start?: (props: typeof __VLS_1) => any;
41
44
  } & {
42
- footer?: (props: typeof __VLS_29) => any;
45
+ empty?: (props: typeof __VLS_29) => any;
43
46
  } & {
44
- default?: (props: typeof __VLS_31) => any;
47
+ footer?: (props: typeof __VLS_31) => any;
48
+ } & {
49
+ default?: (props: typeof __VLS_33) => any;
45
50
  };
46
51
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
47
52
  validate: (...args: unknown[]) => Promise<unknown>;
@@ -324,6 +329,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
324
329
  filter: "label" | "none";
325
330
  label: string;
326
331
  name: string;
332
+ invalid: boolean;
327
333
  size: "sm" | "md" | "lg";
328
334
  disabled: boolean;
329
335
  required: boolean;
@@ -333,7 +339,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
333
339
  disclosure: boolean;
334
340
  help: string;
335
341
  labelVisibility: "visible" | "sr-only";
342
+ loading: boolean;
336
343
  multiple: boolean;
344
+ openOnFocus: boolean;
337
345
  placeholder: string;
338
346
  readonly: boolean;
339
347
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -17,6 +17,7 @@ const props = withDefaults(
17
17
  disclosure?: boolean
18
18
  filter?: 'label' | 'none'
19
19
  help?: string
20
+ invalid?: boolean
20
21
  items?:
21
22
  readonly ({
22
23
  readonly id: string
@@ -32,8 +33,10 @@ const props = withDefaults(
32
33
  })[]
33
34
  label?: string
34
35
  labelVisibility?: 'visible' | 'sr-only'
36
+ loading?: boolean
35
37
  multiple?: boolean
36
38
  name?: string
39
+ openOnFocus?: boolean
37
40
  placeholder?: string
38
41
  query?: string
39
42
  readonly?: boolean
@@ -51,10 +54,13 @@ const props = withDefaults(
51
54
  disclosure: false,
52
55
  filter: 'label',
53
56
  help: '',
57
+ invalid: false,
54
58
  label: '',
55
59
  labelVisibility: 'visible',
60
+ loading: false,
56
61
  multiple: false,
57
62
  name: '',
63
+ openOnFocus: false,
58
64
  placeholder: '',
59
65
  readonly: false,
60
66
  required: false,
@@ -255,7 +261,6 @@ const rows = ref<
255
261
  }[]
256
262
  >([])
257
263
  const active = ref<number | null>(-1)
258
- const loading = ref(false)
259
264
  const helpOpen = ref(false)
260
265
  const lookupError = ref('')
261
266
  const validation = ref<
@@ -304,6 +309,7 @@ const hostState = computed(() =>
304
309
  props.size && `size size=${props.size}`,
305
310
  validationStatus.value && 'validationStatus',
306
311
  `validationStatus=${encodeURIComponent(validationStatus.value)}`,
312
+ props.invalid && 'invalid',
307
313
  props.multiple && 'multiple',
308
314
  ].filter(Boolean).join(' ')
309
315
  )
@@ -709,7 +715,6 @@ const { host, ready } = useComponentHost(controllerModule.default, {
709
715
  expanded,
710
716
  rows,
711
717
  active,
712
- loading,
713
718
  helpOpen,
714
719
  lookupError,
715
720
  validation,
@@ -774,8 +779,8 @@ defineExpose({
774
779
  :id="`${uid}-input`"
775
780
  :aria-controls="`${uid}-listbox`"
776
781
  :aria-expanded="expanded"
777
- :aria-invalid="validationStatus === 'error'"
778
- :aria-busy="validationStatus === 'pending'"
782
+ :aria-invalid="invalid || validationStatus === 'error'"
783
+ :aria-busy="loading || validationStatus === 'pending'"
779
784
  :value.prop="display"
780
785
  :placeholder="placeholder"
781
786
  :disabled="disabled"
@@ -923,6 +928,9 @@ defineExpose({
923
928
  {{ `Create “${raw}”` }}
924
929
  </div>
925
930
  <div v-if="message" class="message">{{ message }}</div>
931
+ <div v-if="!loading && !(rows[0]) && !creatable && !lookupError" class="message">
932
+ <slot name="empty">No suggestions.</slot>
933
+ </div>
926
934
  </div>
927
935
  <slot name="footer" />
928
936
  </div>
@@ -976,6 +984,30 @@ defineExpose({
976
984
  syntax: "*";
977
985
  inherits: false;
978
986
  }
987
+ @property --ui-combobox-radius {
988
+ syntax: "*";
989
+ inherits: false;
990
+ }
991
+ @property --ui-combobox-invalid-border {
992
+ syntax: "*";
993
+ inherits: false;
994
+ }
995
+ @property --ui-combobox-popup-surface {
996
+ syntax: "*";
997
+ inherits: false;
998
+ }
999
+ @property --ui-combobox-popup-border {
1000
+ syntax: "*";
1001
+ inherits: false;
1002
+ }
1003
+ @property --ui-combobox-popup-radius {
1004
+ syntax: "*";
1005
+ inherits: false;
1006
+ }
1007
+ @property --ui-combobox-popup-shadow {
1008
+ syntax: "*";
1009
+ inherits: false;
1010
+ }
979
1011
 
980
1012
  [data-component~="ui-combobox"] {
981
1013
  /* Hooks do not inherit, so the parts below read them from the root. */
@@ -989,6 +1021,12 @@ defineExpose({
989
1021
  --_ui-combobox-item-min-block-size: var(--ui-combobox-item-min-block-size);
990
1022
  --_ui-combobox-item-input-min-inline-size: var(--ui-combobox-item-input-min-inline-size);
991
1023
  --_ui-combobox-item-item-max-inline-size: var(--ui-combobox-item-item-max-inline-size);
1024
+ --_ui-combobox-radius: var(--ui-combobox-radius);
1025
+ --_ui-combobox-invalid-border: var(--ui-combobox-invalid-border);
1026
+ --_ui-combobox-popup-surface: var(--ui-combobox-popup-surface);
1027
+ --_ui-combobox-popup-border: var(--ui-combobox-popup-border);
1028
+ --_ui-combobox-popup-radius: var(--ui-combobox-popup-radius);
1029
+ --_ui-combobox-popup-shadow: var(--ui-combobox-popup-shadow);
992
1030
 
993
1031
  display: grid;
994
1032
  gap: var(--ui-space-1);
@@ -1015,7 +1053,7 @@ label {
1015
1053
  display: flex;
1016
1054
  min-inline-size: 0;
1017
1055
  border: 1px solid var(--ui-control-border, var(--ui-border-default));
1018
- border-radius: var(--ui-radius-md);
1056
+ border-radius: var(--_ui-combobox-radius, var(--ui-field-radius, var(--ui-radius-md)));
1019
1057
  background: var(--ui-control-surface, var(--ui-surface-default));
1020
1058
  box-shadow: var(--ui-control-inset);
1021
1059
  transition:
@@ -1137,8 +1175,12 @@ input:disabled, button:disabled {
1137
1175
  .field:has(input:disabled) {
1138
1176
  background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
1139
1177
  }
1140
- [data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field {
1141
- border-color: var(--ui-danger-solid, var(--ui-accent-active));
1178
+ [data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field,
1179
+ [data-component~="ui-combobox"][data-ui-combobox-state~="invalid"] .field {
1180
+ border-color: var(
1181
+ --_ui-combobox-invalid-border,
1182
+ var(--ui-field-danger, var(--ui-danger-solid, var(--ui-accent-active)))
1183
+ );
1142
1184
  }
1143
1185
  .popup {
1144
1186
  box-sizing: border-box;
@@ -1148,11 +1190,18 @@ input:disabled, button:disabled {
1148
1190
  overflow: auto;
1149
1191
  margin: 0;
1150
1192
  padding: var(--ui-space-1);
1151
- border: 1px solid var(--ui-border-default);
1152
- border-radius: var(--ui-radius-md);
1153
- background: var(--ui-surface-elevated);
1193
+ border: 1px solid
1194
+ var(--_ui-combobox-popup-border, var(--ui-overlay-border, var(--ui-border-default)));
1195
+ border-radius: var(--_ui-combobox-popup-radius, var(--ui-overlay-radius, var(--ui-radius-md)));
1196
+ background: var(
1197
+ --_ui-combobox-popup-surface,
1198
+ var(--ui-overlay-surface, var(--ui-surface-elevated))
1199
+ );
1154
1200
  color: var(--ui-text-primary);
1155
- box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));
1201
+ box-shadow: var(
1202
+ --_ui-combobox-popup-shadow,
1203
+ var(--ui-overlay-shadow, var(--ui-elevation-overlay, var(--ui-shadow-lg)))
1204
+ );
1156
1205
  }
1157
1206
  [hidden] {
1158
1207
  display: none;