@threadlabs/looma 0.5.1 → 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 (309) hide show
  1. package/README.md +1 -1
  2. package/components/ui-button/ui-button.html +13 -0
  3. package/components/ui-combobox/ui-combobox.html +12 -4
  4. package/components/ui-dialog/ui-dialog.html +13 -0
  5. package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +1 -1
  6. package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +1 -1
  7. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +6 -2
  8. package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +20 -4
  9. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +8 -4
  10. package/components/ui-form-field/ui-form-field.html +18 -7
  11. package/components/ui-icon/ui-icon.html +5 -1
  12. package/components/ui-icon-button/ui-icon-button.html +30 -0
  13. package/components/ui-popover/ui-popover.js +10 -2
  14. package/components/ui-search-shell/ui-search-shell.html +7 -0
  15. package/components/ui-search-shell/ui-search-shell.js +9 -0
  16. package/components/ui-tabs/ui-tabs.html +1 -1
  17. package/components/ui-toast-region/ui-toast-region.html +1 -1
  18. package/components/ui-tree-item/ui-tree-item.html +6 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +2 -2
  21. package/package.json +2 -2
  22. package/styles/ui-affordance-scope.css +1 -1
  23. package/styles/ui-avatar-group.css +1 -1
  24. package/styles/ui-avatar.css +1 -1
  25. package/styles/ui-badge.css +1 -1
  26. package/styles/ui-button.css +11 -1
  27. package/styles/ui-callout.css +1 -1
  28. package/styles/ui-checkbox.css +1 -1
  29. package/styles/ui-cluster.css +1 -1
  30. package/styles/ui-combobox.css +1 -1
  31. package/styles/ui-container.css +1 -1
  32. package/styles/ui-context-menu.css +1 -1
  33. package/styles/ui-dialog.css +18 -1
  34. package/styles/ui-disclosure.css +1 -1
  35. package/styles/ui-editable.css +1 -1
  36. package/styles/ui-editor-insert-table-grid.css +1 -1
  37. package/styles/ui-editor-mention-menu.css +1 -1
  38. package/styles/ui-editor-slash-menu.css +1 -1
  39. package/styles/ui-editor-table-context-menu.css +1 -1
  40. package/styles/ui-editor-table-overlay.css +1 -1
  41. package/styles/ui-editor-table-toolbar.css +1 -1
  42. package/styles/ui-editor-toolbar.css +1 -1
  43. package/styles/ui-floating-action-button.css +1 -1
  44. package/styles/ui-form-field.css +24 -10
  45. package/styles/ui-grid.css +1 -1
  46. package/styles/ui-icon-button.css +36 -1
  47. package/styles/ui-icon.css +1 -1
  48. package/styles/ui-input.css +1 -1
  49. package/styles/ui-menu-item.css +1 -1
  50. package/styles/ui-menu.css +1 -1
  51. package/styles/ui-popover.css +1 -1
  52. package/styles/ui-radio-group.css +1 -1
  53. package/styles/ui-radio.css +1 -1
  54. package/styles/ui-reel.css +1 -1
  55. package/styles/ui-search-result-row.css +1 -1
  56. package/styles/ui-search-shell.css +11 -2
  57. package/styles/ui-select.css +1 -1
  58. package/styles/ui-separator.css +1 -1
  59. package/styles/ui-sidebar.css +1 -1
  60. package/styles/ui-stack.css +1 -1
  61. package/styles/ui-switch.css +1 -1
  62. package/styles/ui-switcher.css +1 -1
  63. package/styles/ui-tabs.css +1 -1
  64. package/styles/ui-textarea.css +1 -1
  65. package/styles/ui-toast-region.css +1 -1
  66. package/styles/ui-tooltip.css +1 -1
  67. package/styles/ui-top-bar.css +1 -1
  68. package/styles/ui-tree-item.css +10 -2
  69. package/styles/ui-tree.css +1 -1
  70. package/vanilla/UiAffordanceScope.d.ts +1 -1
  71. package/vanilla/UiAffordanceScope.js +2 -2
  72. package/vanilla/UiAvatar.d.ts +1 -1
  73. package/vanilla/UiAvatar.js +2 -2
  74. package/vanilla/UiAvatarGroup.d.ts +1 -1
  75. package/vanilla/UiAvatarGroup.js +2 -2
  76. package/vanilla/UiBadge.d.ts +1 -1
  77. package/vanilla/UiBadge.js +2 -2
  78. package/vanilla/UiButton.d.ts +3 -1
  79. package/vanilla/UiButton.js +3 -3
  80. package/vanilla/UiCallout.d.ts +1 -1
  81. package/vanilla/UiCallout.js +2 -2
  82. package/vanilla/UiCheckbox.d.ts +1 -1
  83. package/vanilla/UiCheckbox.js +2 -2
  84. package/vanilla/UiCluster.d.ts +1 -1
  85. package/vanilla/UiCluster.js +2 -2
  86. package/vanilla/UiCombobox.d.ts +1 -1
  87. package/vanilla/UiCombobox.js +3 -3
  88. package/vanilla/UiContainer.d.ts +1 -1
  89. package/vanilla/UiContainer.js +2 -2
  90. package/vanilla/UiContextMenu.d.ts +1 -1
  91. package/vanilla/UiContextMenu.js +2 -2
  92. package/vanilla/UiDialog.d.ts +1 -1
  93. package/vanilla/UiDialog.js +2 -2
  94. package/vanilla/UiDisclosure.d.ts +1 -1
  95. package/vanilla/UiDisclosure.js +2 -2
  96. package/vanilla/UiEditable.d.ts +1 -1
  97. package/vanilla/UiEditable.js +2 -2
  98. package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
  99. package/vanilla/UiEditorInsertTableGrid.js +3 -3
  100. package/vanilla/UiEditorMentionMenu.d.ts +1 -1
  101. package/vanilla/UiEditorMentionMenu.js +3 -3
  102. package/vanilla/UiEditorSlashMenu.d.ts +1 -1
  103. package/vanilla/UiEditorSlashMenu.js +2 -2
  104. package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
  105. package/vanilla/UiEditorTableContextMenu.js +3 -3
  106. package/vanilla/UiEditorTableOverlay.d.ts +1 -1
  107. package/vanilla/UiEditorTableOverlay.js +3 -3
  108. package/vanilla/UiEditorTableToolbar.d.ts +1 -1
  109. package/vanilla/UiEditorTableToolbar.js +3 -3
  110. package/vanilla/UiEditorToolbar.d.ts +1 -1
  111. package/vanilla/UiEditorToolbar.js +2 -2
  112. package/vanilla/UiFloatingActionButton.d.ts +1 -1
  113. package/vanilla/UiFloatingActionButton.js +2 -2
  114. package/vanilla/UiFormField.d.ts +1 -1
  115. package/vanilla/UiFormField.js +15 -6
  116. package/vanilla/UiGrid.d.ts +1 -1
  117. package/vanilla/UiGrid.js +2 -2
  118. package/vanilla/UiIcon.d.ts +1 -1
  119. package/vanilla/UiIcon.js +3 -3
  120. package/vanilla/UiIconButton.d.ts +1 -1
  121. package/vanilla/UiIconButton.js +2 -2
  122. package/vanilla/UiInput.d.ts +1 -1
  123. package/vanilla/UiInput.js +2 -2
  124. package/vanilla/UiMenu.d.ts +1 -1
  125. package/vanilla/UiMenu.js +2 -2
  126. package/vanilla/UiMenuItem.d.ts +1 -1
  127. package/vanilla/UiMenuItem.js +2 -2
  128. package/vanilla/UiPopover.d.ts +1 -1
  129. package/vanilla/UiPopover.js +2 -2
  130. package/vanilla/UiRadio.d.ts +1 -1
  131. package/vanilla/UiRadio.js +2 -2
  132. package/vanilla/UiRadioGroup.d.ts +1 -1
  133. package/vanilla/UiRadioGroup.js +2 -2
  134. package/vanilla/UiReel.d.ts +1 -1
  135. package/vanilla/UiReel.js +2 -2
  136. package/vanilla/UiSearchResultRow.d.ts +1 -1
  137. package/vanilla/UiSearchResultRow.js +2 -2
  138. package/vanilla/UiSearchShell.d.ts +1 -1
  139. package/vanilla/UiSearchShell.js +2 -2
  140. package/vanilla/UiSelect.d.ts +1 -1
  141. package/vanilla/UiSelect.js +2 -2
  142. package/vanilla/UiSeparator.d.ts +1 -1
  143. package/vanilla/UiSeparator.js +2 -2
  144. package/vanilla/UiSidebar.d.ts +1 -1
  145. package/vanilla/UiSidebar.js +2 -2
  146. package/vanilla/UiStack.d.ts +1 -1
  147. package/vanilla/UiStack.js +2 -2
  148. package/vanilla/UiSwitch.d.ts +1 -1
  149. package/vanilla/UiSwitch.js +2 -2
  150. package/vanilla/UiSwitcher.d.ts +1 -1
  151. package/vanilla/UiSwitcher.js +2 -2
  152. package/vanilla/UiTabs.d.ts +1 -1
  153. package/vanilla/UiTabs.js +3 -3
  154. package/vanilla/UiTextarea.d.ts +1 -1
  155. package/vanilla/UiTextarea.js +2 -2
  156. package/vanilla/UiToastRegion.d.ts +1 -1
  157. package/vanilla/UiToastRegion.js +3 -3
  158. package/vanilla/UiTooltip.d.ts +1 -1
  159. package/vanilla/UiTooltip.js +2 -2
  160. package/vanilla/UiTopBar.d.ts +1 -1
  161. package/vanilla/UiTopBar.js +1 -1
  162. package/vanilla/UiTree.d.ts +1 -1
  163. package/vanilla/UiTree.js +2 -2
  164. package/vanilla/UiTreeItem.d.ts +1 -1
  165. package/vanilla/UiTreeItem.js +2 -2
  166. package/vue/UiAffordanceScope.d.ts +2 -2
  167. package/vue/UiAffordanceScope.vue +92 -73
  168. package/vue/UiAvatar.d.ts +7 -7
  169. package/vue/UiAvatar.vue +145 -105
  170. package/vue/UiAvatarGroup.d.ts +4 -4
  171. package/vue/UiAvatarGroup.vue +134 -118
  172. package/vue/UiBadge.d.ts +4 -4
  173. package/vue/UiBadge.vue +113 -114
  174. package/vue/UiButton.d.ts +10 -6
  175. package/vue/UiButton.vue +289 -248
  176. package/vue/UiCallout.d.ts +2 -2
  177. package/vue/UiCallout.vue +154 -87
  178. package/vue/UiCheckbox.d.ts +14 -10
  179. package/vue/UiCheckbox.vue +228 -162
  180. package/vue/UiCluster.d.ts +2 -2
  181. package/vue/UiCluster.vue +53 -60
  182. package/vue/UiCombobox.d.ts +36 -32
  183. package/vue/UiCombobox.vue +1005 -416
  184. package/vue/UiContainer.d.ts +2 -2
  185. package/vue/UiContainer.vue +48 -51
  186. package/vue/UiContextMenu.d.ts +6 -4
  187. package/vue/UiContextMenu.vue +205 -116
  188. package/vue/UiDialog.d.ts +11 -9
  189. package/vue/UiDialog.vue +287 -212
  190. package/vue/UiDisclosure.d.ts +8 -6
  191. package/vue/UiDisclosure.vue +248 -159
  192. package/vue/UiEditable.d.ts +16 -12
  193. package/vue/UiEditable.vue +325 -205
  194. package/vue/UiEditorInsertTableGrid.d.ts +8 -8
  195. package/vue/UiEditorInsertTableGrid.vue +216 -157
  196. package/vue/UiEditorMentionMenu.d.ts +9 -9
  197. package/vue/UiEditorMentionMenu.vue +265 -222
  198. package/vue/UiEditorSlashMenu.d.ts +7 -7
  199. package/vue/UiEditorSlashMenu.vue +286 -240
  200. package/vue/UiEditorTableContextMenu.d.ts +5 -5
  201. package/vue/UiEditorTableContextMenu.vue +306 -193
  202. package/vue/UiEditorTableOverlay.d.ts +2 -2
  203. package/vue/UiEditorTableOverlay.vue +609 -369
  204. package/vue/UiEditorTableToolbar.d.ts +7 -7
  205. package/vue/UiEditorTableToolbar.vue +443 -268
  206. package/vue/UiEditorToolbar.d.ts +2 -2
  207. package/vue/UiEditorToolbar.vue +134 -121
  208. package/vue/UiFloatingActionButton.d.ts +6 -6
  209. package/vue/UiFloatingActionButton.vue +100 -99
  210. package/vue/UiFormField.d.ts +6 -6
  211. package/vue/UiFormField.vue +112 -80
  212. package/vue/UiGrid.d.ts +2 -2
  213. package/vue/UiGrid.vue +51 -57
  214. package/vue/UiIcon.d.ts +2 -2
  215. package/vue/UiIcon.vue +118 -89
  216. package/vue/UiIconButton.d.ts +11 -11
  217. package/vue/UiIconButton.vue +283 -217
  218. package/vue/UiInput.d.ts +9 -9
  219. package/vue/UiInput.vue +153 -127
  220. package/vue/UiMenu.d.ts +8 -6
  221. package/vue/UiMenu.vue +217 -143
  222. package/vue/UiMenuItem.d.ts +4 -4
  223. package/vue/UiMenuItem.vue +52 -46
  224. package/vue/UiPopover.d.ts +8 -6
  225. package/vue/UiPopover.vue +197 -137
  226. package/vue/UiRadio.d.ts +14 -10
  227. package/vue/UiRadio.vue +183 -117
  228. package/vue/UiRadioGroup.d.ts +14 -12
  229. package/vue/UiRadioGroup.vue +172 -111
  230. package/vue/UiReel.d.ts +3 -3
  231. package/vue/UiReel.vue +77 -77
  232. package/vue/UiSearchResultRow.d.ts +4 -4
  233. package/vue/UiSearchResultRow.vue +124 -115
  234. package/vue/UiSearchShell.d.ts +10 -8
  235. package/vue/UiSearchShell.vue +245 -176
  236. package/vue/UiSelect.d.ts +9 -9
  237. package/vue/UiSelect.vue +162 -134
  238. package/vue/UiSeparator.d.ts +2 -2
  239. package/vue/UiSeparator.vue +22 -27
  240. package/vue/UiSidebar.d.ts +20 -18
  241. package/vue/UiSidebar.vue +312 -224
  242. package/vue/UiStack.d.ts +3 -3
  243. package/vue/UiStack.vue +64 -70
  244. package/vue/UiSwitch.d.ts +12 -8
  245. package/vue/UiSwitch.vue +218 -150
  246. package/vue/UiSwitcher.d.ts +3 -3
  247. package/vue/UiSwitcher.vue +73 -75
  248. package/vue/UiTabs.d.ts +10 -8
  249. package/vue/UiTabs.vue +251 -210
  250. package/vue/UiTextarea.d.ts +11 -11
  251. package/vue/UiTextarea.vue +155 -128
  252. package/vue/UiToastRegion.d.ts +10 -8
  253. package/vue/UiToastRegion.vue +261 -198
  254. package/vue/UiTooltip.d.ts +14 -12
  255. package/vue/UiTooltip.vue +241 -177
  256. package/vue/UiTopBar.vue +51 -42
  257. package/vue/UiTree.d.ts +8 -6
  258. package/vue/UiTree.vue +157 -70
  259. package/vue/UiTreeItem.d.ts +24 -22
  260. package/vue/UiTreeItem.vue +456 -339
  261. package/vue/chunks/UiAffordanceScope.js +9 -16
  262. package/vue/chunks/UiAvatar.js +23 -29
  263. package/vue/chunks/UiAvatarGroup.js +16 -39
  264. package/vue/chunks/UiBadge.js +3 -12
  265. package/vue/chunks/UiButton.js +15 -18
  266. package/vue/chunks/UiCallout.js +8 -17
  267. package/vue/chunks/UiCheckbox.js +37 -40
  268. package/vue/chunks/UiCluster.js +3 -12
  269. package/vue/chunks/UiCombobox.js +224 -266
  270. package/vue/chunks/UiContainer.js +3 -12
  271. package/vue/chunks/UiContextMenu.js +39 -34
  272. package/vue/chunks/UiDialog.js +36 -39
  273. package/vue/chunks/UiDisclosure.js +43 -48
  274. package/vue/chunks/UiEditable.js +55 -57
  275. package/vue/chunks/UiEditorInsertTableGrid.js +55 -73
  276. package/vue/chunks/UiEditorMentionMenu.js +40 -81
  277. package/vue/chunks/UiEditorSlashMenu.js +28 -52
  278. package/vue/chunks/UiEditorTableContextMenu.js +32 -56
  279. package/vue/chunks/UiEditorTableOverlay.js +58 -82
  280. package/vue/chunks/UiEditorTableToolbar.js +61 -85
  281. package/vue/chunks/UiEditorToolbar.js +4 -13
  282. package/vue/chunks/UiFloatingActionButton.js +7 -21
  283. package/vue/chunks/UiFormField.js +15 -12
  284. package/vue/chunks/UiGrid.js +3 -12
  285. package/vue/chunks/UiIcon.js +20 -43
  286. package/vue/chunks/UiIconButton.js +16 -28
  287. package/vue/chunks/UiInput.js +20 -25
  288. package/vue/chunks/UiMenu.js +29 -33
  289. package/vue/chunks/UiMenuItem.js +4 -10
  290. package/vue/chunks/UiPopover.js +28 -29
  291. package/vue/chunks/UiRadio.js +36 -39
  292. package/vue/chunks/UiRadioGroup.js +30 -34
  293. package/vue/chunks/UiReel.js +6 -15
  294. package/vue/chunks/UiSearchResultRow.js +6 -19
  295. package/vue/chunks/UiSearchShell.js +25 -28
  296. package/vue/chunks/UiSelect.js +20 -23
  297. package/vue/chunks/UiSeparator.js +2 -8
  298. package/vue/chunks/UiSidebar.js +39 -44
  299. package/vue/chunks/UiStack.js +6 -15
  300. package/vue/chunks/UiSwitch.js +35 -38
  301. package/vue/chunks/UiSwitcher.js +6 -15
  302. package/vue/chunks/UiTabs.js +47 -85
  303. package/vue/chunks/UiTextarea.js +21 -26
  304. package/vue/chunks/UiToastRegion.js +38 -72
  305. package/vue/chunks/UiTooltip.js +34 -35
  306. package/vue/chunks/UiTopBar.js +1 -1
  307. package/vue/chunks/UiTree.js +20 -15
  308. package/vue/chunks/UiTreeItem.js +85 -102
  309. package/vue/components.css +3994 -3801
@@ -1,418 +1,535 @@
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 * as controllerModule from "../components/ui-tree-item/ui-tree-item.js";
5
-
6
- defineOptions({ inheritAttrs: false });
7
-
8
- const hn = {
9
- 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),
10
- n: (v: unknown): number | undefined => typeof v === "number" && v === v ? v : undefined,
11
- text: (v: unknown): string => v === undefined || v === null ? "" : Array.isArray(v) ? v.map(hn.text).join(" ") : typeof v === "object" ? "" : String(v),
12
- 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),
13
- enumerated: (v: unknown): any => typeof v === "boolean" ? String(v) : hn.attr(v),
14
- call: (fn: string, ...args: unknown[]): any => {
15
- if (fn === "format") {
16
- let index = 1;
17
- return typeof args[0] === "string" ? args[0].replace(/%s/g, () => index < args.length ? hn.text(args[index++]) : "%s") : undefined;
18
- }
19
- const n = args.map(hn.n);
20
- if (n.some((value) => value === undefined)) return undefined;
21
- const v = n as number[];
22
- switch (fn) {
23
- case "abs": return v.length === 1 ? Math.abs(v[0]!) : undefined;
24
- case "round": return v.length === 1 ? Math.round(v[0]!) : undefined;
25
- case "min": return v.length > 0 ? Math.min(...v) : undefined;
26
- case "max": return v.length > 0 ? Math.max(...v) : undefined;
27
- case "clamp": return v.length === 3 ? Math.min(Math.max(v[0]!, v[1]!), v[2]!) : undefined;
28
- }
29
- return undefined;
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-tree-item/ui-tree-item.js'
13
+
14
+ defineOptions({ inheritAttrs: false })
15
+
16
+ const props = withDefaults(
17
+ defineProps<{
18
+ accepts?: string
19
+ container?: boolean
20
+ disabled?: boolean
21
+ dragType?: string
22
+ dropDepth?: number
23
+ dropScope?: string
24
+ expanded?: boolean
25
+ itemId?: string
26
+ label?: string
27
+ selected?: boolean
28
+ sortable?: boolean
29
+ subtreeDepth?: number
30
+ }>(),
31
+ {
32
+ accepts: '',
33
+ container: false,
34
+ disabled: false,
35
+ dragType: 'item',
36
+ dropScope: '',
37
+ expanded: false,
38
+ itemId: '',
39
+ label: '',
40
+ selected: false,
41
+ sortable: false,
30
42
  },
31
- };
32
-
33
- const props = withDefaults(defineProps<{
34
- accepts?: string | null;
35
- container?: boolean | null;
36
- disabled?: boolean | null;
37
- dragType?: string | null;
38
- dropDepth?: number | null;
39
- dropScope?: string | null;
40
- expanded?: boolean | null;
41
- itemId?: string | null;
42
- label?: string | null;
43
- selected?: boolean | null;
44
- sortable?: boolean | null;
45
- subtreeDepth?: number | null;
46
- }>(), {
47
- accepts: "",
48
- container: false,
49
- disabled: false,
50
- dragType: "item",
51
- dropScope: "",
52
- expanded: false,
53
- itemId: "",
54
- label: "",
55
- selected: false,
56
- sortable: false,
57
- });
43
+ )
58
44
  const emit = defineEmits<{
59
- "expand": [detail: { readonly id: string; readonly expanded: boolean; readonly trigger: "keyboard" | "pointer" | "programmatic" }];
60
- }>();
61
- const root = ref<HTMLElement | null>(null);
62
- const refs: Record<string, Element | undefined> = {};
63
- const state_internalExpanded = ref<any>(false);
64
- const state_structuralLevel = ref<any>(1);
65
- const state_tabStop = ref<any>(false);
66
- const state_isContainer = ref<any>(false);
45
+ 'update:expanded': [value: boolean]
46
+ expand: [
47
+ detail: {
48
+ readonly id: string
49
+ readonly expanded: boolean
50
+ readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
51
+ },
52
+ ]
53
+ }>()
54
+
55
+ const root = ref<HTMLElement | null>(null)
56
+ const rowElement = useTemplateRef<HTMLElement>('row')
57
+ const dragHandleElement = useTemplateRef<HTMLElement>('dragHandle')
58
+ const disclosureElement = useTemplateRef<HTMLElement>('disclosure')
59
+ const childrenElement = useTemplateRef<HTMLElement>('children')
60
+ const internalExpanded = ref(false)
61
+ const structuralLevel = ref(1)
62
+ const tabStop = ref(false)
63
+ const isContainer = ref(false)
64
+
65
+ /** The values the styles' :host-state() rules test. */
66
+ const hostState = computed(() =>
67
+ [
68
+ props.selected && 'selected',
69
+ props.disabled && 'disabled',
70
+ ].filter(Boolean).join(' ')
71
+ )
67
72
 
68
73
  /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
69
- const dispatch = (name: string, detail?: unknown): boolean => {
70
- const declared = {"expand":{"bubbles":false,"composed":true,"cancelable":false}} as Record<string, EventInit | undefined>;
74
+ function dispatch(name: string, detail?: unknown): boolean {
75
+ const declared: Record<string, EventInit | undefined> = {
76
+ expand: { bubbles: false, composed: true, cancelable: false },
77
+ }
71
78
  const checks: Record<string, (detail: unknown) => boolean> = {
72
- "expand": (detail: unknown) => (detail !== null && typeof detail === "object" && !Array.isArray(detail) && typeof (detail as Record<string, unknown>)["id"] === "string" && typeof (detail as Record<string, unknown>)["expanded"] === "boolean" && ((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) => ["id","expanded","trigger"].includes(key))),
73
- };
79
+ expand: (detail) =>
80
+ detail !== null && typeof detail === 'object' && !Array.isArray(detail)
81
+ && typeof (detail as Record<string, unknown>)['id'] === 'string'
82
+ && typeof (detail as Record<string, unknown>)['expanded'] === 'boolean'
83
+ && ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
84
+ || (detail as Record<string, unknown>)['trigger'] === 'pointer'
85
+ || (detail as Record<string, unknown>)['trigger'] === 'programmatic')
86
+ && Object.keys(detail as object).every((key) => ['id', 'expanded', 'trigger'].includes(key)),
87
+ }
74
88
  if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
75
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`);
89
+ throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
90
+ }
91
+ const emitEvent = emit as (name: string, detail: unknown) => void
92
+ emitEvent(name, detail)
93
+ if (detail !== null && typeof detail === 'object' && 'expanded' in detail) {
94
+ emitEvent('update:expanded', (detail as Record<string, unknown>)['expanded'])
76
95
  }
77
- (emit as (name: string, detail: unknown) => void)(name, detail);
78
- return root.value?.dispatchEvent(new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail })) ?? true;
79
- };
80
-
81
- /** The resolved values the styles' :host-state() rules test. */
82
- const hostState = computed(() => (["selected","disabled"] as const).flatMap((name) => {
83
- const value = read(name);
84
- const tokens: string[] = hn.t(value) ? [name] : [];
85
- if (typeof value === "string" || typeof value === "number") tokens.push(`${name}=${encodeURIComponent(String(value))}`);
86
- return tokens;
87
- }).join(" "));
96
+ return root.value?.dispatchEvent(
97
+ new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
98
+ ) ?? true
99
+ }
88
100
 
89
101
  function read(name: string): unknown {
90
- if (name === "internalExpanded") return state_internalExpanded.value;
91
- if (name === "structuralLevel") return state_structuralLevel.value;
92
- if (name === "tabStop") return state_tabStop.value;
93
- if (name === "isContainer") return state_isContainer.value;
94
- return (props as Record<string, unknown>)[name];
102
+ if (name === 'internalExpanded') return internalExpanded.value
103
+ if (name === 'structuralLevel') return structuralLevel.value
104
+ if (name === 'tabStop') return tabStop.value
105
+ if (name === 'isContainer') return isContainer.value
106
+ return (props as Record<string, unknown>)[name]
95
107
  }
96
108
 
97
109
  function write(name: string, value: unknown): boolean {
98
- if (name === "internalExpanded") { state_internalExpanded.value = value; return true; }
99
- if (name === "structuralLevel") { state_structuralLevel.value = value; return true; }
100
- if (name === "tabStop") { state_tabStop.value = value; return true; }
101
- if (name === "isContainer") { state_isContainer.value = value; return true; }
102
- throw new TypeError(`Only declared state is writable; \`${name}\` is not.`);
110
+ if (name === 'internalExpanded') {
111
+ internalExpanded.value = value as never
112
+ return true
113
+ }
114
+ if (name === 'structuralLevel') {
115
+ structuralLevel.value = value as never
116
+ return true
117
+ }
118
+ if (name === 'tabStop') {
119
+ tabStop.value = value as never
120
+ return true
121
+ }
122
+ if (name === 'isContainer') {
123
+ isContainer.value = value as never
124
+ return true
125
+ }
126
+ throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
103
127
  }
104
128
 
105
- const stops: Array<() => void> = [];
129
+ const stops: Array<() => void> = []
106
130
  const host = {
107
- get element(): Element { return root.value as Element; },
131
+ get element(): Element {
132
+ return root.value as Element
133
+ },
108
134
  state: new Proxy({} as Record<string, unknown>, {
109
- get: (_target, name) => typeof name === "string" ? read(name) : undefined,
110
- set: (_target, name, value) => typeof name === "string" && write(name, value),
135
+ get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
136
+ set: (_target, name, value) => typeof name === 'string' && write(name, value),
111
137
  }),
112
- refs: refs as Readonly<Record<string, Element>>,
138
+ refs: {
139
+ get row(): Element {
140
+ return rowElement.value as Element
141
+ },
142
+ get dragHandle(): Element {
143
+ return dragHandleElement.value as Element
144
+ },
145
+ get disclosure(): Element {
146
+ return disclosureElement.value as Element
147
+ },
148
+ get children(): Element {
149
+ return childrenElement.value as Element
150
+ },
151
+ } as Readonly<Record<string, Element>>,
113
152
  elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
114
153
  get: (_target, name) => {
115
- if (typeof name !== "string" || root.value === null) return undefined;
116
- const form = root.value instanceof HTMLFormElement ? root.value : root.value.querySelector("form");
117
- return form?.elements.namedItem(name) ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined;
154
+ if (typeof name !== 'string' || root.value === null) return undefined
155
+ const form = root.value instanceof HTMLFormElement
156
+ ? root.value
157
+ : root.value.querySelector('form')
158
+ return form?.elements.namedItem(name)
159
+ ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
118
160
  },
119
161
  }),
120
162
  signal<T>(initialValue: T) {
121
- const value = shallowRef(initialValue);
163
+ const value = shallowRef(initialValue)
122
164
  return {
123
165
  get: (): T => value.value,
124
- set: (next: T): void => { if (!Object.is(value.value, next)) value.value = next; },
125
- update: (next: (current: T) => T): void => { const updated = next(value.value); if (!Object.is(value.value, updated)) value.value = updated; },
126
- };
166
+ set: (next: T): void => {
167
+ if (!Object.is(value.value, next)) value.value = next
168
+ },
169
+ update: (next: (current: T) => T): void => {
170
+ const updated = next(value.value)
171
+ if (!Object.is(value.value, updated)) value.value = updated
172
+ },
173
+ }
127
174
  },
128
175
  computed<T>(compute: () => T) {
129
- const value = computed(compute);
130
- return { get: (): T => value.value };
176
+ const value = computed(compute)
177
+ return { get: (): T => value.value }
131
178
  },
132
179
  effect(run: () => void | (() => void)): () => void {
133
180
  const stop = watchEffect((onCleanup) => {
134
- const cleanup = run();
135
- if (typeof cleanup === "function") onCleanup(cleanup);
136
- }, { flush: "post" });
137
- stops.push(stop);
138
- return stop;
181
+ const cleanup = run()
182
+ if (typeof cleanup === 'function') onCleanup(cleanup)
183
+ }, { flush: 'post' })
184
+ stops.push(stop)
185
+ return stop
139
186
  },
140
187
  on(event: string, listener: EventListener): () => void {
141
- const element = root.value;
142
- element?.addEventListener(event, listener);
143
- const off = (): void => element?.removeEventListener(event, listener);
144
- stops.push(off);
145
- return off;
188
+ const element = root.value
189
+ element?.addEventListener(event, listener)
190
+ const off = (): void => element?.removeEventListener(event, listener)
191
+ stops.push(off)
192
+ return off
146
193
  },
147
194
  dispatch,
148
- };
195
+ }
149
196
 
150
- let cleanup: void | (() => void);
151
- let ready: Promise<void> | undefined;
197
+ let cleanup: void | (() => void)
198
+ let ready: Promise<void> | undefined
152
199
  onMounted(() => {
153
- ready = Promise.resolve(controllerModule.default(host as never)).then((result) => { cleanup = result; });
154
- });
200
+ ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
201
+ cleanup = result
202
+ })
203
+ })
155
204
  onBeforeUnmount(() => {
156
- for (const stop of stops.splice(0)) stop();
157
- if (typeof cleanup === "function") cleanup();
158
- });
205
+ for (const stop of stops.splice(0)) stop()
206
+ if (typeof cleanup === 'function') cleanup()
207
+ })
159
208
  </script>
160
209
 
161
210
  <template>
162
- <div data-component="ui-tree-item" role="treeitem" v-bind="$attrs" :aria-label="hn.enumerated(props.label)" :aria-level="hn.enumerated(state_structuralLevel)" :aria-selected="hn.enumerated(props.selected)" :aria-disabled="hn.enumerated(props.disabled)" :data-item-id="hn.attr(props.itemId)" :data-drag-type="hn.attr(props.dragType)" :data-drop-scope="hn.attr(props.dropScope)" :data-accepts="hn.attr(props.accepts)" :data-drop-depth="hn.attr(props.dropDepth)" :data-subtree-depth="hn.attr(props.subtreeDepth)" :data-ui-tree-item-state="hostState || undefined" ref="root"><div class="row" :ref="(element) => { refs['row'] = element as Element }"><template v-if="hn.t((hn.t(props.sortable) && hn.t(!hn.t(props.disabled))))"><button class="drag-handle" type="button" draggable="true" :aria-label="hn.enumerated(hn.call('format', 'Drag %s to reorder', props.label))" :ref="(element) => { refs['dragHandle'] = element as Element }"><svg aria-hidden="true" focusable="false" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="12" r="1"></circle><circle cx="9" cy="5" r="1"></circle><circle cx="9" cy="19" r="1"></circle><circle cx="15" cy="12" r="1"></circle><circle cx="15" cy="5" r="1"></circle><circle cx="15" cy="19" r="1"></circle></svg></button></template><button class="disclosure" type="button" :disabled="hn.attr(props.disabled)" :hidden="hn.attr(!hn.t(state_isContainer))" :ref="(element) => { refs['disclosure'] = element as Element }"><span class="disclosure-icon" aria-hidden="true"></span></button><span class="leading"><slot name="leading"></slot></span><span class="label"><slot name="label">{{ hn.text(props.label) }}</slot></span><span class="actions"><slot name="actions"></slot></span><span class="drop-indicator row-drop-indicator" aria-hidden="true"></span></div><div class="children" role="group" :hidden="hn.attr(!hn.t((hn.t(state_isContainer) && hn.t(state_internalExpanded))))" :ref="(element) => { refs['children'] = element as Element }"><slot></slot></div><span class="drop-indicator subtree-drop-indicator" aria-hidden="true"></span></div>
211
+ <div
212
+ data-component="ui-tree-item"
213
+ role="treeitem"
214
+ v-bind="$attrs"
215
+ :aria-label="label"
216
+ :aria-level="structuralLevel"
217
+ :aria-selected="selected"
218
+ :aria-disabled="disabled"
219
+ :data-item-id="itemId"
220
+ :data-drag-type="dragType"
221
+ :data-drop-scope="dropScope"
222
+ :data-accepts="accepts"
223
+ :data-drop-depth="dropDepth"
224
+ :data-subtree-depth="subtreeDepth"
225
+ :data-ui-tree-item-state="hostState || undefined"
226
+ ref="root"
227
+ >
228
+ <div class="row" ref="row">
229
+ <button
230
+ v-if="sortable && !disabled"
231
+ class="drag-handle"
232
+ type="button"
233
+ draggable="true"
234
+ :aria-label="`Drag ${label} to reorder`"
235
+ ref="dragHandle"
236
+ >
237
+ <svg
238
+ aria-hidden="true"
239
+ focusable="false"
240
+ viewBox="0 0 24 24"
241
+ fill="none"
242
+ stroke="currentColor"
243
+ stroke-width="2"
244
+ stroke-linecap="round"
245
+ stroke-linejoin="round"
246
+ >
247
+ <circle cx="9" cy="12" r="1"></circle>
248
+ <circle cx="9" cy="5" r="1"></circle>
249
+ <circle cx="9" cy="19" r="1"></circle>
250
+ <circle cx="15" cy="12" r="1"></circle>
251
+ <circle cx="15" cy="5" r="1"></circle>
252
+ <circle cx="15" cy="19" r="1"></circle>
253
+ </svg>
254
+ </button>
255
+ <button
256
+ class="disclosure"
257
+ type="button"
258
+ :disabled="disabled"
259
+ :hidden="!isContainer"
260
+ ref="disclosure"
261
+ >
262
+ <span class="disclosure-icon" aria-hidden="true"></span>
263
+ </button>
264
+ <span class="leading"><slot name="leading" /></span>
265
+ <span class="label"><slot name="label">{{ label }}</slot></span>
266
+ <span class="actions"><slot name="actions" /></span>
267
+ <span class="drop-indicator row-drop-indicator" aria-hidden="true"></span>
268
+ </div>
269
+ <div class="children" role="group" :hidden="!(isContainer && internalExpanded)" ref="children">
270
+ <slot />
271
+ </div>
272
+ <span class="drop-indicator subtree-drop-indicator" aria-hidden="true"></span>
273
+ </div>
163
274
  </template>
164
275
 
165
276
  <style scoped>
166
277
  [data-component~="ui-tree-item"] {
167
- --_tree-row-min-height: 32px;
278
+ --_tree-row-min-height: 32px;
168
279
 
169
- position: relative;
170
- display: block;
171
- min-inline-size: 0;
172
- margin-inline-start: calc(var(--ui-tree-item-depth, 0) * var(--ui-tree-indent, 16px));
173
- }
280
+ position: relative;
281
+ display: block;
282
+ min-inline-size: 0;
283
+ margin-inline-start: calc(var(--ui-tree-item-depth, 0) * var(--ui-tree-indent, 16px));
284
+ }
174
285
 
175
- .row {
176
- position: relative;
177
- display: grid;
178
- grid-template-columns: 20px auto minmax(0, 1fr) auto;
179
- align-items: center;
180
- min-block-size: var(--ui-tree-row-min-height, var(--_tree-row-min-height));
181
- min-inline-size: 0;
182
- font-size: var(--ui-tree-font-size, var(--ui-font-size-ui, 0.9375rem));
183
- border-radius: var(--ui-radius-md);
184
- color: var(--ui-text-secondary);
185
- transition:
186
- background-color var(--ui-motion-fast) var(--ui-motion-ease),
187
- color var(--ui-motion-fast) var(--ui-motion-ease),
188
- opacity var(--ui-motion-fast) var(--ui-motion-ease),
189
- box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
190
- min-block-size var(--ui-motion-base) var(--ui-motion-ease);
191
- }
286
+ .row {
287
+ position: relative;
288
+ display: grid;
289
+ grid-template-columns: 20px auto minmax(0, 1fr) auto;
290
+ align-items: center;
291
+ min-block-size: var(--ui-tree-row-min-height, var(--_tree-row-min-height));
292
+ min-inline-size: 0;
293
+ font-size: var(--ui-tree-font-size, var(--ui-font-size-ui, 0.9375rem));
294
+ border-radius: var(--ui-radius-md);
295
+ color: var(--ui-text-secondary);
296
+ transition:
297
+ background-color var(--ui-motion-fast) var(--ui-motion-ease),
298
+ color var(--ui-motion-fast) var(--ui-motion-ease),
299
+ opacity var(--ui-motion-fast) var(--ui-motion-ease),
300
+ box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
301
+ min-block-size var(--ui-motion-base) var(--ui-motion-ease);
302
+ }
192
303
 
193
- .row:hover,
194
- [data-component~="ui-tree-item"][data-ui-tree-item-state~="selected"] .row,
195
- .row:focus-within {
196
- color: var(--ui-text-primary);
197
- background: var(--ui-surface-muted);
198
- }
304
+ .row:hover,
305
+ [data-component~="ui-tree-item"][data-ui-tree-item-state~="selected"] .row,
306
+ .row:focus-within {
307
+ color: var(--ui-text-primary);
308
+ background: var(--ui-surface-muted);
309
+ }
199
310
 
200
- [data-component~="ui-tree-item"][data-ui-tree-item-state~="disabled"] .row {
201
- opacity: 0.55;
202
- }
311
+ [data-component~="ui-tree-item"][data-ui-tree-item-state~="disabled"] .row {
312
+ opacity: 0.55;
313
+ }
203
314
 
204
- [data-component~="ui-tree-item"][data-dragging] .row {
205
- opacity: 0.42;
206
- }
315
+ [data-component~="ui-tree-item"][data-dragging] .row {
316
+ opacity: 0.42;
317
+ }
207
318
 
208
- [data-component~="ui-tree-item"]:focus {
209
- outline: none;
210
- }
319
+ [data-component~="ui-tree-item"]:focus {
320
+ outline: none;
321
+ }
211
322
 
212
- [data-component~="ui-tree-item"]:focus-visible .row {
213
- box-shadow: 0 0 0 2px var(--ui-focus-ring);
214
- }
323
+ [data-component~="ui-tree-item"]:focus-visible .row {
324
+ box-shadow: 0 0 0 2px var(--ui-focus-ring);
325
+ }
215
326
 
216
- [data-component~="ui-tree-item"][data-drop-position="inside"] .row {
217
- background: var(--ui-accent-subtle);
218
- box-shadow: inset 0 0 0 1px var(--ui-tree-drop-color, var(--ui-accent-solid));
219
- }
327
+ [data-component~="ui-tree-item"][data-drop-position="inside"] .row {
328
+ background: var(--ui-accent-subtle);
329
+ box-shadow: inset 0 0 0 1px var(--ui-tree-drop-color, var(--ui-accent-solid));
330
+ }
220
331
 
221
- .disclosure,
222
- .disclosure-spacer {
223
- grid-column: 1;
224
- grid-row: 1;
225
- inline-size: 20px;
226
- block-size: 28px;
227
- }
332
+ .disclosure,
333
+ .disclosure-spacer {
334
+ grid-column: 1;
335
+ grid-row: 1;
336
+ inline-size: 20px;
337
+ block-size: 28px;
338
+ }
228
339
 
229
- .disclosure {
230
- display: grid;
231
- place-items: center;
232
- padding: 0;
233
- color: var(--ui-text-muted);
234
- background: transparent;
235
- border: 0;
236
- border-radius: var(--ui-radius-sm);
237
- cursor: pointer;
238
- }
340
+ .disclosure {
341
+ display: grid;
342
+ place-items: center;
343
+ padding: 0;
344
+ color: var(--ui-text-muted);
345
+ background: transparent;
346
+ border: 0;
347
+ border-radius: var(--ui-radius-sm);
348
+ cursor: pointer;
349
+ }
239
350
 
240
- .disclosure[hidden] {
241
- display: none;
242
- }
351
+ .disclosure[hidden] {
352
+ display: none;
353
+ }
243
354
 
244
- .disclosure:hover {
245
- color: var(--ui-text-primary);
246
- background: var(--ui-surface-elevated);
247
- }
355
+ .disclosure:hover {
356
+ color: var(--ui-text-primary);
357
+ background: var(--ui-surface-elevated);
358
+ }
248
359
 
249
- .disclosure-icon {
250
- display: grid;
251
- place-items: center;
252
- inline-size: 14px;
253
- block-size: 14px;
254
- transform: rotate(-90deg);
255
- transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
256
- }
360
+ .disclosure-icon {
361
+ display: grid;
362
+ place-items: center;
363
+ inline-size: 14px;
364
+ block-size: 14px;
365
+ transform: rotate(-90deg);
366
+ transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
367
+ }
257
368
 
258
- .disclosure-icon::before {
259
- display: block;
260
- inline-size: 0.45rem;
261
- block-size: 0.45rem;
262
- border-inline-end: 2px solid currentColor;
263
- border-block-end: 2px solid currentColor;
264
- content: "";
265
- /* A chevron's ink sits below its box centre; lift it so it centres optically (in either rotation). */
266
- transform: translateY(-20%) rotate(45deg);
267
- }
369
+ .disclosure-icon::before {
370
+ display: block;
371
+ inline-size: 0.45rem;
372
+ block-size: 0.45rem;
373
+ border-inline-end: 2px solid currentColor;
374
+ border-block-end: 2px solid currentColor;
375
+ content: "";
376
+ /* A chevron's ink sits below its box centre; lift it so it centres optically (in either rotation). */
377
+ transform: translateY(-20%) rotate(45deg);
378
+ }
268
379
 
269
- [data-component~="ui-tree-item"][aria-expanded="true"] .disclosure-icon {
270
- transform: rotate(0deg);
271
- }
380
+ [data-component~="ui-tree-item"][aria-expanded="true"] .disclosure-icon {
381
+ transform: rotate(0deg);
382
+ }
272
383
 
273
- /* Lucide grip-vertical, filling the handle as in Looma 0.2. */
274
- .drag-handle svg {
275
- display: block;
276
- inline-size: 100%;
277
- block-size: 100%;
278
- }
384
+ /* Lucide grip-vertical, filling the handle as in Looma 0.2. */
385
+ .drag-handle svg {
386
+ display: block;
387
+ inline-size: 100%;
388
+ block-size: 100%;
389
+ }
279
390
 
280
- /* Slotted content is outside this scope, so :has() cannot see it; hide only a truly empty slot. */
281
- .leading {
282
- display: inline-grid;
283
- place-items: center;
284
- grid-column: 2;
285
- grid-row: 1;
286
- inline-size: 1em;
287
- block-size: 1em;
288
- margin-inline-start: var(--ui-space-1);
289
- color: var(--ui-text-muted);
290
- }
391
+ /* Slotted content is outside this scope, so :has() cannot see it; hide only a truly empty slot. */
392
+ .leading {
393
+ display: inline-grid;
394
+ place-items: center;
395
+ grid-column: 2;
396
+ grid-row: 1;
397
+ inline-size: 1em;
398
+ block-size: 1em;
399
+ margin-inline-start: var(--ui-space-1);
400
+ color: var(--ui-text-muted);
401
+ }
291
402
 
292
- .leading:empty {
293
- display: none;
294
- }
403
+ .leading:empty {
404
+ display: none;
405
+ }
295
406
 
296
- /* Icons match the label's size (as in Knit's tree): an unsized SVG would otherwise render 300×150. */
297
- :slotted(svg),
298
- :slotted(img) {
299
- display: block;
300
- inline-size: 1em;
301
- block-size: 1em;
302
- flex: none;
303
- }
407
+ /* Icons match the label's size (as in Knit's tree): an unsized SVG would otherwise render 300×150. */
408
+ :slotted(svg),
409
+ :slotted(img) {
410
+ display: block;
411
+ inline-size: 1em;
412
+ block-size: 1em;
413
+ flex: none;
414
+ }
304
415
 
305
- .label {
306
- grid-column: 3;
307
- grid-row: 1;
308
- min-inline-size: 0;
309
- padding: var(--ui-space-1) var(--ui-space-2);
310
- }
416
+ /* The label spans the row's height and centres its content, so slotted content (a link) can
417
+ stretch to fill the row as its own hit area; the padding tokens remove the inset. */
418
+ .label {
419
+ grid-column: 3;
420
+ grid-row: 1;
421
+ align-self: stretch;
422
+ display: flex;
423
+ align-items: center;
424
+ min-inline-size: 0;
425
+ padding: var(--ui-tree-label-padding-block, var(--ui-space-1))
426
+ var(--ui-tree-label-padding-inline, var(--ui-space-2));
427
+ }
311
428
 
312
- .actions {
313
- grid-column: 4;
314
- grid-row: 1;
315
- display: inline-flex;
316
- align-items: center;
317
- min-inline-size: 0;
318
- }
429
+ .actions {
430
+ grid-column: 4;
431
+ grid-row: 1;
432
+ display: inline-flex;
433
+ align-items: center;
434
+ min-inline-size: 0;
435
+ }
319
436
 
320
- .drag-handle {
321
- position: absolute;
322
- z-index: 2;
323
- inset-block-start: 50%;
324
- inset-inline-start: -22px;
325
- inline-size: 20px;
326
- block-size: 32px;
327
- display: grid;
328
- place-items: center;
329
- padding: 7px 3px;
330
- color: var(--ui-text-muted);
331
- background: var(--ui-surface-elevated);
332
- border: 1px solid transparent;
333
- border-radius: var(--ui-radius-sm);
334
- cursor: grab;
335
- /* Hidden until the row is hovered, but always hittable: the handle sits outside the row, and moving
336
- the pointer onto it must not hide it on the way. */
337
- opacity: 0;
338
- transform: translateY(-50%);
339
- transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
340
- }
437
+ .drag-handle {
438
+ position: absolute;
439
+ z-index: 2;
440
+ inset-block-start: 50%;
441
+ inset-inline-start: -22px;
442
+ inline-size: 20px;
443
+ block-size: 32px;
444
+ display: grid;
445
+ place-items: center;
446
+ padding: 7px 3px;
447
+ color: var(--ui-text-muted);
448
+ background: var(--ui-surface-elevated);
449
+ border: 1px solid transparent;
450
+ border-radius: var(--ui-radius-sm);
451
+ cursor: grab;
452
+ /* Hidden until the row is hovered, but always hittable: the handle sits outside the row, and moving
453
+ the pointer onto it must not hide it on the way. */
454
+ opacity: 0;
455
+ transform: translateY(-50%);
456
+ transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
457
+ }
341
458
 
342
- .row:hover .drag-handle,
343
- .drag-handle:hover,
344
- .drag-handle:focus-visible,
345
- [data-component~="ui-tree-item"][data-dragging] .drag-handle {
346
- opacity: 1;
347
- }
459
+ .row:hover .drag-handle,
460
+ .drag-handle:hover,
461
+ .drag-handle:focus-visible,
462
+ [data-component~="ui-tree-item"][data-dragging] .drag-handle {
463
+ opacity: 1;
464
+ }
348
465
 
349
- .drag-handle:active {
350
- cursor: grabbing;
351
- }
466
+ .drag-handle:active {
467
+ cursor: grabbing;
468
+ }
352
469
 
353
- .drop-indicator {
354
- position: absolute;
355
- z-index: 3;
356
- inset-inline: 1px;
357
- display: none;
358
- block-size: 2px;
359
- border-radius: 999px;
360
- background: var(--ui-tree-drop-color, var(--ui-accent-solid));
361
- pointer-events: none;
362
- }
470
+ .drop-indicator {
471
+ position: absolute;
472
+ z-index: 3;
473
+ inset-inline: 1px;
474
+ display: none;
475
+ block-size: 2px;
476
+ border-radius: 999px;
477
+ background: var(--ui-tree-drop-color, var(--ui-accent-solid));
478
+ pointer-events: none;
479
+ }
363
480
 
364
- .drop-indicator::before,
365
- .drop-indicator::after {
366
- content: "";
367
- position: absolute;
368
- inset-block-start: 50%;
369
- inline-size: 7px;
370
- block-size: 7px;
371
- border: 2px solid var(--ui-tree-drop-color, var(--ui-accent-solid));
372
- border-radius: 999px;
373
- background: var(--ui-surface-elevated);
374
- transform: translateY(-50%);
375
- }
481
+ .drop-indicator::before,
482
+ .drop-indicator::after {
483
+ content: "";
484
+ position: absolute;
485
+ inset-block-start: 50%;
486
+ inline-size: 7px;
487
+ block-size: 7px;
488
+ border: 2px solid var(--ui-tree-drop-color, var(--ui-accent-solid));
489
+ border-radius: 999px;
490
+ background: var(--ui-surface-elevated);
491
+ transform: translateY(-50%);
492
+ }
376
493
 
377
- .drop-indicator::before {
378
- inset-inline-start: -1px;
379
- }
380
- .drop-indicator::after {
381
- inset-inline-end: -1px;
382
- }
494
+ .drop-indicator::before {
495
+ inset-inline-start: -1px;
496
+ }
497
+ .drop-indicator::after {
498
+ inset-inline-end: -1px;
499
+ }
383
500
 
384
- [data-component~="ui-tree-item"][data-drop-position="before"] .row-drop-indicator {
385
- display: block;
386
- inset-block-start: -1px;
387
- }
501
+ [data-component~="ui-tree-item"][data-drop-position="before"] .row-drop-indicator {
502
+ display: block;
503
+ inset-block-start: -1px;
504
+ }
388
505
 
389
- [data-component~="ui-tree-item"][data-drop-position="after"] .subtree-drop-indicator {
390
- display: block;
391
- inset-block-end: -1px;
392
- }
506
+ [data-component~="ui-tree-item"][data-drop-position="after"] .subtree-drop-indicator {
507
+ display: block;
508
+ inset-block-end: -1px;
509
+ }
393
510
 
394
- .children[hidden] {
395
- display: none;
396
- }
511
+ .children[hidden] {
512
+ display: none;
513
+ }
397
514
 
398
- html[data-ui-input-modality="touch"] [data-component~="ui-tree-item"] {
399
- --_tree-row-min-height: 44px;
400
- }
515
+ html[data-ui-input-modality="touch"] [data-component~="ui-tree-item"] {
516
+ --_tree-row-min-height: 44px;
517
+ }
401
518
 
402
- html[data-ui-input-modality="touch"] [data-component~="ui-tree-item"] .drag-handle {
403
- display: none;
404
- }
519
+ html[data-ui-input-modality="touch"] [data-component~="ui-tree-item"] .drag-handle {
520
+ display: none;
521
+ }
405
522
 
406
- @media (prefers-reduced-motion: reduce) {
407
- .row,
408
- .disclosure-icon,
409
- .drag-handle {
410
- transition: none;
411
- }
412
- }
523
+ @media (prefers-reduced-motion: reduce) {
524
+ .row,
525
+ .disclosure-icon,
526
+ .drag-handle {
527
+ transition: none;
528
+ }
529
+ }
413
530
 
414
- /* A component that sets its display still honours the hidden attribute on its root. */
415
- [data-component~="ui-tree-item"][hidden] {
416
- display: none;
417
- }
531
+ /* A component that sets its display still honours the hidden attribute on its root. */
532
+ [data-component~="ui-tree-item"][hidden] {
533
+ display: none;
534
+ }
418
535
  </style>