@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,26 +1,28 @@
1
+ import {
2
+ dispatchDetail
3
+ } from "./chunk-UL7UIUJZ.js";
1
4
  import {
2
5
  closeOverlay,
3
- openOverlay,
4
- requestTopOverlayClose
5
- } from "./chunk-SZJQ3NPX.js";
6
+ openOverlay
7
+ } from "./chunk-TL4FIE7X.js";
6
8
  import {
7
9
  createAnchoredSurface
8
10
  } from "./chunk-YHXJC5M5.js";
9
- import {
10
- dispatchDetail
11
- } from "./chunk-UL7UIUJZ.js";
12
11
  import {
13
12
  Host,
13
+ createEvent,
14
14
  getElement,
15
15
  h,
16
16
  registerInstance
17
- } from "./chunk-NIPNHZ5W.js";
17
+ } from "./chunk-GDMQKT5F.js";
18
18
 
19
19
  // dist/esm/ui-tooltip.entry.js
20
20
  var uiTooltipCss = () => `:host{position:fixed;inset:auto;margin:0;display:inline-block;border:1px solid var(--ui-border-default);border-radius:var(--ui-radius-2);background:var(--ui-surface-elevated);color:var(--ui-text-primary);padding:var(--ui-space-2) var(--ui-space-3);font-size:var(--ui-font-size-sm);box-shadow:var(--ui-shadow-md);opacity:0;transform:translateY(4px);transition:opacity var(--ui-motion-fast) var(--ui-motion-ease), transform var(--ui-motion-fast) var(--ui-motion-ease), display var(--ui-motion-fast) allow-discrete, overlay var(--ui-motion-fast) allow-discrete}:host(:popover-open){opacity:1;transform:translateY(0)}@starting-style{:host(:popover-open){opacity:0;transform:translateY(4px)}}:host([hidden]){display:none !important}@media (prefers-reduced-motion: reduce){:host{transition:none}}`;
21
21
  var UITooltip = class {
22
22
  constructor(hostRef) {
23
23
  registerInstance(this, hostRef);
24
+ this.opened = createEvent(this, "open");
25
+ this.closed = createEvent(this, "close");
24
26
  }
25
27
  get host() {
26
28
  return getElement(this);
@@ -33,6 +35,12 @@ var UITooltip = class {
33
35
  showDelay = 500;
34
36
  /** Pointer leave grace period in milliseconds. */
35
37
  hideDelay = 100;
38
+ /** Click or tap pins the description; activate again to dismiss. */
39
+ toggleOnClick = false;
40
+ pinned = false;
41
+ focused = false;
42
+ opened;
43
+ closed;
36
44
  internalOpen = false;
37
45
  overlayId = `ui-tooltip-${Math.random().toString(36).slice(2, 11)}`;
38
46
  trigger = null;
@@ -65,11 +73,14 @@ var UITooltip = class {
65
73
  }
66
74
  }
67
75
  componentDidLoad() {
76
+ if (!this.host.id)
77
+ this.host.id = this.overlayId;
68
78
  this.syncFromProp();
69
79
  this.internalOpen = this.internalOpen || this.defaultOpen;
70
80
  this.syncTrigger();
71
81
  this.setupSurface();
72
- this.host.addEventListener("keydown", this.onKeydown);
82
+ this.host.addEventListener("pointerenter", this.onSurfaceEnter);
83
+ this.host.addEventListener("pointerleave", this.onTriggerLeave);
73
84
  this.syncOverlay();
74
85
  }
75
86
  componentDidUpdate() {
@@ -80,11 +91,12 @@ var UITooltip = class {
80
91
  this.detachTriggerListeners();
81
92
  this.surface?.destroy();
82
93
  this.surface = null;
83
- this.host.removeEventListener("keydown", this.onKeydown);
94
+ this.host.removeEventListener("pointerenter", this.onSurfaceEnter);
95
+ this.host.removeEventListener("pointerleave", this.onTriggerLeave);
84
96
  closeOverlay(this.overlayId);
85
97
  }
86
98
  syncTrigger() {
87
- const next = this.for ? this.host.ownerDocument.getElementById(this.for) : this.host.previousElementSibling;
99
+ const next = this.for ? this.host.getRootNode().getElementById(this.for) : this.host.previousElementSibling;
88
100
  if (next === this.trigger)
89
101
  return;
90
102
  this.detachTriggerListeners();
@@ -103,6 +115,11 @@ var UITooltip = class {
103
115
  this.detachTriggerListeners();
104
116
  if (!this.trigger)
105
117
  return;
118
+ const ids = new Set((this.trigger.getAttribute("aria-describedby") || "").split(/\s+/).filter(Boolean));
119
+ ids.add(this.host.id);
120
+ this.trigger.setAttribute("aria-describedby", [...ids].join(" "));
121
+ this.trigger.addEventListener("click", this.onTriggerClick);
122
+ this.trigger.addEventListener("keydown", this.onTriggerKeydown);
106
123
  this.trigger.addEventListener("pointerenter", this.onTriggerEnter);
107
124
  this.trigger.addEventListener("pointerleave", this.onTriggerLeave);
108
125
  this.trigger.addEventListener("focusin", this.onTriggerFocusIn);
@@ -111,6 +128,13 @@ var UITooltip = class {
111
128
  detachTriggerListeners() {
112
129
  if (!this.trigger)
113
130
  return;
131
+ const ids = (this.trigger.getAttribute("aria-describedby") || "").split(/\s+/).filter((id) => id && id !== this.host.id);
132
+ if (ids.length)
133
+ this.trigger.setAttribute("aria-describedby", ids.join(" "));
134
+ else
135
+ this.trigger.removeAttribute("aria-describedby");
136
+ this.trigger.removeEventListener("click", this.onTriggerClick);
137
+ this.trigger.removeEventListener("keydown", this.onTriggerKeydown);
114
138
  this.trigger.removeEventListener("pointerenter", this.onTriggerEnter);
115
139
  this.trigger.removeEventListener("pointerleave", this.onTriggerLeave);
116
140
  this.trigger.removeEventListener("focusin", this.onTriggerFocusIn);
@@ -142,7 +166,21 @@ var UITooltip = class {
142
166
  trigger
143
167
  });
144
168
  }
145
- onTriggerEnter = () => {
169
+ onSurfaceEnter = () => this.clearHideTimer();
170
+ onTriggerClick = (event) => {
171
+ if (!this.toggleOnClick)
172
+ return;
173
+ this.clearTimers();
174
+ this.pinned = !this.pinned;
175
+ this.setInteractionOpen(this.pinned, event.detail === 0 ? "keyboard" : "pointer");
176
+ };
177
+ onTriggerKeydown = (event) => {
178
+ if (event.key === "Escape")
179
+ this.clearTimers();
180
+ };
181
+ onTriggerEnter = (event) => {
182
+ if (event.pointerType === "touch")
183
+ return;
146
184
  this.clearHideTimer();
147
185
  if (this.internalOpen || this.showTimer !== null)
148
186
  return;
@@ -153,7 +191,7 @@ var UITooltip = class {
153
191
  };
154
192
  onTriggerLeave = () => {
155
193
  this.clearShowTimer();
156
- if (!this.internalOpen || this.hideTimer !== null)
194
+ if (this.focused || this.pinned || !this.internalOpen || this.hideTimer !== null)
157
195
  return;
158
196
  this.hideTimer = setTimeout(() => {
159
197
  this.hideTimer = null;
@@ -161,6 +199,7 @@ var UITooltip = class {
161
199
  }, Math.max(0, this.hideDelay));
162
200
  };
163
201
  onTriggerFocusIn = () => {
202
+ this.focused = true;
164
203
  this.clearTimers();
165
204
  this.setInteractionOpen(true, "keyboard");
166
205
  };
@@ -168,28 +207,25 @@ var UITooltip = class {
168
207
  const related = e.relatedTarget;
169
208
  if (related && this.host.contains(related))
170
209
  return;
210
+ this.focused = false;
211
+ this.pinned = false;
171
212
  this.clearTimers();
172
213
  this.setInteractionOpen(false, "keyboard");
173
214
  };
174
215
  handleRequestClose(reason, trigger) {
175
- if (reason === "escape") {
216
+ if (reason === "escape" || reason === "light-dismiss" && this.toggleOnClick) {
217
+ this.pinned = false;
176
218
  this.clearTimers();
177
219
  this.internalOpen = false;
178
220
  dispatchDetail(this.host, "close", {
179
221
  open: false,
180
- reason: "escape",
222
+ reason,
181
223
  trigger
182
224
  });
183
- this.trigger?.focus();
184
225
  }
185
226
  }
186
- onKeydown = (e) => {
187
- if (e.key === "Escape") {
188
- requestTopOverlayClose("escape", "keyboard");
189
- }
190
- };
191
227
  render() {
192
- return h(Host, { key: "4c3890a7371508ede06a5b370d1cec32db25280f", role: "tooltip", hidden: !this.internalOpen, "data-open": this.internalOpen ? "" : void 0, onKeyDown: this.onKeydown }, h("slot", { key: "2e3bcd0dc69b0c3e3376d73dc4efc82e4f4cfaaa" }));
228
+ return h(Host, { key: "b0199c23316a707ae3e1e7c361f2838872f62221", role: "tooltip", hidden: !this.internalOpen, "data-open": this.internalOpen ? "" : void 0 }, h("slot", { key: "d0c7822f2f47848a509bf8e310806edbdb320f02" }));
193
229
  }
194
230
  static get watchers() {
195
231
  return {
@@ -3,7 +3,7 @@ import {
3
3
  getElement,
4
4
  h,
5
5
  registerInstance
6
- } from "./chunk-NIPNHZ5W.js";
6
+ } from "./chunk-GDMQKT5F.js";
7
7
 
8
8
  // dist/esm/ui-top-bar.entry.js
9
9
  var uiTopBarCss = () => `:host{position:sticky;inset-block-start:0;z-index:var(--ui-top-bar-z-index, 100);display:block}.top-bar{min-block-size:calc(var(--ui-top-bar-height, 56px) + env(safe-area-inset-top));display:flex;align-items:center;gap:var(--ui-top-bar-gap, var(--ui-space-3, 0.75rem));padding-block-start:env(safe-area-inset-top);padding-inline-start:max( var(--ui-top-bar-padding-inline, var(--ui-space-4, 1rem)), env(safe-area-inset-left) );padding-inline-end:max( var(--ui-top-bar-padding-inline, var(--ui-space-4, 1rem)), env(safe-area-inset-right) );background:var(--ui-top-bar-bg, var(--ui-surface, #ffffff));border-block-end:1px solid var(--ui-top-bar-border, var(--ui-border, #e5e7eb))}.top-bar__leading,.top-bar__search,.top-bar__actions{display:flex;align-items:center;flex-shrink:0}.top-bar__actions{gap:var(--ui-top-bar-actions-gap, var(--ui-space-1, 0.25rem))}.top-bar__title{min-inline-size:0;flex:1}[hidden]{display:none}@media (min-width: 768px){:host{display:none}}`;
@@ -40,7 +40,7 @@ var UITopBar = class {
40
40
  this.hasActions = slotHasContent(this.actionsSlot);
41
41
  };
42
42
  render() {
43
- 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 }))));
43
+ 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 }))));
44
44
  }
45
45
  };
46
46
  UITopBar.style = uiTopBarCss();
@@ -7,7 +7,7 @@ import {
7
7
  getElement,
8
8
  h,
9
9
  registerInstance
10
- } from "./chunk-NIPNHZ5W.js";
10
+ } from "./chunk-GDMQKT5F.js";
11
11
 
12
12
  // dist/esm/ui-tree-item.entry.js
13
13
  var Bold = [
@@ -299,6 +299,10 @@ var UITreeItem = class {
299
299
  label = "";
300
300
  /** One-based visual and semantic nesting level. */
301
301
  depth = 1;
302
+ /** Application hierarchy depth used for drop constraints. Defaults to visual depth. */
303
+ dropDepth;
304
+ /** Deepest descendant distance, used with the tree's max-depth drop constraint. */
305
+ subtreeDepth;
302
306
  /** Whether this item accepts children and exposes disclosure behavior. */
303
307
  container = false;
304
308
  /** Whether this item participates in pointer drag and drop. */
@@ -360,10 +364,10 @@ var UITreeItem = class {
360
364
  const level = Math.max(1, Math.floor(this.depth));
361
365
  const disclosureLabel = `${this.internalExpanded ? "Collapse" : "Expand"} ${this.label || "item"}`;
362
366
  const dragLabel = `Drag ${this.label || "item"} to reorder`;
363
- return h(Host, { key: "ea8ed538aa3883c87257a25614a066965364693f", role: "treeitem", "aria-level": String(level), "aria-expanded": this.container ? String(this.internalExpanded) : void 0, "aria-selected": String(this.selected), "aria-disabled": this.disabled ? "true" : void 0, "data-container": this.container ? "" : void 0, "data-selected": this.selected ? "" : void 0, "data-disabled": this.disabled ? "" : void 0, "data-drag-type": this.dragType || "item", "data-drop-scope": this.dropScope || void 0, "data-accepts": this.accepts || void 0, tabIndex: this.disabled ? -1 : 0, style: {
367
+ return h(Host, { key: "606f5fdac8a95489d0c62cd7d4918c6d5d0c759e", role: "treeitem", "aria-level": String(level), "aria-expanded": this.container ? String(this.internalExpanded) : void 0, "aria-selected": String(this.selected), "aria-disabled": this.disabled ? "true" : void 0, "data-container": this.container ? "" : void 0, "data-selected": this.selected ? "" : void 0, "data-disabled": this.disabled ? "" : void 0, "data-drag-type": this.dragType || "item", "data-drop-scope": this.dropScope || void 0, "data-accepts": this.accepts || void 0, tabIndex: this.disabled ? -1 : 0, style: {
364
368
  "--ui-tree-item-depth": String(level - 1),
365
369
  "margin-inline-start": level > 1 ? "var(--ui-tree-indent, 16px)" : "0px"
366
- } }, 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" }));
370
+ } }, 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" }));
367
371
  }
368
372
  static get watchers() {
369
373
  return {
@@ -6,7 +6,7 @@ import {
6
6
  getElement,
7
7
  h,
8
8
  registerInstance
9
- } from "./chunk-NIPNHZ5W.js";
9
+ } from "./chunk-GDMQKT5F.js";
10
10
 
11
11
  // dist/esm/ui-tree.entry.js
12
12
  function classifyDropPosition(rect, clientY, acceptsChildren) {
@@ -62,9 +62,14 @@ var UITree = class {
62
62
  }
63
63
  label = "Tree";
64
64
  hoverExpandDelay = 700;
65
+ /** Maximum resulting item depth accepted by pointer reordering. Zero is unlimited. */
66
+ maxDepth = 0;
65
67
  source = null;
66
68
  target = null;
67
69
  position = null;
70
+ rejectedTarget = null;
71
+ rejectedPosition = null;
72
+ rejection = null;
68
73
  hoverIntent = null;
69
74
  componentDidLoad() {
70
75
  this.hoverIntent = createHoverIntent(this.hoverExpandDelay, this.expandTarget);
@@ -128,15 +133,37 @@ var UITree = class {
128
133
  accepts: (item.getAttribute("data-accepts") || item.getAttribute("accepts") || "").split(",").map((value) => value.trim()).filter(Boolean)
129
134
  };
130
135
  }
131
- permitsDrop(source, target, position) {
136
+ constraintDepth(item) {
137
+ if (item.dropDepth !== void 0)
138
+ return item.dropDepth;
139
+ const dropDepth = item.getAttribute("drop-depth");
140
+ if (dropDepth !== null)
141
+ return Number(dropDepth);
142
+ if (item.depth !== void 0)
143
+ return item.depth;
144
+ return Number(item.getAttribute("depth")) || 1;
145
+ }
146
+ dropRejection(source, target, position) {
132
147
  if (source.contains(target))
133
- return false;
148
+ return { reason: "descendant" };
134
149
  const sourceMeta = this.itemMetadata(source);
135
150
  const targetMeta = this.itemMetadata(target);
136
151
  if (position === "inside") {
137
- return this.acceptsChildren(target) && (targetMeta.accepts.length === 0 || targetMeta.accepts.includes(sourceMeta.type));
152
+ if (!this.acceptsChildren(target) || targetMeta.accepts.length > 0 && !targetMeta.accepts.includes(sourceMeta.type)) {
153
+ return { reason: "incompatible" };
154
+ }
155
+ } else if (sourceMeta.type !== targetMeta.type) {
156
+ return { reason: "incompatible" };
138
157
  }
139
- return sourceMeta.type === targetMeta.type;
158
+ const maxDepth = Math.max(0, Math.floor(this.maxDepth));
159
+ if (maxDepth > 0 && source.subtreeDepth !== void 0) {
160
+ const targetDepth = Math.max(0, Math.floor(this.constraintDepth(target)));
161
+ const subtreeDepth = Math.max(0, Math.floor(source.subtreeDepth));
162
+ const resultingDepth = targetDepth + (position === "inside" ? 1 : 0) + subtreeDepth;
163
+ if (resultingDepth > maxDepth)
164
+ return { reason: "max-depth", maxDepth, resultingDepth };
165
+ }
166
+ return null;
140
167
  }
141
168
  clearTarget() {
142
169
  this.target?.removeAttribute("data-drop-position");
@@ -144,10 +171,16 @@ var UITree = class {
144
171
  this.position = null;
145
172
  this.hoverIntent?.cancel();
146
173
  }
174
+ clearRejection() {
175
+ this.rejectedTarget = null;
176
+ this.rejectedPosition = null;
177
+ this.rejection = null;
178
+ }
147
179
  finishDrag() {
148
180
  this.source?.removeAttribute("data-dragging");
149
181
  this.source = null;
150
182
  this.clearTarget();
183
+ this.clearRejection();
151
184
  }
152
185
  expandTarget = (itemId) => {
153
186
  const item = Array.from(this.host.querySelectorAll("ui-tree-item")).find((candidate) => this.itemId(candidate) === itemId);
@@ -183,18 +216,28 @@ var UITree = class {
183
216
  return false;
184
217
  if (!target || target === this.source) {
185
218
  this.clearTarget();
219
+ this.clearRejection();
186
220
  return false;
187
221
  }
188
222
  const row = this.rowFor(target);
189
223
  if (!row)
190
224
  return false;
191
225
  const position = classifyDropPosition(row.getBoundingClientRect(), clientY, this.acceptsChildren(target));
192
- if (!this.permitsDrop(this.source, target, position)) {
226
+ const rejection = this.dropRejection(this.source, target, position);
227
+ if (rejection) {
193
228
  if (dataTransfer)
194
229
  dataTransfer.dropEffect = "none";
195
230
  this.clearTarget();
231
+ if (rejection.reason === "max-depth") {
232
+ this.rejectedTarget = target;
233
+ this.rejectedPosition = position;
234
+ this.rejection = rejection;
235
+ } else {
236
+ this.clearRejection();
237
+ }
196
238
  return false;
197
239
  }
240
+ this.clearRejection();
198
241
  if (dataTransfer)
199
242
  dataTransfer.dropEffect = "move";
200
243
  if (this.target !== target || this.position !== position) {
@@ -231,12 +274,15 @@ var UITree = class {
231
274
  if (this.itemAtPoint(event.clientX, event.clientY))
232
275
  return;
233
276
  this.clearTarget();
277
+ this.clearRejection();
234
278
  };
235
279
  dispatchReorder(source, target, position) {
236
280
  const sourceId = this.itemId(source);
237
281
  const targetId = this.itemId(target);
238
282
  if (!sourceId || !targetId)
239
283
  return;
284
+ if (position === "inside")
285
+ this.expandTarget(targetId);
240
286
  const sourceMeta = this.itemMetadata(source);
241
287
  const targetMeta = this.itemMetadata(target);
242
288
  dispatchDetail(this.host, "reorder", {
@@ -250,6 +296,21 @@ var UITree = class {
250
296
  trigger: "pointer"
251
297
  });
252
298
  }
299
+ dispatchReorderRejected(source, target, position, rejection) {
300
+ const sourceId = this.itemId(source);
301
+ const targetId = this.itemId(target);
302
+ if (!sourceId || !targetId)
303
+ return;
304
+ dispatchDetail(this.host, "reorder-rejected", {
305
+ sourceId,
306
+ targetId,
307
+ position,
308
+ reason: "max-depth",
309
+ maxDepth: rejection.maxDepth,
310
+ resultingDepth: rejection.resultingDepth,
311
+ trigger: "pointer"
312
+ });
313
+ }
253
314
  onDrop = (event) => {
254
315
  if (!this.source || !this.target || !this.position)
255
316
  return;
@@ -259,13 +320,21 @@ var UITree = class {
259
320
  };
260
321
  onDragEnd = (event) => {
261
322
  if (this.source) {
323
+ if (this.rejectedTarget && this.rejectedPosition && this.rejection) {
324
+ this.dispatchReorderRejected(this.source, this.rejectedTarget, this.rejectedPosition, this.rejection);
325
+ this.finishDrag();
326
+ return;
327
+ }
262
328
  const target = this.itemAtPoint(event.clientX, event.clientY);
263
329
  if (target && target !== this.source) {
264
330
  const row = this.rowFor(target);
265
331
  if (row) {
266
332
  const position = classifyDropPosition(row.getBoundingClientRect(), event.clientY, this.acceptsChildren(target));
267
- if (this.permitsDrop(this.source, target, position)) {
333
+ const rejection = this.dropRejection(this.source, target, position);
334
+ if (!rejection) {
268
335
  this.dispatchReorder(this.source, target, position);
336
+ } else if (rejection.reason === "max-depth") {
337
+ this.dispatchReorderRejected(this.source, target, position, rejection);
269
338
  }
270
339
  }
271
340
  }
@@ -290,7 +359,7 @@ var UITree = class {
290
359
  next.focus();
291
360
  };
292
361
  render() {
293
- return h(Host, { key: "7da064127eb199f5e2cfc59489a07204c9dac2f2", role: "tree", "aria-label": this.label || "Tree" }, h("slot", { key: "31a98a6774ab35e565dab65f1dd8202494432b32" }));
362
+ return h(Host, { key: "474c2154d2abe3c76eee9c36bf552390089df6e8", role: "tree", "aria-label": this.label || "Tree" }, h("slot", { key: "93aedd02f984dd33b5efc811fef417d1199917bd" }));
294
363
  }
295
364
  };
296
365
  UITree.style = uiTreeCss();
@@ -0,0 +1,52 @@
1
+ import { GenericSchema, GenericSchemaAsync, InferOutput } from 'valibot';
2
+
3
+ /** Structural Standard Schema v1 boundary; no schema-library runtime dependency. */
4
+ interface FieldSchema<Output = unknown> {
5
+ readonly '~standard': {
6
+ readonly version: 1;
7
+ readonly vendor: string;
8
+ readonly validate: (value: unknown) => FieldSchemaResult<Output> | Promise<FieldSchemaResult<Output>>;
9
+ readonly types?: {
10
+ readonly input: unknown;
11
+ readonly output: Output;
12
+ };
13
+ };
14
+ }
15
+ interface FieldIssue {
16
+ readonly message: string;
17
+ readonly path?: ReadonlyArray<PropertyKey | {
18
+ readonly key: PropertyKey;
19
+ }>;
20
+ readonly severity?: 'error' | 'warning';
21
+ }
22
+ type FieldSchemaResult<T = unknown> = {
23
+ readonly value: T;
24
+ readonly issues?: undefined;
25
+ } | {
26
+ readonly issues: readonly FieldIssue[];
27
+ };
28
+ interface FieldRequest<Context = unknown> {
29
+ raw: string;
30
+ value: string | null;
31
+ context: Context;
32
+ signal: AbortSignal;
33
+ }
34
+ interface FieldResult<Output = unknown> {
35
+ output?: Output;
36
+ issues: readonly FieldIssue[];
37
+ }
38
+ interface FieldValidation {
39
+ schema?: FieldSchema;
40
+ parse?: (raw: string, request: FieldRequest) => unknown | Promise<unknown>;
41
+ normalize?: (value: unknown, request: FieldRequest) => unknown | Promise<unknown>;
42
+ validator?: (value: unknown, request: FieldRequest) => Partial<FieldResult> | Promise<Partial<FieldResult>>;
43
+ issues?: readonly FieldIssue[];
44
+ }
45
+
46
+ /** Valibot's Standard Schema implementation preserves async transforms and issue paths.
47
+ * Type-only Valibot imports keep the adapter free of a schema-library runtime. */
48
+ declare function valibotField<T extends GenericSchema | GenericSchemaAsync>(schema: T, options?: Omit<FieldValidation, 'schema'>): FieldValidation & {
49
+ schema: FieldSchema<InferOutput<T>>;
50
+ };
51
+
52
+ export { valibotField };
@@ -0,0 +1,7 @@
1
+ // src/field/valibot.ts
2
+ function valibotField(schema, options = {}) {
3
+ return { ...options, schema };
4
+ }
5
+ export {
6
+ valibotField
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "type": "module",
5
5
  "description": "Looma web components, responsive layout primitives, a complete editor, and supported Vue adapters.",
6
6
  "license": "MIT",
@@ -67,7 +67,11 @@
67
67
  "./theme-high-contrast.css": "./theme-high-contrast.css",
68
68
  "./layout.css": "./layout.css",
69
69
  "./styles.css": "./styles.css",
70
- "./editor.css": "./editor.css"
70
+ "./editor.css": "./editor.css",
71
+ "./valibot": {
72
+ "types": "./dist/valibot.d.ts",
73
+ "import": "./dist/valibot.js"
74
+ }
71
75
  },
72
76
  "files": [
73
77
  "dist/",
@@ -101,7 +105,8 @@
101
105
  "@tiptap/core": ">=2 <3",
102
106
  "@tiptap/pm": ">=2 <3",
103
107
  "@tiptap/vue-3": ">=2 <3",
104
- "vue": "^3.5.0"
108
+ "vue": "^3.5.0",
109
+ "valibot": "^1.1.0"
105
110
  },
106
111
  "peerDependenciesMeta": {
107
112
  "@tiptap/core": {
@@ -115,6 +120,9 @@
115
120
  },
116
121
  "vue": {
117
122
  "optional": true
123
+ },
124
+ "valibot": {
125
+ "optional": true
118
126
  }
119
127
  },
120
128
  "engines": {
package/styles.css CHANGED
@@ -194,14 +194,19 @@
194
194
  ui-button {
195
195
  display: inline-flex;
196
196
  vertical-align: middle;
197
- color: var(--ui-text-primary);
197
+ color: var(--ui-action-secondary-text, var(--ui-text-primary));
198
+ }
199
+
200
+ ui-button[variant="solid"] {
201
+ color: var(--ui-action-primary-text, var(--ui-text-on-accent));
198
202
  }
199
203
 
200
204
  ui-button > button {
201
205
  appearance: none;
202
- border: 1px solid var(--ui-border-default);
206
+ min-block-size: var(--ui-button-min-block-size, 2.5rem);
207
+ border: 1px solid var(--ui-control-border, var(--ui-border-default));
203
208
  border-radius: var(--ui-button-radius, var(--ui-radius-2));
204
- background: var(--ui-surface-default);
209
+ background: var(--ui-action-secondary-surface, var(--ui-surface-default));
205
210
  color: inherit;
206
211
  font: inherit;
207
212
  font-weight: var(--ui-font-medium, 500);
@@ -223,13 +228,14 @@
223
228
  }
224
229
 
225
230
  ui-button[data-size="lg"] > button {
231
+ min-block-size: var(--ui-control-min-block-size, 2.75rem);
226
232
  padding: var(--ui-space-3) var(--ui-space-4);
227
233
  font-size: 1rem;
228
234
  }
229
235
 
230
236
  ui-button > button:hover:enabled {
231
- background: var(--ui-surface-muted);
232
- border-color: var(--ui-border-strong);
237
+ background: var(--ui-action-secondary-surface-hover, var(--ui-surface-muted));
238
+ border-color: var(--ui-control-border-hover, var(--ui-border-strong));
233
239
  }
234
240
 
235
241
  ui-button > button:active:enabled {
@@ -237,22 +243,22 @@
237
243
  }
238
244
 
239
245
  ui-button[variant="solid"] > button {
240
- border-color: var(--ui-accent-solid);
241
- background: var(--ui-accent-solid);
242
- color: var(--ui-text-on-accent);
246
+ border-color: var(--ui-action-primary-surface, var(--ui-accent-solid));
247
+ background: var(--ui-action-primary-surface, var(--ui-accent-solid));
248
+ color: var(--ui-action-primary-text, var(--ui-text-on-accent));
243
249
  box-shadow: var(--ui-button-solid-shadow, inset 0 1px rgb(255 255 255 / 0.16), var(--ui-shadow-xs));
244
250
  }
245
251
 
246
252
  ui-button[variant="solid"] > button:hover:enabled {
247
- background: var(--ui-accent-hover);
248
- border-color: var(--ui-accent-hover);
253
+ background: var(--ui-action-primary-surface-hover, var(--ui-accent-hover));
254
+ border-color: var(--ui-action-primary-surface-hover, var(--ui-accent-hover));
249
255
  box-shadow: var(--ui-shadow-sm);
250
256
  transform: translateY(-1px);
251
257
  }
252
258
 
253
259
  ui-button[variant="solid"] > button:active:enabled {
254
- background: var(--ui-accent-active);
255
- border-color: var(--ui-accent-active);
260
+ background: var(--ui-action-primary-surface-active, var(--ui-accent-active));
261
+ border-color: var(--ui-action-primary-surface-active, var(--ui-accent-active));
256
262
  box-shadow: none;
257
263
  transform: translateY(0);
258
264
  }
@@ -299,23 +305,29 @@
299
305
  outline-offset: 2px;
300
306
  }
301
307
 
302
- ui-button > button:disabled,
303
- ui-button[data-disabled] {
308
+ ui-button[data-disabled="true"],
309
+ ui-button[disabled] {
304
310
  opacity: 0.6;
305
311
  cursor: not-allowed;
306
312
  }
307
313
 
314
+ ui-button > button:disabled {
315
+ cursor: not-allowed;
316
+ }
317
+
308
318
  ui-input {
309
319
  display: inline-flex;
320
+ min-inline-size: 0;
310
321
  color: var(--ui-text-primary);
311
322
  }
312
323
 
313
324
  ui-input > input {
314
325
  width: 100%;
315
326
  appearance: none;
316
- border: 1px solid var(--ui-border-default);
327
+ min-block-size: var(--ui-control-min-block-size, 2.75rem);
328
+ border: 1px solid var(--ui-control-border, var(--ui-border-default));
317
329
  border-radius: var(--ui-radius-2);
318
- background: var(--ui-surface-default);
330
+ background: var(--ui-control-surface, var(--ui-surface-default));
319
331
  color: inherit;
320
332
  font: inherit;
321
333
  line-height: var(--ui-line-height-md);
@@ -328,12 +340,12 @@
328
340
  }
329
341
 
330
342
  ui-input > input:hover:not(:focus):not(:disabled) {
331
- border-color: var(--ui-border-strong);
343
+ border-color: var(--ui-control-border-hover, var(--ui-border-strong));
332
344
  }
333
345
 
334
346
  ui-input > input:focus {
335
- border-color: var(--ui-focus-ring);
336
- box-shadow: 0 0 0 3px var(--ui-accent-soft);
347
+ border-color: var(--ui-control-focus, var(--ui-focus-ring));
348
+ box-shadow: 0 0 0 3px var(--ui-control-focus-halo, var(--ui-accent-soft));
337
349
  }
338
350
 
339
351
  ui-input[invalid] > input,
@@ -344,7 +356,7 @@
344
356
  }
345
357
 
346
358
  ui-input > input:disabled {
347
- background: var(--ui-surface-muted);
359
+ background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
348
360
  color: var(--ui-text-muted);
349
361
  cursor: not-allowed;
350
362
  }
@@ -352,6 +364,8 @@
352
364
  ui-form-field {
353
365
  display: grid;
354
366
  gap: var(--ui-space-2);
367
+ min-inline-size: 0;
368
+ align-content: start;
355
369
  color: var(--ui-text-primary);
356
370
  }
357
371
 
@@ -361,8 +375,10 @@
361
375
  }
362
376
 
363
377
  ui-form-field [data-slot="help"] {
378
+ min-block-size: var(--ui-form-field-help-min-block-size, 0);
364
379
  color: var(--ui-text-muted);
365
380
  font-size: 0.875rem;
381
+ line-height: var(--ui-line-height-md);
366
382
  }
367
383
 
368
384
  ui-form-field [data-slot="error"],