stimeo-ui 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +8 -1
  3. package/dist/cable/index.d.ts +79 -23
  4. package/dist/cable/index.js +363 -436
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/controllers/accordion_controller.d.ts +4 -2
  7. package/dist/controllers/accordion_controller.js +166 -55
  8. package/dist/controllers/accordion_controller.js.map +1 -1
  9. package/dist/controllers/alert_dialog_controller.d.ts +12 -2
  10. package/dist/controllers/alert_dialog_controller.js +862 -221
  11. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  12. package/dist/controllers/announcer_controller.d.ts +35 -5
  13. package/dist/controllers/announcer_controller.js +135 -198
  14. package/dist/controllers/announcer_controller.js.map +1 -1
  15. package/dist/controllers/aspect_ratio_controller.js +0 -10
  16. package/dist/controllers/aspect_ratio_controller.js.map +1 -1
  17. package/dist/controllers/auto_submit_controller.d.ts +30 -6
  18. package/dist/controllers/auto_submit_controller.js +271 -127
  19. package/dist/controllers/auto_submit_controller.js.map +1 -1
  20. package/dist/controllers/avatar_controller.js +171 -105
  21. package/dist/controllers/avatar_controller.js.map +1 -1
  22. package/dist/controllers/breadcrumb_controller.js +0 -130
  23. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  24. package/dist/controllers/bulk_select_controller.d.ts +18 -0
  25. package/dist/controllers/bulk_select_controller.js +262 -52
  26. package/dist/controllers/bulk_select_controller.js.map +1 -1
  27. package/dist/controllers/calendar_controller.d.ts +24 -5
  28. package/dist/controllers/calendar_controller.js +175 -209
  29. package/dist/controllers/calendar_controller.js.map +1 -1
  30. package/dist/controllers/carousel_controller.d.ts +34 -7
  31. package/dist/controllers/carousel_controller.js +461 -399
  32. package/dist/controllers/carousel_controller.js.map +1 -1
  33. package/dist/controllers/character_counter_controller.d.ts +17 -1
  34. package/dist/controllers/character_counter_controller.js +246 -156
  35. package/dist/controllers/character_counter_controller.js.map +1 -1
  36. package/dist/controllers/checkbox_controller.d.ts +7 -2
  37. package/dist/controllers/checkbox_controller.js +32 -74
  38. package/dist/controllers/checkbox_controller.js.map +1 -1
  39. package/dist/controllers/clipboard_controller.d.ts +16 -5
  40. package/dist/controllers/clipboard_controller.js +168 -147
  41. package/dist/controllers/clipboard_controller.js.map +1 -1
  42. package/dist/controllers/collapsible_controller.d.ts +16 -4
  43. package/dist/controllers/collapsible_controller.js +301 -120
  44. package/dist/controllers/collapsible_controller.js.map +1 -1
  45. package/dist/controllers/color_picker_controller.d.ts +18 -6
  46. package/dist/controllers/color_picker_controller.js +149 -139
  47. package/dist/controllers/color_picker_controller.js.map +1 -1
  48. package/dist/controllers/combobox_controller.d.ts +23 -5
  49. package/dist/controllers/combobox_controller.js +360 -133
  50. package/dist/controllers/combobox_controller.js.map +1 -1
  51. package/dist/controllers/command_palette_controller.d.ts +45 -14
  52. package/dist/controllers/command_palette_controller.js +970 -358
  53. package/dist/controllers/command_palette_controller.js.map +1 -1
  54. package/dist/controllers/conditional_fields_controller.d.ts +15 -2
  55. package/dist/controllers/conditional_fields_controller.js +166 -124
  56. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  57. package/dist/controllers/confirm_controller.d.ts +49 -12
  58. package/dist/controllers/confirm_controller.js +939 -248
  59. package/dist/controllers/confirm_controller.js.map +1 -1
  60. package/dist/controllers/context_menu_controller.d.ts +31 -4
  61. package/dist/controllers/context_menu_controller.js +256 -128
  62. package/dist/controllers/context_menu_controller.js.map +1 -1
  63. package/dist/controllers/count_up_controller.d.ts +13 -1
  64. package/dist/controllers/count_up_controller.js +73 -21
  65. package/dist/controllers/count_up_controller.js.map +1 -1
  66. package/dist/controllers/countdown_controller.d.ts +45 -1
  67. package/dist/controllers/countdown_controller.js +183 -148
  68. package/dist/controllers/countdown_controller.js.map +1 -1
  69. package/dist/controllers/currency_input_controller.d.ts +21 -2
  70. package/dist/controllers/currency_input_controller.js +134 -158
  71. package/dist/controllers/currency_input_controller.js.map +1 -1
  72. package/dist/controllers/data_grid_controller.d.ts +15 -4
  73. package/dist/controllers/data_grid_controller.js +114 -186
  74. package/dist/controllers/data_grid_controller.js.map +1 -1
  75. package/dist/controllers/date_range_picker_controller.d.ts +30 -5
  76. package/dist/controllers/date_range_picker_controller.js +288 -206
  77. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  78. package/dist/controllers/dialog_controller.d.ts +13 -1
  79. package/dist/controllers/dialog_controller.js +858 -223
  80. package/dist/controllers/dialog_controller.js.map +1 -1
  81. package/dist/controllers/direct_upload_controller.d.ts +24 -7
  82. package/dist/controllers/direct_upload_controller.js +73 -153
  83. package/dist/controllers/direct_upload_controller.js.map +1 -1
  84. package/dist/controllers/dirty_form_controller.js +14 -48
  85. package/dist/controllers/dirty_form_controller.js.map +1 -1
  86. package/dist/controllers/dismissible_controller.d.ts +19 -0
  87. package/dist/controllers/dismissible_controller.js +175 -21
  88. package/dist/controllers/dismissible_controller.js.map +1 -1
  89. package/dist/controllers/drawer_controller.d.ts +39 -11
  90. package/dist/controllers/drawer_controller.js +933 -341
  91. package/dist/controllers/drawer_controller.js.map +1 -1
  92. package/dist/controllers/dropdown_controller.d.ts +31 -1
  93. package/dist/controllers/dropdown_controller.js +312 -82
  94. package/dist/controllers/dropdown_controller.js.map +1 -1
  95. package/dist/controllers/editable_controller.d.ts +12 -1
  96. package/dist/controllers/editable_controller.js +158 -68
  97. package/dist/controllers/editable_controller.js.map +1 -1
  98. package/dist/controllers/empty_state_controller.js +67 -53
  99. package/dist/controllers/empty_state_controller.js.map +1 -1
  100. package/dist/controllers/file_dropzone_controller.d.ts +60 -18
  101. package/dist/controllers/file_dropzone_controller.js +311 -207
  102. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  103. package/dist/controllers/filter_controller.js +67 -39
  104. package/dist/controllers/filter_controller.js.map +1 -1
  105. package/dist/controllers/flash_controller.d.ts +31 -8
  106. package/dist/controllers/flash_controller.js +172 -314
  107. package/dist/controllers/flash_controller.js.map +1 -1
  108. package/dist/controllers/focus_controller.d.ts +12 -3
  109. package/dist/controllers/focus_controller.js +654 -240
  110. package/dist/controllers/focus_controller.js.map +1 -1
  111. package/dist/controllers/form_field_controller.js +147 -132
  112. package/dist/controllers/form_field_controller.js.map +1 -1
  113. package/dist/controllers/form_validation_controller.js +13 -86
  114. package/dist/controllers/form_validation_controller.js.map +1 -1
  115. package/dist/controllers/frame_loading_controller.d.ts +41 -9
  116. package/dist/controllers/frame_loading_controller.js +264 -213
  117. package/dist/controllers/frame_loading_controller.js.map +1 -1
  118. package/dist/controllers/highlight_controller.d.ts +22 -2
  119. package/dist/controllers/highlight_controller.js +107 -75
  120. package/dist/controllers/highlight_controller.js.map +1 -1
  121. package/dist/controllers/hover_card_controller.d.ts +56 -3
  122. package/dist/controllers/hover_card_controller.js +309 -118
  123. package/dist/controllers/hover_card_controller.js.map +1 -1
  124. package/dist/controllers/idle_controller.d.ts +42 -1
  125. package/dist/controllers/idle_controller.js +267 -101
  126. package/dist/controllers/idle_controller.js.map +1 -1
  127. package/dist/controllers/input_mask_controller.js +71 -72
  128. package/dist/controllers/input_mask_controller.js.map +1 -1
  129. package/dist/controllers/intersection_controller.d.ts +32 -13
  130. package/dist/controllers/intersection_controller.js +147 -106
  131. package/dist/controllers/intersection_controller.js.map +1 -1
  132. package/dist/controllers/lazy_frame_controller.d.ts +16 -0
  133. package/dist/controllers/lazy_frame_controller.js +9 -65
  134. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  135. package/dist/controllers/listbox_controller.d.ts +34 -2
  136. package/dist/controllers/listbox_controller.js +306 -204
  137. package/dist/controllers/listbox_controller.js.map +1 -1
  138. package/dist/controllers/local_time_controller.d.ts +1 -1
  139. package/dist/controllers/local_time_controller.js +54 -64
  140. package/dist/controllers/local_time_controller.js.map +1 -1
  141. package/dist/controllers/masonry_controller.d.ts +11 -3
  142. package/dist/controllers/masonry_controller.js +70 -93
  143. package/dist/controllers/masonry_controller.js.map +1 -1
  144. package/dist/controllers/menu_controller.d.ts +32 -7
  145. package/dist/controllers/menu_controller.js +214 -156
  146. package/dist/controllers/menu_controller.js.map +1 -1
  147. package/dist/controllers/menubar_controller.d.ts +4 -4
  148. package/dist/controllers/menubar_controller.js +170 -329
  149. package/dist/controllers/menubar_controller.js.map +1 -1
  150. package/dist/controllers/meter_controller.d.ts +20 -0
  151. package/dist/controllers/meter_controller.js +151 -67
  152. package/dist/controllers/meter_controller.js.map +1 -1
  153. package/dist/controllers/multi_select_controller.d.ts +32 -4
  154. package/dist/controllers/multi_select_controller.js +593 -358
  155. package/dist/controllers/multi_select_controller.js.map +1 -1
  156. package/dist/controllers/navigation_menu_controller.d.ts +8 -1
  157. package/dist/controllers/navigation_menu_controller.js +124 -232
  158. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  159. package/dist/controllers/nested_form_controller.d.ts +10 -0
  160. package/dist/controllers/nested_form_controller.js +352 -182
  161. package/dist/controllers/nested_form_controller.js.map +1 -1
  162. package/dist/controllers/network_status_controller.d.ts +23 -0
  163. package/dist/controllers/network_status_controller.js +242 -54
  164. package/dist/controllers/network_status_controller.js.map +1 -1
  165. package/dist/controllers/number_input_controller.d.ts +26 -2
  166. package/dist/controllers/number_input_controller.js +320 -263
  167. package/dist/controllers/number_input_controller.js.map +1 -1
  168. package/dist/controllers/optimistic_controller.js +16 -76
  169. package/dist/controllers/optimistic_controller.js.map +1 -1
  170. package/dist/controllers/otp_controller.d.ts +20 -4
  171. package/dist/controllers/otp_controller.js +198 -193
  172. package/dist/controllers/otp_controller.js.map +1 -1
  173. package/dist/controllers/overflow_indicator_controller.d.ts +5 -0
  174. package/dist/controllers/overflow_indicator_controller.js +116 -113
  175. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  176. package/dist/controllers/overflow_menu_controller.d.ts +48 -11
  177. package/dist/controllers/overflow_menu_controller.js +343 -283
  178. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  179. package/dist/controllers/pagination_controller.d.ts +35 -6
  180. package/dist/controllers/pagination_controller.js +295 -119
  181. package/dist/controllers/pagination_controller.js.map +1 -1
  182. package/dist/controllers/password_reveal_controller.d.ts +45 -8
  183. package/dist/controllers/password_reveal_controller.js +389 -121
  184. package/dist/controllers/password_reveal_controller.js.map +1 -1
  185. package/dist/controllers/password_strength_controller.d.ts +14 -5
  186. package/dist/controllers/password_strength_controller.js +99 -153
  187. package/dist/controllers/password_strength_controller.js.map +1 -1
  188. package/dist/controllers/persist_controller.d.ts +11 -4
  189. package/dist/controllers/persist_controller.js +237 -103
  190. package/dist/controllers/persist_controller.js.map +1 -1
  191. package/dist/controllers/pointer_drag_controller.d.ts +19 -7
  192. package/dist/controllers/pointer_drag_controller.js +185 -165
  193. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  194. package/dist/controllers/popover_controller.d.ts +38 -2
  195. package/dist/controllers/popover_controller.js +236 -97
  196. package/dist/controllers/popover_controller.js.map +1 -1
  197. package/dist/controllers/portal_controller.d.ts +44 -4
  198. package/dist/controllers/portal_controller.js +209 -76
  199. package/dist/controllers/portal_controller.js.map +1 -1
  200. package/dist/controllers/preview_guard_controller.d.ts +10 -4
  201. package/dist/controllers/preview_guard_controller.js +232 -116
  202. package/dist/controllers/preview_guard_controller.js.map +1 -1
  203. package/dist/controllers/progress_controller.d.ts +11 -0
  204. package/dist/controllers/progress_controller.js +125 -56
  205. package/dist/controllers/progress_controller.js.map +1 -1
  206. package/dist/controllers/radio_group_controller.d.ts +14 -5
  207. package/dist/controllers/radio_group_controller.js +117 -137
  208. package/dist/controllers/radio_group_controller.js.map +1 -1
  209. package/dist/controllers/range_slider_controller.d.ts +43 -3
  210. package/dist/controllers/range_slider_controller.js +192 -105
  211. package/dist/controllers/range_slider_controller.js.map +1 -1
  212. package/dist/controllers/rating_controller.d.ts +20 -4
  213. package/dist/controllers/rating_controller.js +418 -207
  214. package/dist/controllers/rating_controller.js.map +1 -1
  215. package/dist/controllers/read_more_controller.d.ts +2 -0
  216. package/dist/controllers/read_more_controller.js +134 -63
  217. package/dist/controllers/read_more_controller.js.map +1 -1
  218. package/dist/controllers/reading_progress_controller.d.ts +1 -1
  219. package/dist/controllers/reading_progress_controller.js +147 -135
  220. package/dist/controllers/reading_progress_controller.js.map +1 -1
  221. package/dist/controllers/relative_time_controller.d.ts +18 -4
  222. package/dist/controllers/relative_time_controller.js +145 -110
  223. package/dist/controllers/relative_time_controller.js.map +1 -1
  224. package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
  225. package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +97 -38
  226. package/dist/controllers/reset_on_restore_controller.js.map +1 -0
  227. package/dist/controllers/resizable_controller.d.ts +28 -2
  228. package/dist/controllers/resizable_controller.js +255 -139
  229. package/dist/controllers/resizable_controller.js.map +1 -1
  230. package/dist/controllers/roving_controller.js +39 -84
  231. package/dist/controllers/roving_controller.js.map +1 -1
  232. package/dist/controllers/scroll_area_controller.d.ts +7 -3
  233. package/dist/controllers/scroll_area_controller.js +428 -225
  234. package/dist/controllers/scroll_area_controller.js.map +1 -1
  235. package/dist/controllers/scroll_restore_controller.js +0 -53
  236. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  237. package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
  238. package/dist/controllers/scroll_visibility_controller.js +395 -145
  239. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  240. package/dist/controllers/scrollspy_controller.d.ts +6 -1
  241. package/dist/controllers/scrollspy_controller.js +181 -242
  242. package/dist/controllers/scrollspy_controller.js.map +1 -1
  243. package/dist/controllers/separator_controller.d.ts +19 -4
  244. package/dist/controllers/separator_controller.js +267 -140
  245. package/dist/controllers/separator_controller.js.map +1 -1
  246. package/dist/controllers/sidebar_controller.d.ts +64 -7
  247. package/dist/controllers/sidebar_controller.js +1023 -386
  248. package/dist/controllers/sidebar_controller.js.map +1 -1
  249. package/dist/controllers/skeleton_controller.d.ts +23 -0
  250. package/dist/controllers/skeleton_controller.js +248 -97
  251. package/dist/controllers/skeleton_controller.js.map +1 -1
  252. package/dist/controllers/slider_controller.d.ts +27 -1
  253. package/dist/controllers/slider_controller.js +159 -79
  254. package/dist/controllers/slider_controller.js.map +1 -1
  255. package/dist/controllers/smart_sticky_header_controller.d.ts +21 -3
  256. package/dist/controllers/smart_sticky_header_controller.js +162 -63
  257. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  258. package/dist/controllers/sortable_controller.js +0 -112
  259. package/dist/controllers/sortable_controller.js.map +1 -1
  260. package/dist/controllers/spinner_controller.d.ts +39 -4
  261. package/dist/controllers/spinner_controller.js +277 -169
  262. package/dist/controllers/spinner_controller.js.map +1 -1
  263. package/dist/controllers/step_indicator_controller.d.ts +5 -0
  264. package/dist/controllers/step_indicator_controller.js +99 -46
  265. package/dist/controllers/step_indicator_controller.js.map +1 -1
  266. package/dist/controllers/stepper_controller.d.ts +12 -3
  267. package/dist/controllers/stepper_controller.js +114 -73
  268. package/dist/controllers/stepper_controller.js.map +1 -1
  269. package/dist/controllers/stick_to_bottom_controller.d.ts +6 -0
  270. package/dist/controllers/stick_to_bottom_controller.js +262 -138
  271. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  272. package/dist/controllers/sticky_observer_controller.d.ts +11 -0
  273. package/dist/controllers/sticky_observer_controller.js +214 -49
  274. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  275. package/dist/controllers/submit_once_controller.d.ts +23 -8
  276. package/dist/controllers/submit_once_controller.js +294 -205
  277. package/dist/controllers/submit_once_controller.js.map +1 -1
  278. package/dist/controllers/switch_controller.d.ts +12 -1
  279. package/dist/controllers/switch_controller.js +33 -60
  280. package/dist/controllers/switch_controller.js.map +1 -1
  281. package/dist/controllers/tabs_controller.d.ts +2 -2
  282. package/dist/controllers/tabs_controller.js +35 -29
  283. package/dist/controllers/tabs_controller.js.map +1 -1
  284. package/dist/controllers/tags_input_controller.d.ts +12 -0
  285. package/dist/controllers/tags_input_controller.js +136 -145
  286. package/dist/controllers/tags_input_controller.js.map +1 -1
  287. package/dist/controllers/textarea_autosize_controller.d.ts +10 -0
  288. package/dist/controllers/textarea_autosize_controller.js +71 -58
  289. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  290. package/dist/controllers/theme_controller.d.ts +21 -9
  291. package/dist/controllers/theme_controller.js +130 -112
  292. package/dist/controllers/theme_controller.js.map +1 -1
  293. package/dist/controllers/time_picker_controller.d.ts +18 -1
  294. package/dist/controllers/time_picker_controller.js +146 -80
  295. package/dist/controllers/time_picker_controller.js.map +1 -1
  296. package/dist/controllers/toast_controller.d.ts +36 -11
  297. package/dist/controllers/toast_controller.js +186 -297
  298. package/dist/controllers/toast_controller.js.map +1 -1
  299. package/dist/controllers/toggle_group_controller.d.ts +12 -3
  300. package/dist/controllers/toggle_group_controller.js +95 -136
  301. package/dist/controllers/toggle_group_controller.js.map +1 -1
  302. package/dist/controllers/toolbar_controller.js +68 -98
  303. package/dist/controllers/toolbar_controller.js.map +1 -1
  304. package/dist/controllers/tooltip_controller.d.ts +45 -3
  305. package/dist/controllers/tooltip_controller.js +158 -124
  306. package/dist/controllers/tooltip_controller.js.map +1 -1
  307. package/dist/controllers/transition_controller.d.ts +22 -4
  308. package/dist/controllers/transition_controller.js +123 -119
  309. package/dist/controllers/transition_controller.js.map +1 -1
  310. package/dist/controllers/tree_view_controller.d.ts +21 -11
  311. package/dist/controllers/tree_view_controller.js +150 -345
  312. package/dist/controllers/tree_view_controller.js.map +1 -1
  313. package/dist/index.d.ts +8 -5
  314. package/dist/index.js +6370 -9346
  315. package/dist/index.js.map +1 -1
  316. package/dist/inspector/cli.d.ts +23 -3
  317. package/dist/inspector/cli.js +92 -37
  318. package/dist/inspector/cli.js.map +1 -1
  319. package/dist/inspector/cli_bin.js +92 -56
  320. package/dist/inspector/cli_bin.js.map +1 -1
  321. package/dist/inspector/examples.json +8 -8
  322. package/dist/inspector/manifest.json +787 -100
  323. package/dist/positioning/index.d.ts +8 -0
  324. package/dist/positioning/index.js +148 -47
  325. package/dist/positioning/index.js.map +1 -1
  326. package/package.json +6 -6
  327. package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
  328. package/dist/controllers/reset_before_cache_controller.js.map +0 -1
@@ -1,20 +1,158 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
3
- // src/controllers/hover_card_controller.ts
3
+ function sharedRegistry(key, create) {
4
+ const symbol = Symbol.for(key);
5
+ const scope = globalThis;
6
+ const existing = scope[symbol];
7
+ if (existing !== void 0) return existing;
8
+ const registry = create();
9
+ Object.defineProperty(globalThis, symbol, { value: registry });
10
+ return registry;
11
+ }
12
+
13
+ function isAttributeValue(value) {
14
+ return value === null || typeof value === "string";
15
+ }
16
+ function readLeaseRecord(element, record) {
17
+ try {
18
+ const parsed = JSON.parse(element.getAttribute(record) ?? "null");
19
+ if (!Array.isArray(parsed)) return void 0;
20
+ const [original, written, ...rest] = parsed;
21
+ const linked = rest[0] !== false;
22
+ const beneath = linked ? rest : rest.slice(1);
23
+ if (!beneath.every((under) => typeof under === "string")) return void 0;
24
+ return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
25
+ } catch {
26
+ return void 0;
27
+ }
28
+ }
29
+ var AttributeLease = class _AttributeLease {
30
+ static #registry = sharedRegistry(
31
+ "stimeo-ui.attribute-lease.registry.v1",
32
+ () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
33
+ );
34
+ #attribute;
35
+ #record;
36
+ #base;
37
+ #held = /* @__PURE__ */ new Set();
38
+ constructor(attribute, owner, options = {}) {
39
+ this.#attribute = attribute;
40
+ this.#record = `data-${owner}-${attribute}-lease`;
41
+ this.#base = options.base === true;
42
+ const names = _AttributeLease.#registry.names;
43
+ names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
44
+ }
45
+ write(element, value) {
46
+ const stack = this.#stack(element);
47
+ const hold = this.#take(stack) ?? this.#acquire(element, stack);
48
+ this.#held.add(element);
49
+ const shows = !this.#covered(element, stack, hold);
50
+ hold.written = value;
51
+ this.#mark(element, stack);
52
+ if (shows) this.#reflect(element, value);
53
+ }
54
+ return(element) {
55
+ const held = this.#held.delete(element);
56
+ const known = _AttributeLease.#registry.stacks.get(element)?.has(this.#attribute);
57
+ const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
58
+ const hold = this.#take(stack);
59
+ if (!hold) return false;
60
+ const carries = element.getAttribute(this.#attribute) === hold.written;
61
+ const owns = carries && !this.#covered(element, stack, hold);
62
+ const index = stack.indexOf(hold);
63
+ stack.splice(index, 1);
64
+ const above = stack[index];
65
+ if (above) above.linked &&= hold.linked;
66
+ this.#mark(element, stack);
67
+ if (!owns) return true;
68
+ const below = hold.linked ? stack[index - 1] : void 0;
69
+ this.#reflect(element, below ? below.written : hold.original);
70
+ return true;
71
+ }
72
+ returnAll() {
73
+ for (const element of Array.from(this.#held)) this.return(element);
74
+ }
75
+ #stack(element) {
76
+ const stacks = _AttributeLease.#registry.stacks;
77
+ const byAttribute = stacks.get(element) ?? /* @__PURE__ */ new Map();
78
+ stacks.set(element, byAttribute);
79
+ const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);
80
+ byAttribute.set(this.#attribute, stack);
81
+ return stack;
82
+ }
83
+ #seed(element) {
84
+ const found = [];
85
+ for (const record of _AttributeLease.#registry.names.get(this.#attribute) ?? []) {
86
+ const read = readLeaseRecord(element, record);
87
+ if (read) found.push({ ...read, record });
88
+ }
89
+ const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
90
+ return found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
91
+ lease: null,
92
+ record,
93
+ written,
94
+ original,
95
+ linked: linked && index > 0
96
+ }));
97
+ }
98
+ #take(stack) {
99
+ const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
100
+ if (hold) hold.lease = this;
101
+ return hold;
102
+ }
103
+ #acquire(element, stack) {
104
+ const current = element.getAttribute(this.#attribute);
105
+ const top = stack.at(-1);
106
+ const bottom = stack[0];
107
+ const over = top?.written === current ? top : void 0;
108
+ const from = this.#base ? bottom : over;
109
+ const hold = {
110
+ lease: this,
111
+ record: this.#record,
112
+ written: current,
113
+ original: from ? from.original : current,
114
+ linked: !this.#base && over !== void 0
115
+ };
116
+ if (this.#base && bottom) {
117
+ bottom.linked = true;
118
+ stack.unshift(hold);
119
+ } else stack.push(hold);
120
+ return hold;
121
+ }
122
+ #covered(element, stack, hold) {
123
+ const current = element.getAttribute(this.#attribute);
124
+ return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
125
+ }
126
+ #mark(element, stack) {
127
+ const records = /* @__PURE__ */ new Map([[this.#record, null]]);
128
+ stack.forEach((hold, index) => {
129
+ const names = stack.slice(0, index).map((under) => under.record);
130
+ const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
131
+ const marker = hold.linked || beneath.length === 0 ? [] : [false];
132
+ records.set(
133
+ hold.record,
134
+ hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
135
+ );
136
+ });
137
+ for (const [name, recorded] of records) {
138
+ if (element.getAttribute(name) === recorded) continue;
139
+ if (recorded === null) element.removeAttribute(name);
140
+ else element.setAttribute(name, recorded);
141
+ }
142
+ }
143
+ #reflect(element, value) {
144
+ if (element.getAttribute(this.#attribute) === value) return;
145
+ if (value === null) element.removeAttribute(this.#attribute);
146
+ else element.setAttribute(this.#attribute, value);
147
+ }
148
+ };
4
149
 
5
- // src/utils/escape_layer.ts
6
150
  var EscapeLayer = class _EscapeLayer {
7
- static #registries = /* @__PURE__ */ new WeakMap();
8
- #ownerDocument = null;
9
- /** Dismissal callback while active; `null` when inactive. */
10
- #onDismiss = null;
11
- /** Live predicate deciding whether the layer claims a press; `null` = always. */
12
- #claims = null;
13
- /**
14
- * Activates this layer at the top of its document's Escape stack, installing
15
- * the document's shared resolver listener if this is its first layer.
16
- * Re-activating an already-active layer moves it to the top.
17
- */
151
+ static #registries = sharedRegistry(
152
+ "stimeo-ui.escape-layer.registry.v1",
153
+ () => /* @__PURE__ */ new WeakMap()
154
+ );
155
+ #active = null;
18
156
  activate(ownerDocument = document, options) {
19
157
  this.deactivate();
20
158
  let registry = _EscapeLayer.#registries.get(ownerDocument);
@@ -23,44 +161,31 @@ var EscapeLayer = class _EscapeLayer {
23
161
  _EscapeLayer.#registries.set(ownerDocument, registry);
24
162
  ownerDocument.addEventListener("keydown", registry.onKeydown);
25
163
  }
26
- registry.stack.push(this);
27
- this.#ownerDocument = ownerDocument;
28
- this.#onDismiss = options.onDismiss;
29
- this.#claims = options.claims ?? null;
30
- }
31
- /**
32
- * Removes this layer from its document's Escape stack, uninstalling the
33
- * shared listener when the stack empties. Safe to call when inactive.
34
- */
164
+ const entry = { onDismiss: options.onDismiss, claims: options.claims ?? null };
165
+ registry.stack.push(entry);
166
+ this.#active = { document: ownerDocument, entry };
167
+ }
35
168
  deactivate() {
36
- const ownerDocument = this.#ownerDocument;
37
- if (!ownerDocument) return;
38
- const registry = _EscapeLayer.#registries.get(ownerDocument);
169
+ const active = this.#active;
170
+ if (!active) return;
171
+ const registry = _EscapeLayer.#registries.get(active.document);
39
172
  if (registry) {
40
- const index = registry.stack.lastIndexOf(this);
173
+ const index = registry.stack.lastIndexOf(active.entry);
41
174
  if (index >= 0) registry.stack.splice(index, 1);
42
175
  if (registry.stack.length === 0) {
43
- ownerDocument.removeEventListener("keydown", registry.onKeydown);
44
- _EscapeLayer.#registries.delete(ownerDocument);
176
+ active.document.removeEventListener("keydown", registry.onKeydown);
177
+ _EscapeLayer.#registries.delete(active.document);
45
178
  }
46
179
  }
47
- this.#ownerDocument = null;
48
- this.#onDismiss = null;
49
- this.#claims = null;
50
- }
51
- /**
52
- * Whether this active layer would own a press right now: it is the topmost
53
- * layer whose {@link EscapeLayerOptions.claims} passes. Exposed for tests
54
- * and diagnostics — production dismissal goes through the shared listener.
55
- */
180
+ this.#active = null;
181
+ }
56
182
  get ownsEscape() {
57
- const ownerDocument = this.#ownerDocument;
58
- if (!ownerDocument) return false;
59
- const registry = _EscapeLayer.#registries.get(ownerDocument);
183
+ const active = this.#active;
184
+ if (!active) return false;
185
+ const registry = _EscapeLayer.#registries.get(active.document);
60
186
  if (!registry) return false;
61
- return _EscapeLayer.#resolveOwner(registry.stack) === this;
187
+ return _EscapeLayer.#resolveOwner(registry.stack) === active.entry;
62
188
  }
63
- /** Builds a document's registry with its shared resolver listener. */
64
189
  static #createRegistry() {
65
190
  const registry = {
66
191
  stack: [],
@@ -69,60 +194,86 @@ var EscapeLayer = class _EscapeLayer {
69
194
  const owner = _EscapeLayer.#resolveOwner(registry.stack);
70
195
  if (!owner) return;
71
196
  event.preventDefault();
72
- owner.#onDismiss?.();
197
+ owner.onDismiss();
73
198
  }
74
199
  };
75
200
  return registry;
76
201
  }
77
- /** The topmost stack layer whose claims predicate passes, or `null`. */
78
202
  static #resolveOwner(stack) {
79
203
  for (let index = stack.length - 1; index >= 0; index--) {
80
204
  const layer = stack[index];
81
205
  if (!layer) continue;
82
- if (layer.#claims && !layer.#claims()) continue;
206
+ if (layer.claims && !layer.claims()) continue;
83
207
  return layer;
84
208
  }
85
209
  return null;
86
210
  }
87
211
  };
88
212
 
89
- // src/utils/safe_timeout.ts
213
+ var MAX_TIMER_DELAY_MS = 2147483647;
214
+
215
+ var NUMBER_BOUNDS = {
216
+ timer: { finite: true, min: 0, max: MAX_TIMER_DELAY_MS }};
217
+ function matchesNumberBounds(value, bounds) {
218
+ if (!Number.isFinite(value)) {
219
+ const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
220
+ if (direction === null) return false;
221
+ if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
222
+ }
223
+ if (bounds.min !== void 0 && value < bounds.min) return false;
224
+ if (bounds.max !== void 0 && value > bounds.max) return false;
225
+ if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
226
+ if (bounds.integer && !Number.isInteger(value)) return false;
227
+ if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
228
+ return true;
229
+ }
230
+
231
+ function readNumber(raw, fallback, bounds) {
232
+ return matchesNumberBounds(raw, bounds) ? raw : fallback;
233
+ }
234
+
235
+ var NumberValueReader = class {
236
+ #lastRejected = /* @__PURE__ */ new Map();
237
+ read(owner, name, raw, fallback, bounds) {
238
+ const resolved = readNumber(raw, fallback, bounds);
239
+ if (matchesNumberBounds(raw, bounds)) {
240
+ this.#lastRejected.delete(name);
241
+ return resolved;
242
+ }
243
+ const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
244
+ const literal = owner.element.getAttribute(attribute);
245
+ if (literal === null) {
246
+ this.#lastRejected.delete(name);
247
+ return resolved;
248
+ }
249
+ if (this.#lastRejected.get(name) !== literal) {
250
+ this.#lastRejected.set(name, literal);
251
+ console.warn(
252
+ `Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
253
+ );
254
+ }
255
+ return resolved;
256
+ }
257
+ };
258
+
90
259
  var TimerRegistry = class {
91
- /** Live timer ids that have not yet been cleared (or, for timeouts, fired). */
92
260
  ids = /* @__PURE__ */ new Set();
93
- /**
94
- * Cancels a single tracked timer.
95
- *
96
- * No-ops if the id is unknown (already cleared, fired, or never owned by this
97
- * registry), so callers can clear defensively without guarding.
98
- */
99
261
  clear(id) {
100
262
  if (this.ids.delete(id)) {
101
263
  this.cancel(id);
102
264
  }
103
265
  }
104
- /**
105
- * Cancels every tracked timer. Call this from a controller's `disconnect()`
106
- * to guarantee no timer outlives the element.
107
- */
108
266
  clearAll() {
109
267
  for (const id of this.ids) {
110
268
  this.cancel(id);
111
269
  }
112
270
  this.ids.clear();
113
271
  }
114
- /** Number of timers currently tracked (pending). */
115
272
  get size() {
116
273
  return this.ids.size;
117
274
  }
118
275
  };
119
276
  var SafeTimeout = class extends TimerRegistry {
120
- /**
121
- * Schedules `callback` after `delay` ms and returns the timer id.
122
- *
123
- * The id is removed from the registry automatically when the timeout fires,
124
- * so {@link TimerRegistry.size | size} reflects only still-pending timers.
125
- */
126
277
  set(callback, delay) {
127
278
  const id = this.schedule(() => {
128
279
  this.ids.delete(id);
@@ -139,7 +290,6 @@ var SafeTimeout = class extends TimerRegistry {
139
290
  }
140
291
  };
141
292
 
142
- // src/utils/scroll_dismiss.ts
143
293
  function observeScrollDismiss(element, onScroll) {
144
294
  const targets = [...scrollParents(element), window];
145
295
  const handler = () => onScroll();
@@ -164,7 +314,6 @@ function isScrollable(element) {
164
314
  return /auto|scroll|overlay/.test(style.overflow + style.overflowX + style.overflowY);
165
315
  }
166
316
 
167
- // src/utils/state_reason.ts
168
317
  var FOCUS_EVENTS = /* @__PURE__ */ new Set(["blur", "focus", "focusin", "focusout"]);
169
318
  var POINTER_EVENTS = /* @__PURE__ */ new Set(["mouseenter", "mouseleave", "pointerenter", "pointerleave"]);
170
319
  function stateReasonFor(event) {
@@ -174,129 +323,171 @@ function stateReasonFor(event) {
174
323
  return "user";
175
324
  }
176
325
 
177
- // src/controllers/hover_card_controller.ts
178
- var HoverCardController = class extends Controller {
326
+ var HoverCardController = class _HoverCardController extends Controller {
327
+ #numbers = new NumberValueReader();
179
328
  static targets = ["trigger", "card"];
180
329
  static values = {
181
330
  openDelay: { type: Number, default: 300 },
182
331
  closeDelay: { type: Number, default: 200 },
183
332
  closeOnScroll: { type: Boolean, default: false }
184
333
  };
334
+ static valueConstraints = {
335
+ openDelay: NUMBER_BOUNDS.timer,
336
+ closeDelay: NUMBER_BOUNDS.timer
337
+ };
185
338
  static actions = ["close", "open"];
186
339
  static events = ["close", "open"];
187
- /** Pending open/close timers, with their IDs reset on every lifecycle boundary. */
188
340
  #timers = new SafeTimeout();
189
- /** Escape-stack membership while open; the shared resolver dismisses via it. */
190
341
  #escapeLayer = new EscapeLayer();
342
+ #expanded = new AttributeLease("aria-expanded", this.identifier);
191
343
  #pendingOpen = null;
192
344
  #pendingClose = null;
193
- /** Cleanup for the dismiss-on-scroll listeners while open, or `null`. */
194
345
  #stopScrollDismiss = null;
195
- /** Whether state moves are reported: set once `connect()` settled the baseline. */
346
+ #shownCard = null;
347
+ #connected = false;
196
348
  #reporting = false;
197
- /** Starts closed and discards any stale pending state from a prior connection. */
198
349
  connect() {
199
- this.#cancelOpen();
200
- this.#cancelClose();
350
+ this.#cancelTimers();
201
351
  this.#conceal("api");
352
+ this.#connected = true;
202
353
  this.#reporting = true;
203
354
  }
204
- /** Clears timers, the Escape-stack membership, and scroll listeners so nothing outlives the element. */
205
355
  disconnect() {
356
+ this.#connected = false;
206
357
  this.#reporting = false;
207
- this.#cancelOpen();
208
- this.#cancelClose();
209
- this.#escapeLayer.deactivate();
210
- this.#stopScrollDismiss?.();
211
- this.#stopScrollDismiss = null;
358
+ this.#cancelTimers();
359
+ this.#release();
360
+ }
361
+ closeOnScrollValueChanged() {
362
+ if (this.#shownCard) this.#syncScrollDismiss();
363
+ }
364
+ cardTargetDisconnected(card) {
365
+ if (card !== this.#shownCard) return;
366
+ if (this.cardTargets.includes(card)) return;
367
+ this.#cancelTimers();
368
+ this.#release();
369
+ card.hidden = true;
370
+ card.setAttribute("data-state", "closed");
371
+ this.#reflectClosed();
372
+ }
373
+ triggerTargetConnected() {
374
+ if (this.#connected) this.#reflectTrigger();
375
+ }
376
+ triggerTargetDisconnected(trigger) {
377
+ if (!this.triggerTargets.includes(trigger)) this.#expanded.return(trigger);
378
+ if (this.#connected) this.#reflectTrigger();
212
379
  }
213
- /** Opens the card, after `openDelay` ms (or immediately at 0). Cancels a pending close. */
214
380
  open(event) {
215
381
  const reason = stateReasonFor(event);
216
382
  this.#cancelClose();
217
383
  if (this.#isOpen || this.#pendingOpen !== null) return;
218
- if (this.openDelayValue <= 0) {
384
+ if (this.#safeOpenDelay <= 0) {
219
385
  this.#reveal(reason);
220
386
  return;
221
387
  }
222
388
  this.#pendingOpen = this.#timers.set(() => {
223
389
  this.#pendingOpen = null;
224
390
  this.#reveal(reason);
225
- }, this.openDelayValue);
226
- }
227
- /**
228
- * Schedules the card to close after `closeDelay`. Cancels a pending open. The
229
- * delayed callback re-checks whether focus has landed inside the controller
230
- * (e.g. a link in the card) and, if so, aborts the close — covering keyboard
231
- * traversal that the pointer-only hoverable bridge cannot.
232
- */
391
+ }, this.#safeOpenDelay);
392
+ }
233
393
  close(event) {
234
394
  const reason = stateReasonFor(event);
235
395
  this.#cancelOpen();
236
- if (!this.#isOpen || this.#pendingClose !== null) return;
396
+ if (!this.#closable || this.#pendingClose !== null) return;
237
397
  this.#pendingClose = this.#timers.set(() => {
238
398
  this.#pendingClose = null;
239
399
  if (this.element.contains(document.activeElement)) return;
240
400
  this.#conceal(reason);
241
- }, this.closeDelayValue);
242
- }
243
- /**
244
- * Reveals the card, reflects state, reports a move, and joins the Escape stack.
245
- *
246
- * @stimeoRuntimeOnly `closeOnScroll` decides whether this reveal wires the scroll dismissal; what
247
- * is shown does not depend on it.
248
- */
401
+ }, this.#safeCloseDelay);
402
+ }
249
403
  #reveal(reason) {
250
404
  if (!this.hasCardTarget) return;
405
+ const card = this.cardTarget;
251
406
  const was = this.#isOpen;
252
- this.cardTarget.hidden = false;
253
- this.cardTarget.setAttribute("data-state", "open");
254
- if (this.hasTriggerTarget) this.triggerTarget.setAttribute("aria-expanded", "true");
407
+ card.hidden = false;
408
+ card.setAttribute("data-state", "open");
409
+ if (this.hasTriggerTarget) this.#expanded.write(this.triggerTarget, "true");
410
+ this.#shownCard = card;
255
411
  if (!was && this.#reporting) this.dispatch("open", { detail: { reason }, cancelable: false });
412
+ if (this.#shownCard !== card) return;
256
413
  this.#escapeLayer.activate(document, { onDismiss: () => this.#dismiss("escape") });
257
- if (this.closeOnScrollValue && !this.#stopScrollDismiss) {
258
- this.#stopScrollDismiss = observeScrollDismiss(this.element, () => this.#dismiss("scroll"));
259
- }
414
+ this.#syncScrollDismiss();
260
415
  }
261
- /** Hides the card, reflects state, reports a move, and leaves the Escape stack. */
262
416
  #conceal(reason) {
263
417
  const was = this.#isOpen;
264
- this.#escapeLayer.deactivate();
265
- this.#stopScrollDismiss?.();
266
- this.#stopScrollDismiss = null;
418
+ this.#release();
419
+ this.#reflectClosed();
420
+ if (was && this.#reporting) this.dispatch("close", { detail: { reason }, cancelable: false });
421
+ }
422
+ #reflectClosed() {
267
423
  if (this.hasCardTarget) {
268
424
  this.cardTarget.hidden = true;
269
425
  this.cardTarget.setAttribute("data-state", "closed");
270
426
  }
271
- if (this.hasTriggerTarget) this.triggerTarget.setAttribute("aria-expanded", "false");
272
- if (was && this.#reporting) this.dispatch("close", { detail: { reason }, cancelable: false });
427
+ if (this.hasTriggerTarget) this.#expanded.write(this.triggerTarget, "false");
428
+ }
429
+ #reflectTrigger() {
430
+ if (this.hasTriggerTarget) this.#expanded.write(this.triggerTarget, String(this.#isOpen));
431
+ }
432
+ #release() {
433
+ this.#shownCard = null;
434
+ this.#escapeLayer.deactivate();
435
+ this.#stopScrollDismiss?.();
436
+ this.#stopScrollDismiss = null;
437
+ }
438
+ #syncScrollDismiss() {
439
+ if (this.closeOnScrollValue) {
440
+ this.#stopScrollDismiss ??= observeScrollDismiss(this.element, () => this.#dismiss("scroll"));
441
+ return;
442
+ }
443
+ this.#stopScrollDismiss?.();
444
+ this.#stopScrollDismiss = null;
273
445
  }
274
- /** Cancels pending timers and conceals immediately (shared Escape path). */
275
446
  #dismiss(reason) {
447
+ this.#cancelTimers();
448
+ this.#conceal(reason);
449
+ }
450
+ #cancelTimers() {
276
451
  this.#cancelOpen();
277
452
  this.#cancelClose();
278
- this.#conceal(reason);
279
453
  }
280
- /** Cancels any pending open timer. */
281
454
  #cancelOpen() {
282
455
  if (this.#pendingOpen !== null) {
283
456
  this.#timers.clear(this.#pendingOpen);
284
457
  this.#pendingOpen = null;
285
458
  }
286
459
  }
287
- /** Cancels any pending close timer. */
288
460
  #cancelClose() {
289
461
  if (this.#pendingClose !== null) {
290
462
  this.#timers.clear(this.#pendingClose);
291
463
  this.#pendingClose = null;
292
464
  }
293
465
  }
294
- /** Whether the card is currently visible. */
295
466
  get #isOpen() {
296
467
  return this.hasCardTarget && !this.cardTarget.hidden;
297
468
  }
469
+ get #closable() {
470
+ return this.#isOpen || this.#shownCard !== null;
471
+ }
472
+ get #safeOpenDelay() {
473
+ return this.#numbers.read(
474
+ this,
475
+ "openDelay",
476
+ this.openDelayValue,
477
+ _HoverCardController.values.openDelay.default,
478
+ _HoverCardController.valueConstraints.openDelay
479
+ );
480
+ }
481
+ get #safeCloseDelay() {
482
+ return this.#numbers.read(
483
+ this,
484
+ "closeDelay",
485
+ this.closeDelayValue,
486
+ _HoverCardController.values.closeDelay.default,
487
+ _HoverCardController.valueConstraints.closeDelay
488
+ );
489
+ }
298
490
  };
299
491
 
300
492
  export { HoverCardController };
301
- //# sourceMappingURL=hover_card_controller.js.map
302
493
  //# sourceMappingURL=hover_card_controller.js.map