@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
package/README.md CHANGED
@@ -42,7 +42,7 @@ The editor components' event and geometry types, without Tiptap, are in
42
42
  ```
43
43
 
44
44
  Importing the package registers every component with the
45
- [HTML Next runtime](https://www.npmjs.com/package/@nextwebwg/declarative-components), which turns
45
+ [HTML Next runtime](https://www.npmjs.com/package/@nextwebwg/html-next), which turns
46
46
  each `<ui-*>` element into its native root. Each component's styles are scoped to it; the token
47
47
  stylesheet is the only stylesheet to include. Without a build, link components one by one from
48
48
  `@threadlabs/looma/components/<tag>/<tag>.html`.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Marks the document `data-ui-input-modality="touch"` once the user actually touches it, rather than
3
+ * guessing from capability media queries: hybrid devices keep compact pointer affordances until then.
4
+ * Idempotent per document; touch is sticky once observed.
5
+ *
6
+ * @param {Document} document
7
+ */
8
+ export function trackInputModality(document: Document): void;
@@ -4,6 +4,8 @@ const initialized = new WeakSet();
4
4
  * Marks the document `data-ui-input-modality="touch"` once the user actually touches it, rather than
5
5
  * guessing from capability media queries: hybrid devices keep compact pointer affordances until then.
6
6
  * Idempotent per document; touch is sticky once observed.
7
+ *
8
+ * @param {Document} document
7
9
  */
8
10
  export function trackInputModality(document) {
9
11
  if (initialized.has(document)) return;
@@ -4,6 +4,9 @@
4
4
  >Visual emphasis and semantic intent. link is an inline text action that reads as a link.</prop>
5
5
  <prop name="size" type="sm | md | lg" default="md">Control size.</prop>
6
6
  <prop name="disabled" type="boolean" default="false">disabled token.</prop>
7
+ <prop name="align" type="center | start" default="center"
8
+ >Content alignment. start lays the content out like a list option: from the start edge, with start-aligned text.</prop>
9
+ <prop name="stretch" type="boolean" default="false">Fills the inline size of its container.</prop>
7
10
  </defs>
8
11
  <button type="button" :disabled="disabled"><slot></slot></button>
9
12
  <style>
@@ -19,6 +22,16 @@
19
22
  color: var(--ui-action-primary-text, var(--ui-text-on-accent));
20
23
  }
21
24
 
25
+ :host-state([align="start"]) {
26
+ justify-content: flex-start;
27
+ text-align: start;
28
+ }
29
+
30
+ :host-state([stretch]) {
31
+ display: flex;
32
+ inline-size: 100%;
33
+ }
34
+
22
35
  :host {
23
36
  appearance: none;
24
37
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md, 2.5rem));
@@ -114,6 +127,7 @@
114
127
  border-color: transparent;
115
128
  background: transparent;
116
129
  box-shadow: none;
130
+ color: var(--ui-button-ghost-text, var(--ui-action-secondary-text, var(--ui-text-primary)));
117
131
  }
118
132
 
119
133
  /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
@@ -141,9 +155,31 @@
141
155
  var(--ui-focus-halo);
142
156
  }
143
157
 
158
+ /* Disabled colours fall back to each variant's own; ghost and link take only the text colour. */
144
159
  :host:disabled {
145
- opacity: 0.6;
160
+ opacity: var(--ui-button-disabled-opacity, 0.6);
146
161
  cursor: not-allowed;
162
+ border-color: var(--ui-button-disabled-border, var(--ui-button-border, var(--ui-border-strong)));
163
+ background-color: var(--ui-button-disabled-surface, var(--ui-button-surface, var(--ui-surface-elevated)));
164
+ color: var(--ui-button-disabled-text, var(--ui-button-text, var(--ui-action-secondary-text, var(--ui-text-primary))));
165
+ }
166
+
167
+ :host-state([variant="solid"]):disabled {
168
+ border-color: var(--ui-button-disabled-border, var(--ui-action-primary-surface, var(--ui-accent-solid)));
169
+ background-color: var(--ui-button-disabled-surface, var(--ui-action-primary-surface, var(--ui-accent-solid)));
170
+ color: var(--ui-button-disabled-text, var(--ui-action-primary-text, var(--ui-text-on-accent)));
171
+ }
172
+
173
+ :host-state([variant="danger"]):disabled {
174
+ border-color: var(--ui-button-disabled-border, var(--ui-danger-solid));
175
+ background-color: var(--ui-button-disabled-surface, var(--ui-danger-solid));
176
+ color: var(--ui-button-disabled-text, var(--ui-text-on-accent));
177
+ }
178
+
179
+ :host-state([variant="ghost"]):disabled {
180
+ border-color: transparent;
181
+ background-color: transparent;
182
+ color: var(--ui-button-disabled-text, var(--ui-button-ghost-text, var(--ui-action-secondary-text, var(--ui-text-primary))));
147
183
  }
148
184
 
149
185
  @media (pointer: coarse) {
@@ -183,6 +219,11 @@
183
219
  transform: none;
184
220
  }
185
221
 
222
+ :host-state([variant="link"]):disabled {
223
+ background: none;
224
+ color: var(--ui-button-disabled-text, var(--ui-button-link-color, var(--ui-text-secondary)));
225
+ }
226
+
186
227
  :host-state([variant="link"]):focus-visible {
187
228
  box-shadow: none;
188
229
  /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
@@ -23,16 +23,24 @@
23
23
  <prop name="help" type="string" default="">help token.</prop>
24
24
  <state name="raw" :value="''"></state>
25
25
  <state name="display" :value="''"></state>
26
- <state name="selected" :value="null"></state>
26
+ <state name="selected" type="string | null" :value="null"></state>
27
27
  <state name="expanded" :value="false"></state>
28
- <state name="rows" :value="[]"></state>
28
+ <state name="rows" type="list(object({ id: string, value: string, label: string, group?: string, disabled: boolean }))" :value="[]"></state>
29
29
  <state name="active" :value="-1"></state>
30
30
  <state name="loading" :value="false"></state>
31
31
  <state name="helpOpen" :value="false"></state>
32
32
  <state name="lookupError" :value="''"></state>
33
- <state name="validation" :value="{ status: 'pristine', touched: false, dirty: false, issues: [] }"></state>
33
+ <state
34
+ name="validation"
35
+ type="object({ status: pristine | pending | valid | warning | error, touched: boolean, dirty: boolean, issues: list(object({ message: string })), ... })"
36
+ :value="{ status: 'pristine', touched: false, dirty: false, issues: [] }"
37
+ ></state>
34
38
  <state name="uid" :value="''"></state>
35
- <state name="groups" :value="[]"></state>
39
+ <state
40
+ name="groups"
41
+ type="list(object({ name: string, role: group | presentation, label: string | null, rows: list(object({ id: string, value: string, label: string, group?: string, disabled: boolean, index: integer })) }))"
42
+ :value="[]"
43
+ ></state>
36
44
  <state name="creatable" :value="false"></state>
37
45
  <state name="createIndex" :value="0"></state>
38
46
  <state name="message" :value="''"></state>
@@ -127,6 +127,19 @@
127
127
  outline-offset: 2px;
128
128
  }
129
129
 
130
+ /* A touch target, like Button on coarse pointers. */
131
+ @media (pointer: coarse) {
132
+ .close {
133
+ inline-size: var(--ui-control-min-block-size, 2.75rem);
134
+ block-size: var(--ui-control-min-block-size, 2.75rem);
135
+ }
136
+ }
137
+
138
+ html[data-ui-input-modality="touch"] :host .close {
139
+ inline-size: var(--ui-control-min-block-size, 2.75rem);
140
+ block-size: var(--ui-control-min-block-size, 2.75rem);
141
+ }
142
+
130
143
  .body {
131
144
  flex: 1 1 auto;
132
145
  min-block-size: 0;
@@ -4,7 +4,7 @@
4
4
  <prop name="maxRows" type="integer" default="8">The most rows the grid offers (at most 10).</prop>
5
5
  <prop name="maxCols" type="integer" default="8">The most columns the grid offers (at most 10).</prop>
6
6
  <prop name="headerRow" type="boolean" default="false">Whether table insertion initially includes a header row.</prop>
7
- <state name="cells" :value="[]"></state>
7
+ <state name="cells" type="list(object({ key: string, row: integer, col: integer, label: string, selected: boolean }))" :value="[]"></state>
8
8
  <state name="rows" :value="8"></state>
9
9
  <state name="cols" :value="8"></state>
10
10
  <state name="hint" :value="''"></state>
@@ -10,7 +10,7 @@
10
10
  type="object({ left?: number, top?: number, right?: number, bottom?: number, x?: number, y?: number, width?: number, height?: number }) | null"
11
11
  >Where the @ was typed, in viewport coordinates.</prop>
12
12
  <state name="visible" :value="false"></state>
13
- <state name="rows" :value="[]"></state>
13
+ <state name="rows" type="list(object({ id: string, label: string, detail?: string, initials: string }))" :value="[]"></state>
14
14
  <state name="searching" :value="false"></state>
15
15
  <state name="active" :value="0"></state>
16
16
  <state name="prefix" :value="'ui-editor-mention-menu'"></state>
@@ -7,8 +7,12 @@
7
7
  name="actions"
8
8
  type="list(align-left | align-center | align-right | background-none | background-gray | background-yellow | background-blue | background-green | background-red | add-row-before | add-row-after | add-column-before | add-column-after | clear-cells | merge-cells | split-cell | delete-row | delete-column | delete-table)"
9
9
  >The complete set of commands the current selection permits.</prop>
10
- <state name="swatches" :value="[]"></state>
11
- <state name="sections" :value="[]"></state>
10
+ <state name="swatches" type="list(object({ action: string, label: string, color: string, selected: boolean })) | null" :value="[]"></state>
11
+ <state
12
+ name="sections"
13
+ type="list(object({ heading: string, items: list(object({ action: string, label: string, icon: string, danger: boolean })) }))"
14
+ :value="[]"
15
+ ></state>
12
16
  <event
13
17
  name="action"
14
18
  type="object({ action: align-left | align-center | align-right | background-none | background-gray | background-yellow | background-blue | background-green | background-red | add-row-before | add-row-after | add-column-before | add-column-after | clear-cells | merge-cells | split-cell | delete-row | delete-column | delete-table })"
@@ -6,10 +6,26 @@
6
6
  name="geometry"
7
7
  type="object({ rowBoundaries: list(number), columnBoundaries: list(number), activeCell: object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer }) | null, hoveredCell?: object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer }) | null }) | null"
8
8
  >The authoritative editor-measured table boundaries and active or hovered cell rectangles.</prop>
9
- <state name="rows" :value="[]"></state>
10
- <state name="cols" :value="[]"></state>
11
- <state name="hovered" :value="null"></state>
12
- <state name="active" :value="null"></state>
9
+ <state
10
+ name="rows"
11
+ type="list(object({ key: string, index: integer, offset: string, affordance: insert-row | insert-column, action: add-row-before | add-row-after | add-column-before | add-column-after, label: string }))"
12
+ :value="[]"
13
+ ></state>
14
+ <state
15
+ name="cols"
16
+ type="list(object({ key: string, index: integer, offset: string, affordance: insert-row | insert-column, action: add-row-before | add-row-after | add-column-before | add-column-after, label: string }))"
17
+ :value="[]"
18
+ ></state>
19
+ <state
20
+ name="hovered"
21
+ type="object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer, rowOffset: string, columnOffset: string }) | null"
22
+ :value="null"
23
+ ></state>
24
+ <state
25
+ name="active"
26
+ type="object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer, menuLeft: string, menuTop: string }) | null"
27
+ :value="null"
28
+ ></state>
13
29
  <state name="activeKey" :value="''"></state>
14
30
  <event
15
31
  name="action"
@@ -8,10 +8,14 @@
8
8
  name="actions"
9
9
  type="list(align-left | align-center | align-right | background-none | background-gray | background-yellow | background-blue | background-green | background-red | add-row-before | add-row-after | add-column-before | add-column-after | clear-cells | merge-cells | split-cell | delete-row | delete-column | delete-table)"
10
10
  >The complete set of commands the current selection permits.</prop>
11
- <state name="alignments" :value="[]"></state>
12
- <state name="structure" :value="[]"></state>
13
- <state name="swatches" :value="[]"></state>
14
- <state name="sections" :value="[]"></state>
11
+ <state name="alignments" type="list(object({ action: align-left | align-center | align-right, label: string, active: boolean }))" :value="[]"></state>
12
+ <state name="structure" type="list(object({ action: add-row-after | add-column-after, label: string, icon: string }))" :value="[]"></state>
13
+ <state name="swatches" type="list(object({ action: string, label: string, color: string, selected: boolean }))" :value="[]"></state>
14
+ <state
15
+ name="sections"
16
+ type="list(object({ heading: string, items: list(object({ action: string, label: string, icon: string, danger: boolean })) }))"
17
+ :value="[]"
18
+ ></state>
15
19
  <state name="hasOverflow" :value="false"></state>
16
20
  <state name="overflowOpen" :value="false"></state>
17
21
  <event
@@ -5,10 +5,10 @@
5
5
  <prop name="required" type="boolean" default="false">required token.</prop>
6
6
  </defs>
7
7
  <div>
8
- <slot name="label"></slot>
8
+ <div class="label"><slot name="label"></slot></div>
9
9
  <slot></slot>
10
- <slot name="help"></slot>
11
- <slot name="error"></slot>
10
+ <div class="help"><slot name="help"></slot></div>
11
+ <div class="error"><slot name="error"></slot></div>
12
12
  </div>
13
13
  <style>
14
14
  :host {
@@ -19,19 +19,30 @@
19
19
  color: var(--ui-text-primary);
20
20
  }
21
21
 
22
- :slotted([slot="label"]) {
22
+ /* Each named region styles whatever fills it, however it was slotted (slot="…" in HTML, #label
23
+ in Vue), and generates no box of its own, so an empty region adds no gap. */
24
+ .label,
25
+ .help,
26
+ .error {
27
+ display: contents;
28
+ }
29
+
30
+ .label {
23
31
  color: var(--ui-text-secondary);
24
32
  font-size: 0.95rem;
25
33
  }
26
34
 
27
- :slotted([slot="help"]) {
28
- min-block-size: var(--ui-form-field-help-min-block-size, 0);
35
+ .help {
29
36
  color: var(--ui-text-muted);
30
37
  font-size: 0.875rem;
31
38
  line-height: var(--ui-line-height-md);
32
39
  }
33
40
 
34
- :slotted([slot="error"]),
41
+ .help > :slotted(*) {
42
+ min-block-size: var(--ui-form-field-help-min-block-size, 0);
43
+ }
44
+
45
+ .error,
35
46
  :slotted([role="alert"]) {
36
47
  color: var(--ui-accent-active);
37
48
  font-size: 0.875rem;
@@ -1,7 +1,11 @@
1
1
  <template component="ui-icon" controller="./ui-icon.js">
2
2
  <defs>
3
3
  <prop name="name" type="string" default="">The icon's name.</prop>
4
- <state name="shapes" :value="[]"></state>
4
+ <state
5
+ name="shapes"
6
+ type="list(object({ tag: path | circle | rect, d?: string, cx?: string, cy?: string, r?: string, x?: string, y?: string, width?: string, height?: string, rx?: string }))"
7
+ :value="[]"
8
+ ></state>
5
9
  </defs>
6
10
  <span aria-hidden="true">
7
11
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false">
@@ -79,6 +79,36 @@
79
79
  }
80
80
  }
81
81
 
82
+ /* A touch target without a bigger button: an invisible hit area, at least the control
83
+ minimum, centred on the button (::before is the anticipatory guide). */
84
+ @media (pointer: coarse) {
85
+ :host {
86
+ position: relative;
87
+ }
88
+
89
+ :host::after {
90
+ content: "";
91
+ position: absolute;
92
+ inset: 50% auto auto 50%;
93
+ inline-size: max(100%, var(--ui-control-min-block-size, 2.75rem));
94
+ block-size: max(100%, var(--ui-control-min-block-size, 2.75rem));
95
+ transform: translate(-50%, -50%);
96
+ }
97
+ }
98
+
99
+ html[data-ui-input-modality="touch"] :host {
100
+ position: relative;
101
+ }
102
+
103
+ html[data-ui-input-modality="touch"] :host::after {
104
+ content: "";
105
+ position: absolute;
106
+ inset: 50% auto auto 50%;
107
+ inline-size: max(100%, var(--ui-control-min-block-size, 2.75rem));
108
+ block-size: max(100%, var(--ui-control-min-block-size, 2.75rem));
109
+ transform: translate(-50%, -50%);
110
+ }
111
+
82
112
  :host-state([size="sm"]) {
83
113
  inline-size: var(--ui-icon-button-size-sm, 1.75rem);
84
114
  block-size: var(--ui-icon-button-size-sm, 1.75rem);
@@ -135,11 +165,24 @@
135
165
  box-shadow: var(--ui-focus-halo);
136
166
  }
137
167
 
168
+ /* Disabled colours fall back to each variant's own; ghost takes only the icon colour. */
138
169
  :host:disabled {
139
- opacity: 0.6;
170
+ opacity: var(--ui-icon-button-disabled-opacity, 0.6);
171
+ color: var(--ui-icon-button-disabled-color, inherit);
140
172
  cursor: not-allowed;
141
173
  }
142
174
 
175
+ :host-state([variant="outline"]):disabled {
176
+ border-color: var(--ui-icon-button-disabled-border, var(--ui-icon-button-border, var(--ui-border-default)));
177
+ background-color: var(--ui-icon-button-disabled-bg, var(--ui-icon-button-outline-bg, var(--ui-surface-default)));
178
+ color: var(--ui-icon-button-disabled-color, var(--ui-icon-button-outline-color, var(--ui-text-primary)));
179
+ }
180
+
181
+ :host-state([variant="solid"]):disabled {
182
+ background-color: var(--ui-icon-button-disabled-bg, var(--ui-icon-button-solid-bg, var(--ui-accent-solid)));
183
+ color: var(--ui-icon-button-disabled-color, var(--ui-icon-button-solid-color, var(--ui-text-on-accent)));
184
+ }
185
+
143
186
  :host {
144
187
  --_icon-button-icon-default: var(--ui-icon-size-md, 1.25rem);
145
188
  }
@@ -14,11 +14,19 @@ export default function controller(host) {
14
14
 
15
15
  const close = (reason, trigger) => {
16
16
  host.state.internalOpen = false;
17
+ lastOpen = false;
17
18
  host.dispatch("close", { open: false, reason, trigger });
18
19
  };
19
20
  const onAnchorClick = (event) => {
20
- host.state.internalOpen = !Boolean(host.state.internalOpen);
21
- if (!host.state.internalOpen) close("action", event.detail === 0 ? "keyboard" : "pointer");
21
+ const trigger = event.detail === 0 ? "keyboard" : "pointer";
22
+ if (host.state.internalOpen) {
23
+ close("action", trigger);
24
+ return;
25
+ }
26
+ host.state.internalOpen = true;
27
+ // Announce the anchor's toggle once, with its real trigger; apply() only announces changes it made.
28
+ lastOpen = true;
29
+ host.dispatch("open", { open: true, reason: "action", trigger });
22
30
  };
23
31
  const ids = createIdResolver(document, () => apply());
24
32
  const setup = () => {
@@ -64,6 +64,13 @@
64
64
  .search {
65
65
  padding: var(--ui-space-3);
66
66
  border-block-end: 1px solid var(--ui-border-default);
67
+ transition: border-color var(--ui-motion-fast) var(--ui-motion-ease), box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
68
+ }
69
+
70
+ /* The search region shows where typing goes, whatever the author put in it. */
71
+ .search:focus-within {
72
+ border-block-end-color: var(--ui-search-shell-focus-color, var(--ui-control-focus));
73
+ box-shadow: inset 0 -1px 0 var(--ui-search-shell-focus-color, var(--ui-control-focus));
67
74
  }
68
75
 
69
76
  :slotted(input[slot="search"]) {
@@ -40,6 +40,13 @@ export default function controller(host) {
40
40
  event.preventDefault();
41
41
  if (host.state.dismissible) dispatchClose("escape", "keyboard");
42
42
  };
43
+ // A search field spends the first Escape clearing itself and the dialog never sees a cancel,
44
+ // so a dismissible shell closes on Escape from anywhere inside it.
45
+ const onKeydown = (event) => {
46
+ if (event.key !== "Escape" || event.defaultPrevented || !host.state.dismissible) return;
47
+ event.preventDefault();
48
+ dispatchClose("escape", "keyboard");
49
+ };
43
50
  const onClick = (event) => {
44
51
  if (host.state.dismissible && event.target === dialog) dispatchClose("light-dismiss", trigger());
45
52
  };
@@ -47,12 +54,14 @@ export default function controller(host) {
47
54
  if (!suppressNativeClose && host.state.internalOpen) dispatchClose("action", trigger());
48
55
  };
49
56
  dialog.addEventListener("cancel", onCancel);
57
+ dialog.addEventListener("keydown", onKeydown);
50
58
  dialog.addEventListener("click", onClick);
51
59
  dialog.addEventListener("close", onClose);
52
60
  return () => {
53
61
  stop();
54
62
  stopTracking();
55
63
  dialog.removeEventListener("cancel", onCancel);
64
+ dialog.removeEventListener("keydown", onKeydown);
56
65
  dialog.removeEventListener("click", onClick);
57
66
  dialog.removeEventListener("close", onClose);
58
67
  closeNative();
@@ -5,7 +5,7 @@
5
5
  <prop name="orientation" type="horizontal | vertical" default="horizontal">orientation token.</prop>
6
6
  <prop name="stretch" type="boolean" default="false">Share the full width of the tab list equally between tabs instead of sizing each to its label.</prop>
7
7
  <state name="internalValue" :value="''"></state>
8
- <state name="tabs" :value="[]"></state>
8
+ <state name="tabs" type="list(object({ id: string, label: string }))" :value="[]"></state>
9
9
  <event name="select" type="object({ value: string, previousValue: string, trigger: keyboard | pointer | programmatic })"></event>
10
10
  </defs>
11
11
  <div>
@@ -7,7 +7,7 @@
7
7
  >Dismiss each message automatically after its duration. Timers pause while the pointer or focus is on a message.</prop>
8
8
  <prop name="duration" type="number" default="5000">Milliseconds an automatically dismissed message stays visible.</prop>
9
9
  <state name="internalOpen" :value="false"></state>
10
- <state name="toasts" :value="[]"></state>
10
+ <state name="toasts" type="list(object({ id: string, message: string, role: alert | status, closing: boolean }))" :value="[]"></state>
11
11
  <event
12
12
  name="close"
13
13
  type="object({ open: boolean, reason: action | timeout | programmatic | light-dismiss | escape, trigger: keyboard | pointer | programmatic })"
@@ -209,11 +209,16 @@
209
209
  flex: none;
210
210
  }
211
211
 
212
+ /* The label spans the row's height and centres its content, so slotted content (a link) can
213
+ stretch to fill the row as its own hit area; the padding tokens remove the inset. */
212
214
  .label {
213
215
  grid-column: 3;
214
216
  grid-row: 1;
217
+ align-self: stretch;
218
+ display: flex;
219
+ align-items: center;
215
220
  min-inline-size: 0;
216
- padding: var(--ui-space-1) var(--ui-space-2);
221
+ padding: var(--ui-tree-label-padding-block, var(--ui-space-1)) var(--ui-tree-label-padding-inline, var(--ui-space-2));
217
222
  }
218
223
 
219
224
  .actions {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ComponentDefinition } from "@nextwebwg/declarative-components";
1
+ import type { ComponentDefinition } from "@nextwebwg/html-next";
2
2
  export declare const definitions: readonly ComponentDefinition[];
3
3
  export declare function register(root?: Document): () => void;
4
4
  export declare const stop: undefined | (() => void);