@threadlabs/looma 0.1.22 → 0.1.23

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 (248) hide show
  1. package/dist/{chunk-NIPNHZ5W.js → chunk-GDMQKT5F.js} +63 -31
  2. package/dist/{chunk-SZJQ3NPX.js → chunk-TL4FIE7X.js} +4 -8
  3. package/dist/cjs/{index-D07f6BOw.js → index-BHG9Rpil.js} +33 -0
  4. package/dist/cjs/loader.cjs.js +2 -2
  5. package/dist/cjs/looma.cjs.js +2 -2
  6. package/dist/cjs/{manager-C9j3HZay.js → manager-Ce25WRtl.js} +6 -7
  7. package/dist/cjs/ui-affordance-scope.cjs.entry.js +1 -1
  8. package/dist/cjs/ui-avatar-group.cjs.entry.js +1 -1
  9. package/dist/cjs/ui-avatar.cjs.entry.js +1 -1
  10. package/dist/cjs/ui-badge.cjs.entry.js +1 -1
  11. package/dist/cjs/ui-button.cjs.entry.js +16 -5
  12. package/dist/cjs/ui-checkbox.cjs.entry.js +1 -1
  13. package/dist/cjs/ui-combobox.cjs.entry.js +541 -0
  14. package/dist/cjs/ui-context-menu.cjs.entry.js +3 -3
  15. package/dist/cjs/ui-dialog.cjs.entry.js +3 -3
  16. package/dist/cjs/ui-disclosure.cjs.entry.js +2 -2
  17. package/dist/cjs/ui-floating-action-button.cjs.entry.js +2 -2
  18. package/dist/cjs/ui-form-field.cjs.entry.js +3 -3
  19. package/dist/cjs/ui-icon-button.cjs.entry.js +2 -2
  20. package/dist/cjs/ui-input.cjs.entry.js +11 -6
  21. package/dist/cjs/ui-menu-item.cjs.entry.js +2 -2
  22. package/dist/cjs/ui-menu.cjs.entry.js +3 -3
  23. package/dist/cjs/ui-popover.cjs.entry.js +3 -3
  24. package/dist/cjs/ui-radio-group.cjs.entry.js +2 -2
  25. package/dist/cjs/ui-radio.cjs.entry.js +3 -3
  26. package/dist/cjs/ui-search-result-row.cjs.entry.js +2 -2
  27. package/dist/cjs/ui-search-shell.cjs.entry.js +2 -2
  28. package/dist/cjs/ui-select.cjs.entry.js +15 -7
  29. package/dist/cjs/ui-switch.cjs.entry.js +3 -3
  30. package/dist/cjs/ui-tabs.cjs.entry.js +2 -2
  31. package/dist/cjs/ui-textarea.cjs.entry.js +10 -6
  32. package/dist/cjs/ui-toast-region.cjs.entry.js +2 -2
  33. package/dist/cjs/ui-tooltip.cjs.entry.js +52 -16
  34. package/dist/cjs/ui-top-bar.cjs.entry.js +2 -2
  35. package/dist/cjs/ui-tree-item.cjs.entry.js +7 -3
  36. package/dist/cjs/ui-tree.cjs.entry.js +81 -9
  37. package/dist/collection/collection-manifest.json +1 -0
  38. package/dist/collection/components/ui-button/ui-button.css +36 -26
  39. package/dist/collection/components/ui-button/ui-button.js +14 -3
  40. package/dist/collection/components/ui-combobox/ui-combobox.css +24 -0
  41. package/dist/collection/components/ui-combobox/ui-combobox.js +973 -0
  42. package/dist/collection/components/ui-context-menu/ui-context-menu.js +1 -1
  43. package/dist/collection/components/ui-dialog/ui-dialog.js +1 -1
  44. package/dist/collection/components/ui-disclosure/ui-disclosure.js +1 -1
  45. package/dist/collection/components/ui-floating-action-button/ui-floating-action-button.js +1 -1
  46. package/dist/collection/components/ui-form-field/ui-form-field.css +4 -0
  47. package/dist/collection/components/ui-form-field/ui-form-field.js +1 -1
  48. package/dist/collection/components/ui-icon-button/ui-icon-button.js +1 -1
  49. package/dist/collection/components/ui-input/ui-input.css +8 -6
  50. package/dist/collection/components/ui-input/ui-input.js +11 -7
  51. package/dist/collection/components/ui-menu/ui-menu.js +1 -1
  52. package/dist/collection/components/ui-menu-item/ui-menu-item.js +1 -1
  53. package/dist/collection/components/ui-popover/ui-popover.js +1 -1
  54. package/dist/collection/components/ui-radio/ui-radio.js +2 -2
  55. package/dist/collection/components/ui-radio-group/ui-radio-group.js +1 -1
  56. package/dist/collection/components/ui-search-result-row/ui-search-result-row.js +1 -1
  57. package/dist/collection/components/ui-search-shell/ui-search-shell.js +1 -1
  58. package/dist/collection/components/ui-select/ui-select.css +8 -6
  59. package/dist/collection/components/ui-select/ui-select.js +17 -11
  60. package/dist/collection/components/ui-switch/ui-switch.js +2 -2
  61. package/dist/collection/components/ui-tabs/ui-tabs.js +1 -1
  62. package/dist/collection/components/ui-textarea/ui-textarea.css +7 -6
  63. package/dist/collection/components/ui-textarea/ui-textarea.js +10 -7
  64. package/dist/collection/components/ui-toast-region/ui-toast-region.js +1 -1
  65. package/dist/collection/components/ui-tooltip/ui-tooltip.js +102 -15
  66. package/dist/collection/components/ui-top-bar/ui-top-bar.js +1 -1
  67. package/dist/collection/components/ui-tree/ui-tree.js +100 -8
  68. package/dist/collection/components/ui-tree-item/ui-tree-item.js +44 -2
  69. package/dist/collection/field/combobox.js +4 -0
  70. package/dist/collection/field/valibot.js +5 -0
  71. package/dist/collection/field/validation.js +62 -0
  72. package/dist/collection/overlay/manager.js +6 -7
  73. package/dist/components/index.d.ts +2 -0
  74. package/dist/components/index.js +1 -1
  75. package/dist/components/p-Bh_1GxOD.js +1 -0
  76. package/dist/components/p-C-0syqXZ.js +1 -0
  77. package/dist/components/p-CaietZcq.js +1 -0
  78. package/dist/components/p-DHd18bK7.js +1 -0
  79. package/dist/components/ui-affordance-scope.js +1 -1
  80. package/dist/components/ui-avatar-group.js +1 -1
  81. package/dist/components/ui-avatar.js +1 -1
  82. package/dist/components/ui-badge.js +1 -1
  83. package/dist/components/ui-button.js +1 -1
  84. package/dist/components/ui-checkbox.js +1 -1
  85. package/dist/components/ui-combobox.d.ts +11 -0
  86. package/dist/components/ui-combobox.js +1 -0
  87. package/dist/components/ui-context-menu.js +1 -1
  88. package/dist/components/ui-dialog.js +1 -1
  89. package/dist/components/ui-disclosure.js +1 -1
  90. package/dist/components/ui-floating-action-button.js +1 -1
  91. package/dist/components/ui-form-field.js +1 -1
  92. package/dist/components/ui-icon-button.js +1 -1
  93. package/dist/components/ui-input.js +1 -1
  94. package/dist/components/ui-menu-item.js +1 -1
  95. package/dist/components/ui-menu.js +1 -1
  96. package/dist/components/ui-popover.js +1 -1
  97. package/dist/components/ui-radio-group.js +1 -1
  98. package/dist/components/ui-radio.js +1 -1
  99. package/dist/components/ui-search-result-row.js +1 -1
  100. package/dist/components/ui-search-shell.js +1 -1
  101. package/dist/components/ui-select.js +1 -1
  102. package/dist/components/ui-switch.js +1 -1
  103. package/dist/components/ui-tabs.js +1 -1
  104. package/dist/components/ui-textarea.js +1 -1
  105. package/dist/components/ui-toast-region.js +1 -1
  106. package/dist/components/ui-tooltip.js +1 -1
  107. package/dist/components/ui-top-bar.js +1 -1
  108. package/dist/components/ui-tree-item.js +2 -2
  109. package/dist/components/ui-tree.js +1 -1
  110. package/dist/esm/{index-CEeiinfk.js → index-8BGiMGQ0.js} +33 -1
  111. package/dist/esm/loader.js +3 -3
  112. package/dist/esm/looma.js +3 -3
  113. package/dist/esm/{manager-PM9a74r7.js → manager-C-0syqXZ.js} +6 -7
  114. package/dist/esm/ui-affordance-scope.entry.js +1 -1
  115. package/dist/esm/ui-avatar-group.entry.js +1 -1
  116. package/dist/esm/ui-avatar.entry.js +1 -1
  117. package/dist/esm/ui-badge.entry.js +1 -1
  118. package/dist/esm/ui-button.entry.js +16 -5
  119. package/dist/esm/ui-checkbox.entry.js +1 -1
  120. package/dist/esm/ui-combobox.entry.js +539 -0
  121. package/dist/esm/ui-context-menu.entry.js +3 -3
  122. package/dist/esm/ui-dialog.entry.js +3 -3
  123. package/dist/esm/ui-disclosure.entry.js +2 -2
  124. package/dist/esm/ui-floating-action-button.entry.js +2 -2
  125. package/dist/esm/ui-form-field.entry.js +3 -3
  126. package/dist/esm/ui-icon-button.entry.js +2 -2
  127. package/dist/esm/ui-input.entry.js +11 -6
  128. package/dist/esm/ui-menu-item.entry.js +2 -2
  129. package/dist/esm/ui-menu.entry.js +3 -3
  130. package/dist/esm/ui-popover.entry.js +3 -3
  131. package/dist/esm/ui-radio-group.entry.js +2 -2
  132. package/dist/esm/ui-radio.entry.js +3 -3
  133. package/dist/esm/ui-search-result-row.entry.js +2 -2
  134. package/dist/esm/ui-search-shell.entry.js +2 -2
  135. package/dist/esm/ui-select.entry.js +15 -7
  136. package/dist/esm/ui-switch.entry.js +3 -3
  137. package/dist/esm/ui-tabs.entry.js +2 -2
  138. package/dist/esm/ui-textarea.entry.js +10 -6
  139. package/dist/esm/ui-toast-region.entry.js +2 -2
  140. package/dist/esm/ui-tooltip.entry.js +52 -16
  141. package/dist/esm/ui-top-bar.entry.js +2 -2
  142. package/dist/esm/ui-tree-item.entry.js +7 -3
  143. package/dist/esm/ui-tree.entry.js +81 -9
  144. package/dist/index.cjs +883 -123
  145. package/dist/index.d.cts +104 -1
  146. package/dist/index.d.ts +104 -1
  147. package/dist/index.js +62 -8
  148. package/dist/looma/looma.esm.js +1 -1
  149. package/dist/looma/{p-0198bb21.entry.js → p-13347631.entry.js} +1 -1
  150. package/dist/looma/p-14c081cf.entry.js +1 -0
  151. package/dist/looma/{p-0f45c5f0.entry.js → p-25366205.entry.js} +1 -1
  152. package/dist/looma/{p-a9f46811.entry.js → p-2e3aa869.entry.js} +1 -1
  153. package/dist/looma/p-40fe7fee.entry.js +1 -0
  154. package/dist/looma/p-446cda76.entry.js +1 -0
  155. package/dist/looma/p-4fc1b005.entry.js +13 -0
  156. package/dist/looma/p-582973b5.entry.js +1 -0
  157. package/dist/looma/{p-d273b857.entry.js → p-5a87b59d.entry.js} +1 -1
  158. package/dist/looma/{p-2ed7e241.entry.js → p-5da09f47.entry.js} +1 -1
  159. package/dist/looma/{p-7e94d90d.entry.js → p-69a5557b.entry.js} +1 -1
  160. package/dist/looma/p-6a8a4736.entry.js +1 -0
  161. package/dist/looma/{p-caa8fc7b.entry.js → p-6bf4038b.entry.js} +1 -1
  162. package/dist/looma/p-7e0bb7f6.entry.js +1 -0
  163. package/dist/looma/{p-ed5abf6d.entry.js → p-8204fee6.entry.js} +1 -1
  164. package/dist/looma/{p-5ba9d496.entry.js → p-8238e0dc.entry.js} +1 -1
  165. package/dist/looma/p-8BGiMGQ0.js +2 -0
  166. package/dist/looma/{p-051f578c.entry.js → p-8b8840b8.entry.js} +1 -1
  167. package/dist/looma/{p-1674cda4.entry.js → p-99d88efb.entry.js} +1 -1
  168. package/dist/looma/p-C-0syqXZ.js +1 -0
  169. package/dist/looma/p-a27669b1.entry.js +1 -0
  170. package/dist/looma/{p-11083743.entry.js → p-a6ee76b7.entry.js} +1 -1
  171. package/dist/looma/p-a90d2821.entry.js +1 -0
  172. package/dist/looma/{p-2e6f791e.entry.js → p-add36e74.entry.js} +1 -1
  173. package/dist/looma/{p-0584a051.entry.js → p-b6398a6b.entry.js} +1 -1
  174. package/dist/looma/{p-078f9fb8.entry.js → p-d50faaff.entry.js} +1 -1
  175. package/dist/looma/{p-b7aa4488.entry.js → p-d77278ce.entry.js} +1 -1
  176. package/dist/looma/p-d9ec13b7.entry.js +1 -0
  177. package/dist/looma/{p-1681b218.entry.js → p-ecf8005f.entry.js} +1 -1
  178. package/dist/looma/p-ed368426.entry.js +1 -0
  179. package/dist/looma/{p-063f5a89.entry.js → p-f0487ff3.entry.js} +1 -1
  180. package/dist/looma/p-f74e5546.entry.js +1 -0
  181. package/dist/types/components/ui-combobox/ui-combobox.d.ts +93 -0
  182. package/dist/types/components/ui-input/ui-input.d.ts +1 -1
  183. package/dist/types/components/ui-select/ui-select.d.ts +3 -2
  184. package/dist/types/components/ui-textarea/ui-textarea.d.ts +1 -1
  185. package/dist/types/components/ui-tooltip/ui-tooltip.d.ts +18 -1
  186. package/dist/types/components/ui-tree/ui-tree.d.ts +9 -1
  187. package/dist/types/components/ui-tree-item/ui-tree-item.d.ts +4 -0
  188. package/dist/types/components.d.ts +260 -28
  189. package/dist/types/field/combobox.d.ts +46 -0
  190. package/dist/types/field/valibot.d.ts +7 -0
  191. package/dist/types/field/validation.d.ts +56 -0
  192. package/dist/{ui-affordance-scope.entry-L533MECG.js → ui-affordance-scope.entry-VO4C2MZX.js} +1 -1
  193. package/dist/{ui-avatar-group.entry-BWS7E2CM.js → ui-avatar-group.entry-TAXJRIIU.js} +1 -1
  194. package/dist/{ui-avatar.entry-3INAY3XP.js → ui-avatar.entry-T6FU6ZYM.js} +1 -1
  195. package/dist/{ui-badge.entry-2WOBVOYP.js → ui-badge.entry-MZFYNBMJ.js} +1 -1
  196. package/dist/ui-button.entry-7UXMUGHN.js +80 -0
  197. package/dist/{ui-checkbox.entry-2PTBHSCQ.js → ui-checkbox.entry-DMZJB3RE.js} +1 -1
  198. package/dist/ui-combobox.entry-ZCTPXEES.js +553 -0
  199. package/dist/{ui-context-menu.entry-AYDDCIZS.js → ui-context-menu.entry-2WMCBGCP.js} +6 -6
  200. package/dist/{ui-dialog.entry-I2XI3ZTZ.js → ui-dialog.entry-WO23XOSW.js} +6 -6
  201. package/dist/{ui-disclosure.entry-5LY2BT7B.js → ui-disclosure.entry-USX7OUEW.js} +2 -2
  202. package/dist/{ui-floating-action-button.entry-EJAMR5AM.js → ui-floating-action-button.entry-MXDIN7MV.js} +2 -2
  203. package/dist/{ui-form-field.entry-SJ6NNFXB.js → ui-form-field.entry-7ZCMEHPY.js} +3 -3
  204. package/dist/{ui-icon-button.entry-7SD2LVXE.js → ui-icon-button.entry-MJUNXHBU.js} +2 -2
  205. package/dist/{ui-input.entry-7MM7GEQW.js → ui-input.entry-AWG63YIG.js} +8 -6
  206. package/dist/{ui-menu-item.entry-V3HIMR75.js → ui-menu-item.entry-HFTWG62N.js} +2 -2
  207. package/dist/{ui-menu.entry-R4WK5QSX.js → ui-menu.entry-IT3GW5TL.js} +7 -7
  208. package/dist/{ui-popover.entry-ZRJRTXA7.js → ui-popover.entry-ZQQB4N6E.js} +6 -6
  209. package/dist/{ui-radio-group.entry-S6RXHFSN.js → ui-radio-group.entry-V7PCTS7I.js} +2 -2
  210. package/dist/{ui-radio.entry-B73QZK2M.js → ui-radio.entry-JYH6TQBI.js} +3 -3
  211. package/dist/{ui-search-result-row.entry-DR2Y5S7P.js → ui-search-result-row.entry-JBNYXXUN.js} +2 -2
  212. package/dist/{ui-search-shell.entry-ST5IKJBC.js → ui-search-shell.entry-TEAWE76O.js} +2 -2
  213. package/dist/{ui-select.entry-7GPRFV67.js → ui-select.entry-F3A6TE2U.js} +13 -7
  214. package/dist/{ui-switch.entry-XQ5IRJRH.js → ui-switch.entry-MJIICMP2.js} +3 -3
  215. package/dist/{ui-tabs.entry-HPW5L5CY.js → ui-tabs.entry-6REFIUHV.js} +2 -2
  216. package/dist/{ui-textarea.entry-W2PSRYVS.js → ui-textarea.entry-OJTXCED7.js} +8 -6
  217. package/dist/{ui-toast-region.entry-FJUHFXKZ.js → ui-toast-region.entry-NOFXLKPS.js} +5 -5
  218. package/dist/{ui-tooltip.entry-G5WHQW7K.js → ui-tooltip.entry-COWTWVHX.js} +57 -21
  219. package/dist/{ui-top-bar.entry-3NCHFC4Y.js → ui-top-bar.entry-PIAWXJNV.js} +2 -2
  220. package/dist/{ui-tree-item.entry-45RR3CMP.js → ui-tree-item.entry-BSEWNL2O.js} +7 -3
  221. package/dist/{ui-tree.entry-SZW4Q5PY.js → ui-tree.entry-XYI3ZFAZ.js} +77 -8
  222. package/dist/valibot.d.ts +52 -0
  223. package/dist/valibot.js +7 -0
  224. package/package.json +11 -3
  225. package/styles.css +36 -20
  226. package/theme-high-contrast.css +12 -0
  227. package/tokens.css +23 -0
  228. package/vue/{chunk-5KWCMTXB.js → chunk-JLW23USW.js} +88 -1
  229. package/vue/editor/index.js +1 -1
  230. package/vue/index.d.ts +123 -1
  231. package/vue/index.js +3 -1
  232. package/dist/components/p-CEYIKqYc.js +0 -1
  233. package/dist/components/p-CIA4RyEp.js +0 -1
  234. package/dist/components/p-PM9a74r7.js +0 -1
  235. package/dist/looma/p-34417499.entry.js +0 -1
  236. package/dist/looma/p-4b422d40.entry.js +0 -1
  237. package/dist/looma/p-54722713.entry.js +0 -13
  238. package/dist/looma/p-54c41576.entry.js +0 -1
  239. package/dist/looma/p-5d4713a6.entry.js +0 -1
  240. package/dist/looma/p-624ba086.entry.js +0 -1
  241. package/dist/looma/p-8d5adb17.entry.js +0 -1
  242. package/dist/looma/p-9194a99d.entry.js +0 -1
  243. package/dist/looma/p-CEeiinfk.js +0 -2
  244. package/dist/looma/p-PM9a74r7.js +0 -1
  245. package/dist/looma/p-a33522a2.entry.js +0 -1
  246. package/dist/looma/p-a5127c7d.entry.js +0 -1
  247. package/dist/looma/p-e3f99a24.entry.js +0 -1
  248. package/dist/ui-button.entry-VCGSEONK.js +0 -71
@@ -1,5 +1,5 @@
1
1
  import { Host, h } from "@stencil/core";
2
- import { openOverlay, closeOverlay, requestTopOverlayClose } from "../../overlay/manager";
2
+ import { openOverlay, closeOverlay } from "../../overlay/manager";
3
3
  import { dispatchDetail } from "../../utils/events";
4
4
  import { createAnchoredSurface, } from "../../overlay/positioning";
5
5
  export class UITooltip {
@@ -12,6 +12,12 @@ export class UITooltip {
12
12
  showDelay = 500;
13
13
  /** Pointer leave grace period in milliseconds. */
14
14
  hideDelay = 100;
15
+ /** Click or tap pins the description; activate again to dismiss. */
16
+ toggleOnClick = false;
17
+ pinned = false;
18
+ focused = false;
19
+ opened;
20
+ closed;
15
21
  internalOpen = false;
16
22
  overlayId = `ui-tooltip-${Math.random().toString(36).slice(2, 11)}`;
17
23
  trigger = null;
@@ -45,11 +51,14 @@ export class UITooltip {
45
51
  }
46
52
  }
47
53
  componentDidLoad() {
54
+ if (!this.host.id)
55
+ this.host.id = this.overlayId;
48
56
  this.syncFromProp();
49
57
  this.internalOpen = this.internalOpen || this.defaultOpen;
50
58
  this.syncTrigger();
51
59
  this.setupSurface();
52
- this.host.addEventListener('keydown', this.onKeydown);
60
+ this.host.addEventListener('pointerenter', this.onSurfaceEnter);
61
+ this.host.addEventListener('pointerleave', this.onTriggerLeave);
53
62
  this.syncOverlay();
54
63
  }
55
64
  componentDidUpdate() {
@@ -60,12 +69,13 @@ export class UITooltip {
60
69
  this.detachTriggerListeners();
61
70
  this.surface?.destroy();
62
71
  this.surface = null;
63
- this.host.removeEventListener('keydown', this.onKeydown);
72
+ this.host.removeEventListener('pointerenter', this.onSurfaceEnter);
73
+ this.host.removeEventListener('pointerleave', this.onTriggerLeave);
64
74
  closeOverlay(this.overlayId);
65
75
  }
66
76
  syncTrigger() {
67
77
  const next = this.for
68
- ? this.host.ownerDocument.getElementById(this.for)
78
+ ? this.host.getRootNode().getElementById(this.for)
69
79
  : this.host.previousElementSibling;
70
80
  if (next === this.trigger)
71
81
  return;
@@ -85,6 +95,11 @@ export class UITooltip {
85
95
  this.detachTriggerListeners();
86
96
  if (!this.trigger)
87
97
  return;
98
+ const ids = new Set((this.trigger.getAttribute('aria-describedby') || '').split(/\s+/).filter(Boolean));
99
+ ids.add(this.host.id);
100
+ this.trigger.setAttribute('aria-describedby', [...ids].join(' '));
101
+ this.trigger.addEventListener('click', this.onTriggerClick);
102
+ this.trigger.addEventListener('keydown', this.onTriggerKeydown);
88
103
  this.trigger.addEventListener('pointerenter', this.onTriggerEnter);
89
104
  this.trigger.addEventListener('pointerleave', this.onTriggerLeave);
90
105
  this.trigger.addEventListener('focusin', this.onTriggerFocusIn);
@@ -93,6 +108,13 @@ export class UITooltip {
93
108
  detachTriggerListeners() {
94
109
  if (!this.trigger)
95
110
  return;
111
+ const ids = (this.trigger.getAttribute('aria-describedby') || '').split(/\s+/).filter(id => id && id !== this.host.id);
112
+ if (ids.length)
113
+ this.trigger.setAttribute('aria-describedby', ids.join(' '));
114
+ else
115
+ this.trigger.removeAttribute('aria-describedby');
116
+ this.trigger.removeEventListener('click', this.onTriggerClick);
117
+ this.trigger.removeEventListener('keydown', this.onTriggerKeydown);
96
118
  this.trigger.removeEventListener('pointerenter', this.onTriggerEnter);
97
119
  this.trigger.removeEventListener('pointerleave', this.onTriggerLeave);
98
120
  this.trigger.removeEventListener('focusin', this.onTriggerFocusIn);
@@ -124,7 +146,21 @@ export class UITooltip {
124
146
  trigger,
125
147
  });
126
148
  }
127
- onTriggerEnter = () => {
149
+ onSurfaceEnter = () => this.clearHideTimer();
150
+ onTriggerClick = (event) => {
151
+ if (!this.toggleOnClick)
152
+ return;
153
+ this.clearTimers();
154
+ this.pinned = !this.pinned;
155
+ this.setInteractionOpen(this.pinned, event.detail === 0 ? 'keyboard' : 'pointer');
156
+ };
157
+ onTriggerKeydown = (event) => {
158
+ if (event.key === 'Escape')
159
+ this.clearTimers();
160
+ };
161
+ onTriggerEnter = (event) => {
162
+ if (event.pointerType === 'touch')
163
+ return;
128
164
  this.clearHideTimer();
129
165
  if (this.internalOpen || this.showTimer !== null)
130
166
  return;
@@ -135,7 +171,7 @@ export class UITooltip {
135
171
  };
136
172
  onTriggerLeave = () => {
137
173
  this.clearShowTimer();
138
- if (!this.internalOpen || this.hideTimer !== null)
174
+ if (this.focused || this.pinned || !this.internalOpen || this.hideTimer !== null)
139
175
  return;
140
176
  this.hideTimer = setTimeout(() => {
141
177
  this.hideTimer = null;
@@ -143,6 +179,7 @@ export class UITooltip {
143
179
  }, Math.max(0, this.hideDelay));
144
180
  };
145
181
  onTriggerFocusIn = () => {
182
+ this.focused = true;
146
183
  this.clearTimers();
147
184
  this.setInteractionOpen(true, 'keyboard');
148
185
  };
@@ -150,28 +187,25 @@ export class UITooltip {
150
187
  const related = e.relatedTarget;
151
188
  if (related && this.host.contains(related))
152
189
  return;
190
+ this.focused = false;
191
+ this.pinned = false;
153
192
  this.clearTimers();
154
193
  this.setInteractionOpen(false, 'keyboard');
155
194
  };
156
195
  handleRequestClose(reason, trigger) {
157
- if (reason === 'escape') {
196
+ if (reason === 'escape' || (reason === 'light-dismiss' && this.toggleOnClick)) {
197
+ this.pinned = false;
158
198
  this.clearTimers();
159
199
  this.internalOpen = false;
160
200
  dispatchDetail(this.host, 'close', {
161
201
  open: false,
162
- reason: 'escape',
202
+ reason,
163
203
  trigger: trigger,
164
204
  });
165
- this.trigger?.focus();
166
205
  }
167
206
  }
168
- onKeydown = (e) => {
169
- if (e.key === 'Escape') {
170
- requestTopOverlayClose('escape', 'keyboard');
171
- }
172
- };
173
207
  render() {
174
- return (h(Host, { key: '4c3890a7371508ede06a5b370d1cec32db25280f', role: "tooltip", hidden: !this.internalOpen, "data-open": this.internalOpen ? '' : undefined, onKeyDown: this.onKeydown }, h("slot", { key: '2e3bcd0dc69b0c3e3376d73dc4efc82e4f4cfaaa' })));
208
+ return (h(Host, { key: 'b0199c23316a707ae3e1e7c361f2838872f62221', role: "tooltip", hidden: !this.internalOpen, "data-open": this.internalOpen ? '' : undefined }, h("slot", { key: 'd0c7822f2f47848a509bf8e310806edbdb320f02' })));
175
209
  }
176
210
  static get is() { return "ui-tooltip"; }
177
211
  static get encapsulation() { return "shadow"; }
@@ -313,6 +347,26 @@ export class UITooltip {
313
347
  "reflect": false,
314
348
  "attribute": "hide-delay",
315
349
  "defaultValue": "100"
350
+ },
351
+ "toggleOnClick": {
352
+ "type": "boolean",
353
+ "mutable": false,
354
+ "complexType": {
355
+ "original": "boolean",
356
+ "resolved": "boolean",
357
+ "references": {}
358
+ },
359
+ "required": false,
360
+ "optional": false,
361
+ "docs": {
362
+ "tags": [],
363
+ "text": "Click or tap pins the description; activate again to dismiss."
364
+ },
365
+ "getter": false,
366
+ "setter": false,
367
+ "reflect": false,
368
+ "attribute": "toggle-on-click",
369
+ "defaultValue": "false"
316
370
  }
317
371
  };
318
372
  }
@@ -321,6 +375,39 @@ export class UITooltip {
321
375
  "internalOpen": {}
322
376
  };
323
377
  }
378
+ static get events() {
379
+ return [{
380
+ "method": "opened",
381
+ "name": "open",
382
+ "bubbles": true,
383
+ "cancelable": true,
384
+ "composed": true,
385
+ "docs": {
386
+ "tags": [],
387
+ "text": ""
388
+ },
389
+ "complexType": {
390
+ "original": "{ open: boolean; reason: string; trigger: string }",
391
+ "resolved": "{ open: boolean; reason: string; trigger: string; }",
392
+ "references": {}
393
+ }
394
+ }, {
395
+ "method": "closed",
396
+ "name": "close",
397
+ "bubbles": true,
398
+ "cancelable": true,
399
+ "composed": true,
400
+ "docs": {
401
+ "tags": [],
402
+ "text": ""
403
+ },
404
+ "complexType": {
405
+ "original": "{ open: boolean; reason: string; trigger: string }",
406
+ "resolved": "{ open: boolean; reason: string; trigger: string; }",
407
+ "references": {}
408
+ }
409
+ }];
410
+ }
324
411
  static get elementRef() { return "host"; }
325
412
  static get watchers() {
326
413
  return [{
@@ -27,7 +27,7 @@ export class UITopBar {
27
27
  this.hasActions = slotHasContent(this.actionsSlot);
28
28
  };
29
29
  render() {
30
- return (h(Host, { key: '15c840c082724df0ec39ab6ad4e55f99192df5be' }, h("header", { key: '790afaeecdb3e598b8365391f57ee1e2d8ca69a2', class: "top-bar", part: "base" }, h("div", { key: 'fab822f5875c7e3b8e267be42c075597d79374fa', class: "top-bar__leading", hidden: !this.hasLeading }, h("slot", { key: '0723013c4b674964e4029442b715daa9eb0036db', name: "leading", ref: (el) => (this.leadingSlot = el), onSlotchange: this.syncSlots })), h("div", { key: '77fc006257b7fa6a191191d9969ea66445b8bc3e', class: "top-bar__title" }, h("slot", { key: 'e8a07f1f767c1c0fa1244abcf3bb0e697e36a4fe' })), h("div", { key: 'bde5cdf797ae898f68eddeab362b8395f89bdf28', class: "top-bar__search", hidden: !this.hasSearch }, h("slot", { key: '8b059d6123e94f3b7e18c15c88828ee9c6436136', name: "search", ref: (el) => (this.searchSlot = el), onSlotchange: this.syncSlots })), h("div", { key: 'c262446cf29873903530ea3f840de4de9db3de82', class: "top-bar__actions", hidden: !this.hasActions }, h("slot", { key: 'f417dbc8cc0115a455a72ce0feb5f32b323ce68f', name: "actions", ref: (el) => (this.actionsSlot = el), onSlotchange: this.syncSlots })))));
30
+ return (h(Host, { key: '730e45232ab2b86c2ac99dba773f4ca15d7c3c51' }, h("header", { key: 'f94f9b4f3f5930fda950895d2eec01d3ec175479', class: "top-bar", part: "base" }, h("div", { key: '038f6a404b0f159b4b826ada73d3c920266354c8', class: "top-bar__leading", hidden: !this.hasLeading }, h("slot", { key: '2d415368310c319eca3f3eb9b2c885ef79bb4107', name: "leading", ref: (el) => (this.leadingSlot = el), onSlotchange: this.syncSlots })), h("div", { key: 'dfd78b02066a91e9c610e4655a70da704ad65327', class: "top-bar__title" }, h("slot", { key: '499e24a864a31f6e400fd02aab4a3f960c87e572' })), h("div", { key: '5aa94952996487651dffecd2e351548631fa29b6', class: "top-bar__search", hidden: !this.hasSearch }, h("slot", { key: 'eddad95f8acf787ee0cead2a46e7961a06375d5c', name: "search", ref: (el) => (this.searchSlot = el), onSlotchange: this.syncSlots })), h("div", { key: 'dc69d492aa221a8beb888350bf101f8beeceede9', class: "top-bar__actions", hidden: !this.hasActions }, h("slot", { key: '7cde7e062f487da8209738a32415636c7a6b72f0', name: "actions", ref: (el) => (this.actionsSlot = el), onSlotchange: this.syncSlots })))));
31
31
  }
32
32
  static get is() { return "ui-top-bar"; }
33
33
  static get encapsulation() { return "shadow"; }
@@ -5,9 +5,14 @@ export class UITree {
5
5
  host;
6
6
  label = 'Tree';
7
7
  hoverExpandDelay = 700;
8
+ /** Maximum resulting item depth accepted by pointer reordering. Zero is unlimited. */
9
+ maxDepth = 0;
8
10
  source = null;
9
11
  target = null;
10
12
  position = null;
13
+ rejectedTarget = null;
14
+ rejectedPosition = null;
15
+ rejection = null;
11
16
  hoverIntent = null;
12
17
  componentDidLoad() {
13
18
  this.hoverIntent = createHoverIntent(this.hoverExpandDelay, this.expandTarget);
@@ -75,19 +80,42 @@ export class UITree {
75
80
  .filter(Boolean),
76
81
  };
77
82
  }
78
- permitsDrop(source, target, position) {
83
+ constraintDepth(item) {
84
+ if (item.dropDepth !== undefined)
85
+ return item.dropDepth;
86
+ const dropDepth = item.getAttribute('drop-depth');
87
+ if (dropDepth !== null)
88
+ return Number(dropDepth);
89
+ if (item.depth !== undefined)
90
+ return item.depth;
91
+ return Number(item.getAttribute('depth')) || 1;
92
+ }
93
+ dropRejection(source, target, position) {
79
94
  // A tree item can never move into (or beside) one of its own descendants.
80
95
  // Reject the target before showing any insertion affordance so the preview
81
96
  // stays truthful instead of promising a move the consumer must undo.
82
97
  if (source.contains(target))
83
- return false;
98
+ return { reason: 'descendant' };
84
99
  const sourceMeta = this.itemMetadata(source);
85
100
  const targetMeta = this.itemMetadata(target);
86
101
  if (position === 'inside') {
87
- return this.acceptsChildren(target)
88
- && (targetMeta.accepts.length === 0 || targetMeta.accepts.includes(sourceMeta.type));
102
+ if (!this.acceptsChildren(target)
103
+ || (targetMeta.accepts.length > 0 && !targetMeta.accepts.includes(sourceMeta.type))) {
104
+ return { reason: 'incompatible' };
105
+ }
106
+ }
107
+ else if (sourceMeta.type !== targetMeta.type) {
108
+ return { reason: 'incompatible' };
109
+ }
110
+ const maxDepth = Math.max(0, Math.floor(this.maxDepth));
111
+ if (maxDepth > 0 && source.subtreeDepth !== undefined) {
112
+ const targetDepth = Math.max(0, Math.floor(this.constraintDepth(target)));
113
+ const subtreeDepth = Math.max(0, Math.floor(source.subtreeDepth));
114
+ const resultingDepth = targetDepth + (position === 'inside' ? 1 : 0) + subtreeDepth;
115
+ if (resultingDepth > maxDepth)
116
+ return { reason: 'max-depth', maxDepth, resultingDepth };
89
117
  }
90
- return sourceMeta.type === targetMeta.type;
118
+ return null;
91
119
  }
92
120
  clearTarget() {
93
121
  this.target?.removeAttribute('data-drop-position');
@@ -95,10 +123,16 @@ export class UITree {
95
123
  this.position = null;
96
124
  this.hoverIntent?.cancel();
97
125
  }
126
+ clearRejection() {
127
+ this.rejectedTarget = null;
128
+ this.rejectedPosition = null;
129
+ this.rejection = null;
130
+ }
98
131
  finishDrag() {
99
132
  this.source?.removeAttribute('data-dragging');
100
133
  this.source = null;
101
134
  this.clearTarget();
135
+ this.clearRejection();
102
136
  }
103
137
  expandTarget = (itemId) => {
104
138
  const item = Array.from(this.host.querySelectorAll('ui-tree-item'))
@@ -136,18 +170,29 @@ export class UITree {
136
170
  return false;
137
171
  if (!target || target === this.source) {
138
172
  this.clearTarget();
173
+ this.clearRejection();
139
174
  return false;
140
175
  }
141
176
  const row = this.rowFor(target);
142
177
  if (!row)
143
178
  return false;
144
179
  const position = classifyDropPosition(row.getBoundingClientRect(), clientY, this.acceptsChildren(target));
145
- if (!this.permitsDrop(this.source, target, position)) {
180
+ const rejection = this.dropRejection(this.source, target, position);
181
+ if (rejection) {
146
182
  if (dataTransfer)
147
183
  dataTransfer.dropEffect = 'none';
148
184
  this.clearTarget();
185
+ if (rejection.reason === 'max-depth') {
186
+ this.rejectedTarget = target;
187
+ this.rejectedPosition = position;
188
+ this.rejection = rejection;
189
+ }
190
+ else {
191
+ this.clearRejection();
192
+ }
149
193
  return false;
150
194
  }
195
+ this.clearRejection();
151
196
  if (dataTransfer)
152
197
  dataTransfer.dropEffect = 'move';
153
198
  if (this.target !== target || this.position !== position) {
@@ -189,12 +234,15 @@ export class UITree {
189
234
  if (this.itemAtPoint(event.clientX, event.clientY))
190
235
  return;
191
236
  this.clearTarget();
237
+ this.clearRejection();
192
238
  };
193
239
  dispatchReorder(source, target, position) {
194
240
  const sourceId = this.itemId(source);
195
241
  const targetId = this.itemId(target);
196
242
  if (!sourceId || !targetId)
197
243
  return;
244
+ if (position === 'inside')
245
+ this.expandTarget(targetId);
198
246
  const sourceMeta = this.itemMetadata(source);
199
247
  const targetMeta = this.itemMetadata(target);
200
248
  dispatchDetail(this.host, 'reorder', {
@@ -208,6 +256,21 @@ export class UITree {
208
256
  trigger: 'pointer',
209
257
  });
210
258
  }
259
+ dispatchReorderRejected(source, target, position, rejection) {
260
+ const sourceId = this.itemId(source);
261
+ const targetId = this.itemId(target);
262
+ if (!sourceId || !targetId)
263
+ return;
264
+ dispatchDetail(this.host, 'reorder-rejected', {
265
+ sourceId,
266
+ targetId,
267
+ position,
268
+ reason: 'max-depth',
269
+ maxDepth: rejection.maxDepth,
270
+ resultingDepth: rejection.resultingDepth,
271
+ trigger: 'pointer',
272
+ });
273
+ }
211
274
  onDrop = (event) => {
212
275
  if (!this.source || !this.target || !this.position)
213
276
  return;
@@ -217,14 +280,23 @@ export class UITree {
217
280
  };
218
281
  onDragEnd = (event) => {
219
282
  if (this.source) {
283
+ if (this.rejectedTarget && this.rejectedPosition && this.rejection) {
284
+ this.dispatchReorderRejected(this.source, this.rejectedTarget, this.rejectedPosition, this.rejection);
285
+ this.finishDrag();
286
+ return;
287
+ }
220
288
  const target = this.itemAtPoint(event.clientX, event.clientY);
221
289
  if (target && target !== this.source) {
222
290
  const row = this.rowFor(target);
223
291
  if (row) {
224
292
  const position = classifyDropPosition(row.getBoundingClientRect(), event.clientY, this.acceptsChildren(target));
225
- if (this.permitsDrop(this.source, target, position)) {
293
+ const rejection = this.dropRejection(this.source, target, position);
294
+ if (!rejection) {
226
295
  this.dispatchReorder(this.source, target, position);
227
296
  }
297
+ else if (rejection.reason === 'max-depth') {
298
+ this.dispatchReorderRejected(this.source, target, position, rejection);
299
+ }
228
300
  }
229
301
  }
230
302
  }
@@ -249,7 +321,7 @@ export class UITree {
249
321
  next.focus();
250
322
  };
251
323
  render() {
252
- return (h(Host, { key: '7da064127eb199f5e2cfc59489a07204c9dac2f2', role: "tree", "aria-label": this.label || 'Tree' }, h("slot", { key: '31a98a6774ab35e565dab65f1dd8202494432b32' })));
324
+ return (h(Host, { key: '474c2154d2abe3c76eee9c36bf552390089df6e8', role: "tree", "aria-label": this.label || 'Tree' }, h("slot", { key: '93aedd02f984dd33b5efc811fef417d1199917bd' })));
253
325
  }
254
326
  static get is() { return "ui-tree"; }
255
327
  static get encapsulation() { return "shadow"; }
@@ -304,6 +376,26 @@ export class UITree {
304
376
  "reflect": false,
305
377
  "attribute": "hover-expand-delay",
306
378
  "defaultValue": "700"
379
+ },
380
+ "maxDepth": {
381
+ "type": "number",
382
+ "mutable": false,
383
+ "complexType": {
384
+ "original": "number",
385
+ "resolved": "number",
386
+ "references": {}
387
+ },
388
+ "required": false,
389
+ "optional": false,
390
+ "docs": {
391
+ "tags": [],
392
+ "text": "Maximum resulting item depth accepted by pointer reordering. Zero is unlimited."
393
+ },
394
+ "getter": false,
395
+ "setter": false,
396
+ "reflect": false,
397
+ "attribute": "max-depth",
398
+ "defaultValue": "0"
307
399
  }
308
400
  };
309
401
  }
@@ -9,6 +9,10 @@ export class UITreeItem {
9
9
  label = '';
10
10
  /** One-based visual and semantic nesting level. */
11
11
  depth = 1;
12
+ /** Application hierarchy depth used for drop constraints. Defaults to visual depth. */
13
+ dropDepth;
14
+ /** Deepest descendant distance, used with the tree's max-depth drop constraint. */
15
+ subtreeDepth;
12
16
  /** Whether this item accepts children and exposes disclosure behavior. */
13
17
  container = false;
14
18
  /** Whether this item participates in pointer drag and drop. */
@@ -71,10 +75,10 @@ export class UITreeItem {
71
75
  const level = Math.max(1, Math.floor(this.depth));
72
76
  const disclosureLabel = `${this.internalExpanded ? 'Collapse' : 'Expand'} ${this.label || 'item'}`;
73
77
  const dragLabel = `Drag ${this.label || 'item'} to reorder`;
74
- return (h(Host, { key: 'ea8ed538aa3883c87257a25614a066965364693f', role: "treeitem", "aria-level": String(level), "aria-expanded": this.container ? String(this.internalExpanded) : undefined, "aria-selected": String(this.selected), "aria-disabled": this.disabled ? 'true' : undefined, "data-container": this.container ? '' : undefined, "data-selected": this.selected ? '' : undefined, "data-disabled": this.disabled ? '' : undefined, "data-drag-type": this.dragType || 'item', "data-drop-scope": this.dropScope || undefined, "data-accepts": this.accepts || undefined, tabIndex: this.disabled ? -1 : 0, style: {
78
+ return (h(Host, { key: '606f5fdac8a95489d0c62cd7d4918c6d5d0c759e', role: "treeitem", "aria-level": String(level), "aria-expanded": this.container ? String(this.internalExpanded) : undefined, "aria-selected": String(this.selected), "aria-disabled": this.disabled ? 'true' : undefined, "data-container": this.container ? '' : undefined, "data-selected": this.selected ? '' : undefined, "data-disabled": this.disabled ? '' : undefined, "data-drag-type": this.dragType || 'item', "data-drop-scope": this.dropScope || undefined, "data-accepts": this.accepts || undefined, tabIndex: this.disabled ? -1 : 0, style: {
75
79
  '--ui-tree-item-depth': String(level - 1),
76
80
  'margin-inline-start': level > 1 ? 'var(--ui-tree-indent, 16px)' : '0px',
77
- } }, h("div", { key: '740b93aa47e65d8a1cb899d4b9c966d9ad1d456f', class: "row", part: "row", onClick: this.onRowClick }, this.sortable && !this.disabled ? (h("button", { class: "drag-handle", part: "drag-handle", type: "button", draggable: true, "aria-label": dragLabel, title: dragLabel }, h("span", { innerHTML: loomaIconMarkup('grip-vertical') }))) : null, this.container ? (h("button", { class: "disclosure", part: "disclosure", type: "button", "aria-label": disclosureLabel, "aria-expanded": String(this.internalExpanded), disabled: this.disabled, onClick: this.onDisclosureClick, onKeyDown: this.onDisclosureKeydown }, h("span", { class: { 'disclosure-icon': true, 'disclosure-icon--expanded': this.internalExpanded }, innerHTML: loomaIconMarkup('chevron-down') }))) : h("span", { class: "disclosure-spacer", "aria-hidden": "true" }), h("span", { key: '37e1b7f1cdddf623734becef465ffde83d8b86f2', class: "leading", part: "leading" }, h("slot", { key: '0ab3a60c98628f009918d0d720772154912d2709', name: "leading" })), h("span", { key: 'defdd343f25a0f4354110e981f3889e1d09c27ee', class: "label", part: "label" }, h("slot", { key: 'bde46ccacc1a620348062fc300503c4f1736316b' })), h("span", { key: 'caff9ada38c41be90aeb6e331f4c54a51f31d26c', class: "actions", part: "actions" }, h("slot", { key: 'e11704d6871445c91eaa29c99302d8b751be69d3', name: "actions" })), h("span", { key: '9efc0e95588f1dd4527dade2b7ff9f2774462c2e', class: "drop-indicator row-drop-indicator", part: "drop-indicator", "aria-hidden": "true" })), this.container ? (h("div", { class: "children", part: "children", role: "group", hidden: !this.internalExpanded }, h("slot", { name: "children" }))) : null, h("span", { key: '8893ec2c4082bb8af942ef563055a2910d0d4201', class: "drop-indicator subtree-drop-indicator", part: "drop-indicator", "aria-hidden": "true" })));
81
+ } }, h("div", { key: '2b4bb03d4b24ef668f22b08e803f7f43c2d63ae5', class: "row", part: "row", onClick: this.onRowClick }, this.sortable && !this.disabled ? (h("button", { class: "drag-handle", part: "drag-handle", type: "button", draggable: true, "aria-label": dragLabel, title: dragLabel }, h("span", { innerHTML: loomaIconMarkup('grip-vertical') }))) : null, this.container ? (h("button", { class: "disclosure", part: "disclosure", type: "button", "aria-label": disclosureLabel, "aria-expanded": String(this.internalExpanded), disabled: this.disabled, onClick: this.onDisclosureClick, onKeyDown: this.onDisclosureKeydown }, h("span", { class: { 'disclosure-icon': true, 'disclosure-icon--expanded': this.internalExpanded }, innerHTML: loomaIconMarkup('chevron-down') }))) : h("span", { class: "disclosure-spacer", "aria-hidden": "true" }), h("span", { key: 'e7b935158e35cdc6518bdd73d54c42dcfa211aee', class: "leading", part: "leading" }, h("slot", { key: '8448462349fd23b8be0fb673fc6e101bf94beaa7', name: "leading" })), h("span", { key: 'e0b6338e1ec9ec043446e42c5f03724adf7e1862', class: "label", part: "label" }, h("slot", { key: 'ed44e6f2ce3466c28d2b87fc7511399ecc339255' })), h("span", { key: '2aea78227904fe23cfc4b8e14852a4601e3cc34b', class: "actions", part: "actions" }, h("slot", { key: '7c6549008c2a54c3ea6fcdf9e0fdbe445d379922', name: "actions" })), h("span", { key: '05166ba04765bc518d6b95ca7ae5a67c4394d1bf', class: "drop-indicator row-drop-indicator", part: "drop-indicator", "aria-hidden": "true" })), this.container ? (h("div", { class: "children", part: "children", role: "group", hidden: !this.internalExpanded }, h("slot", { name: "children" }))) : null, h("span", { key: '7381d6e9e2a8f94695f29e73194b1603d79cefb9', class: "drop-indicator subtree-drop-indicator", part: "drop-indicator", "aria-hidden": "true" })));
78
82
  }
79
83
  static get is() { return "ui-tree-item"; }
80
84
  static get encapsulation() { return "shadow"; }
@@ -150,6 +154,44 @@ export class UITreeItem {
150
154
  "attribute": "depth",
151
155
  "defaultValue": "1"
152
156
  },
157
+ "dropDepth": {
158
+ "type": "number",
159
+ "mutable": false,
160
+ "complexType": {
161
+ "original": "number",
162
+ "resolved": "number",
163
+ "references": {}
164
+ },
165
+ "required": false,
166
+ "optional": true,
167
+ "docs": {
168
+ "tags": [],
169
+ "text": "Application hierarchy depth used for drop constraints. Defaults to visual depth."
170
+ },
171
+ "getter": false,
172
+ "setter": false,
173
+ "reflect": false,
174
+ "attribute": "drop-depth"
175
+ },
176
+ "subtreeDepth": {
177
+ "type": "number",
178
+ "mutable": false,
179
+ "complexType": {
180
+ "original": "number",
181
+ "resolved": "number",
182
+ "references": {}
183
+ },
184
+ "required": false,
185
+ "optional": true,
186
+ "docs": {
187
+ "tags": [],
188
+ "text": "Deepest descendant distance, used with the tree's max-depth drop constraint."
189
+ },
190
+ "getter": false,
191
+ "setter": false,
192
+ "reflect": false,
193
+ "attribute": "subtree-depth"
194
+ },
153
195
  "container": {
154
196
  "type": "boolean",
155
197
  "mutable": false,
@@ -0,0 +1,4 @@
1
+ /** Map domain records at the boundary, preserving typed metadata for rich rows. */
2
+ export function mapComboboxOptions(rows, map) {
3
+ return rows.map(row => ({ ...map(row), metadata: row }));
4
+ }
@@ -0,0 +1,5 @@
1
+ /** Valibot's Standard Schema implementation preserves async transforms and issue paths.
2
+ * Type-only Valibot imports keep the adapter free of a schema-library runtime. */
3
+ export function valibotField(schema, options = {}) {
4
+ return { ...options, schema };
5
+ }
@@ -0,0 +1,62 @@
1
+ /** Formatting is additive: every original character must survive in order.
2
+ * Normalization belongs to submitted output, never the visible editing buffer. */
3
+ export function formatEditingValue(raw, selection, format) {
4
+ const unchanged = { display: raw, selection };
5
+ if (!format)
6
+ return unchanged;
7
+ let result;
8
+ try {
9
+ result = format(raw, selection);
10
+ }
11
+ catch {
12
+ return unchanged;
13
+ }
14
+ if (!result)
15
+ return unchanged;
16
+ const characters = Array.from(raw);
17
+ let cursor = 0;
18
+ for (const character of result.display)
19
+ if (character === characters[cursor])
20
+ cursor += 1;
21
+ if (!Number.isInteger(result.selection.start) || !Number.isInteger(result.selection.end) || cursor !== characters.length || result.selection.start < 0 || result.selection.end < result.selection.start
22
+ || result.selection.end > result.display.length)
23
+ return unchanged;
24
+ return result;
25
+ }
26
+ export async function validateField(request, config) {
27
+ let output = request.raw;
28
+ let issues = [];
29
+ const check = () => request.signal.throwIfAborted();
30
+ try {
31
+ check();
32
+ if (config.parse)
33
+ output = await config.parse(request.raw, request);
34
+ check();
35
+ if (config.schema) {
36
+ const result = await config.schema['~standard'].validate(output);
37
+ check();
38
+ if (result.issues)
39
+ issues = result.issues;
40
+ else if ('value' in result)
41
+ output = result.value;
42
+ }
43
+ if (!issues.some(issue => issue.severity !== 'warning')) {
44
+ if (config.normalize)
45
+ output = await config.normalize(output, request);
46
+ check();
47
+ if (config.validator) {
48
+ const result = await config.validator(output, request);
49
+ check();
50
+ issues = [...issues, ...(result.issues ?? [])];
51
+ if ('output' in result)
52
+ output = result.output;
53
+ }
54
+ }
55
+ }
56
+ catch (error) {
57
+ check();
58
+ issues = [{ message: error instanceof Error ? error.message : 'Unable to validate this value.' }];
59
+ }
60
+ issues = [...issues, ...(config.issues ?? [])];
61
+ return { output: issues.some(issue => issue.severity !== 'warning') ? undefined : output, issues };
62
+ }
@@ -29,13 +29,12 @@ function handleLightDismiss(event) {
29
29
  if (!top || !getOverlayDismissible(top)) {
30
30
  return;
31
31
  }
32
- const target = event.target;
33
- if (target instanceof Node) {
34
- if (top.element.contains(target))
35
- return;
36
- if (top.relatedElements?.some((element) => element.contains(target)))
37
- return;
38
- }
32
+ // A document listener sees a shadow host as event.target. Use the composed
33
+ // path so connected controls inside a field remain inside the overlay boundary.
34
+ const boundary = [top.element, ...(top.relatedElements ?? [])];
35
+ if (event.composedPath().some(target => target instanceof Node
36
+ && boundary.some(element => element.contains(target))))
37
+ return;
39
38
  requestTopOverlayClose("light-dismiss", "pointer");
40
39
  }
41
40
  function ensureListeners() {
@@ -11,6 +11,8 @@ export { UIButton as UiButton } from '../types/components/ui-button/ui-button';
11
11
  export { defineCustomElement as defineCustomElementUiButton } from './ui-button';
12
12
  export { UICheckbox as UiCheckbox } from '../types/components/ui-checkbox/ui-checkbox';
13
13
  export { defineCustomElement as defineCustomElementUiCheckbox } from './ui-checkbox';
14
+ export { UICombobox as UiCombobox } from '../types/components/ui-combobox/ui-combobox';
15
+ export { defineCustomElement as defineCustomElementUiCombobox } from './ui-combobox';
14
16
  export { UIContextMenu as UiContextMenu } from '../types/components/ui-context-menu/ui-context-menu';
15
17
  export { defineCustomElement as defineCustomElementUiContextMenu } from './ui-context-menu';
16
18
  export { UIDialog as UiDialog } from '../types/components/ui-dialog/ui-dialog';
@@ -1 +1 @@
1
- export{g as getAssetPath,r as render,s as setAssetPath,a as setNonce,b as setPlatformOptions}from"./p-CIA4RyEp.js";export{UiAffordanceScope,defineCustomElement as defineCustomElementUiAffordanceScope}from"./ui-affordance-scope.js";export{UiAvatar,defineCustomElement as defineCustomElementUiAvatar}from"./ui-avatar.js";export{UiAvatarGroup,defineCustomElement as defineCustomElementUiAvatarGroup}from"./ui-avatar-group.js";export{UiBadge,defineCustomElement as defineCustomElementUiBadge}from"./ui-badge.js";export{UiButton,defineCustomElement as defineCustomElementUiButton}from"./ui-button.js";export{UiCheckbox,defineCustomElement as defineCustomElementUiCheckbox}from"./ui-checkbox.js";export{UiContextMenu,defineCustomElement as defineCustomElementUiContextMenu}from"./ui-context-menu.js";export{UiDialog,defineCustomElement as defineCustomElementUiDialog}from"./ui-dialog.js";export{UiDisclosure,defineCustomElement as defineCustomElementUiDisclosure}from"./ui-disclosure.js";export{UiFloatingActionButton,defineCustomElement as defineCustomElementUiFloatingActionButton}from"./ui-floating-action-button.js";export{UiFormField,defineCustomElement as defineCustomElementUiFormField}from"./ui-form-field.js";export{UiIconButton,defineCustomElement as defineCustomElementUiIconButton}from"./ui-icon-button.js";export{UiInput,defineCustomElement as defineCustomElementUiInput}from"./ui-input.js";export{UiMenu,defineCustomElement as defineCustomElementUiMenu}from"./ui-menu.js";export{UiMenuItem,defineCustomElement as defineCustomElementUiMenuItem}from"./ui-menu-item.js";export{UiPopover,defineCustomElement as defineCustomElementUiPopover}from"./ui-popover.js";export{UiRadio,defineCustomElement as defineCustomElementUiRadio}from"./ui-radio.js";export{UiRadioGroup,defineCustomElement as defineCustomElementUiRadioGroup}from"./ui-radio-group.js";export{UiSearchResultRow,defineCustomElement as defineCustomElementUiSearchResultRow}from"./ui-search-result-row.js";export{UiSearchShell,defineCustomElement as defineCustomElementUiSearchShell}from"./ui-search-shell.js";export{UiSelect,defineCustomElement as defineCustomElementUiSelect}from"./ui-select.js";export{UiSwitch,defineCustomElement as defineCustomElementUiSwitch}from"./ui-switch.js";export{UiTabs,defineCustomElement as defineCustomElementUiTabs}from"./ui-tabs.js";export{UiTextarea,defineCustomElement as defineCustomElementUiTextarea}from"./ui-textarea.js";export{UiToastRegion,defineCustomElement as defineCustomElementUiToastRegion}from"./ui-toast-region.js";export{UiTooltip,defineCustomElement as defineCustomElementUiTooltip}from"./ui-tooltip.js";export{UiTopBar,defineCustomElement as defineCustomElementUiTopBar}from"./ui-top-bar.js";export{UiTree,defineCustomElement as defineCustomElementUiTree}from"./ui-tree.js";export{UiTreeItem,defineCustomElement as defineCustomElementUiTreeItem}from"./ui-tree-item.js";
1
+ export{g as getAssetPath,r as render,s as setAssetPath,a as setNonce,b as setPlatformOptions}from"./p-Bh_1GxOD.js";export{UiAffordanceScope,defineCustomElement as defineCustomElementUiAffordanceScope}from"./ui-affordance-scope.js";export{UiAvatar,defineCustomElement as defineCustomElementUiAvatar}from"./ui-avatar.js";export{UiAvatarGroup,defineCustomElement as defineCustomElementUiAvatarGroup}from"./ui-avatar-group.js";export{UiBadge,defineCustomElement as defineCustomElementUiBadge}from"./ui-badge.js";export{UiButton,defineCustomElement as defineCustomElementUiButton}from"./ui-button.js";export{UiCheckbox,defineCustomElement as defineCustomElementUiCheckbox}from"./ui-checkbox.js";export{UiCombobox,defineCustomElement as defineCustomElementUiCombobox}from"./ui-combobox.js";export{UiContextMenu,defineCustomElement as defineCustomElementUiContextMenu}from"./ui-context-menu.js";export{UiDialog,defineCustomElement as defineCustomElementUiDialog}from"./ui-dialog.js";export{UiDisclosure,defineCustomElement as defineCustomElementUiDisclosure}from"./ui-disclosure.js";export{UiFloatingActionButton,defineCustomElement as defineCustomElementUiFloatingActionButton}from"./ui-floating-action-button.js";export{UiFormField,defineCustomElement as defineCustomElementUiFormField}from"./ui-form-field.js";export{UiIconButton,defineCustomElement as defineCustomElementUiIconButton}from"./ui-icon-button.js";export{UiInput,defineCustomElement as defineCustomElementUiInput}from"./ui-input.js";export{UiMenu,defineCustomElement as defineCustomElementUiMenu}from"./ui-menu.js";export{UiMenuItem,defineCustomElement as defineCustomElementUiMenuItem}from"./ui-menu-item.js";export{UiPopover,defineCustomElement as defineCustomElementUiPopover}from"./ui-popover.js";export{UiRadio,defineCustomElement as defineCustomElementUiRadio}from"./ui-radio.js";export{UiRadioGroup,defineCustomElement as defineCustomElementUiRadioGroup}from"./ui-radio-group.js";export{UiSearchResultRow,defineCustomElement as defineCustomElementUiSearchResultRow}from"./ui-search-result-row.js";export{UiSearchShell,defineCustomElement as defineCustomElementUiSearchShell}from"./ui-search-shell.js";export{UiSelect,defineCustomElement as defineCustomElementUiSelect}from"./ui-select.js";export{UiSwitch,defineCustomElement as defineCustomElementUiSwitch}from"./ui-switch.js";export{UiTabs,defineCustomElement as defineCustomElementUiTabs}from"./ui-tabs.js";export{UiTextarea,defineCustomElement as defineCustomElementUiTextarea}from"./ui-textarea.js";export{UiToastRegion,defineCustomElement as defineCustomElementUiToastRegion}from"./ui-toast-region.js";export{UiTooltip,defineCustomElement as defineCustomElementUiTooltip}from"./ui-tooltip.js";export{UiTopBar,defineCustomElement as defineCustomElementUiTopBar}from"./ui-top-bar.js";export{UiTree,defineCustomElement as defineCustomElementUiTree}from"./ui-tree.js";export{UiTreeItem,defineCustomElement as defineCustomElementUiTreeItem}from"./ui-tree-item.js";