stimeo-ui 0.15.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 (332) hide show
  1. package/CHANGELOG.md +209 -0
  2. package/README.md +128 -1
  3. package/dist/cable/index.d.ts +79 -23
  4. package/dist/cable/index.js +392 -417
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/controllers/accordion_controller.d.ts +34 -5
  7. package/dist/controllers/accordion_controller.js +228 -28
  8. package/dist/controllers/accordion_controller.js.map +1 -1
  9. package/dist/controllers/alert_dialog_controller.d.ts +20 -9
  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 +38 -7
  13. package/dist/controllers/announcer_controller.js +135 -191
  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 +295 -110
  19. package/dist/controllers/auto_submit_controller.js.map +1 -1
  20. package/dist/controllers/avatar_controller.js +172 -106
  21. package/dist/controllers/avatar_controller.js.map +1 -1
  22. package/dist/controllers/breadcrumb_controller.d.ts +10 -7
  23. package/dist/controllers/breadcrumb_controller.js +0 -129
  24. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  25. package/dist/controllers/bulk_select_controller.d.ts +22 -4
  26. package/dist/controllers/bulk_select_controller.js +264 -53
  27. package/dist/controllers/bulk_select_controller.js.map +1 -1
  28. package/dist/controllers/calendar_controller.d.ts +109 -28
  29. package/dist/controllers/calendar_controller.js +346 -180
  30. package/dist/controllers/calendar_controller.js.map +1 -1
  31. package/dist/controllers/carousel_controller.d.ts +99 -27
  32. package/dist/controllers/carousel_controller.js +587 -300
  33. package/dist/controllers/carousel_controller.js.map +1 -1
  34. package/dist/controllers/character_counter_controller.d.ts +18 -2
  35. package/dist/controllers/character_counter_controller.js +271 -143
  36. package/dist/controllers/character_counter_controller.js.map +1 -1
  37. package/dist/controllers/checkbox_controller.d.ts +7 -2
  38. package/dist/controllers/checkbox_controller.js +77 -75
  39. package/dist/controllers/checkbox_controller.js.map +1 -1
  40. package/dist/controllers/clipboard_controller.d.ts +44 -7
  41. package/dist/controllers/clipboard_controller.js +187 -108
  42. package/dist/controllers/clipboard_controller.js.map +1 -1
  43. package/dist/controllers/collapsible_controller.d.ts +41 -5
  44. package/dist/controllers/collapsible_controller.js +374 -108
  45. package/dist/controllers/collapsible_controller.js.map +1 -1
  46. package/dist/controllers/color_picker_controller.d.ts +47 -14
  47. package/dist/controllers/color_picker_controller.js +183 -127
  48. package/dist/controllers/color_picker_controller.js.map +1 -1
  49. package/dist/controllers/combobox_controller.d.ts +33 -6
  50. package/dist/controllers/combobox_controller.js +426 -109
  51. package/dist/controllers/combobox_controller.js.map +1 -1
  52. package/dist/controllers/command_palette_controller.d.ts +45 -14
  53. package/dist/controllers/command_palette_controller.js +994 -350
  54. package/dist/controllers/command_palette_controller.js.map +1 -1
  55. package/dist/controllers/conditional_fields_controller.d.ts +15 -2
  56. package/dist/controllers/conditional_fields_controller.js +212 -125
  57. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  58. package/dist/controllers/confirm_controller.d.ts +49 -12
  59. package/dist/controllers/confirm_controller.js +939 -245
  60. package/dist/controllers/confirm_controller.js.map +1 -1
  61. package/dist/controllers/context_menu_controller.d.ts +36 -3
  62. package/dist/controllers/context_menu_controller.js +275 -127
  63. package/dist/controllers/context_menu_controller.js.map +1 -1
  64. package/dist/controllers/count_up_controller.d.ts +13 -1
  65. package/dist/controllers/count_up_controller.js +73 -21
  66. package/dist/controllers/count_up_controller.js.map +1 -1
  67. package/dist/controllers/countdown_controller.d.ts +75 -2
  68. package/dist/controllers/countdown_controller.js +235 -97
  69. package/dist/controllers/countdown_controller.js.map +1 -1
  70. package/dist/controllers/currency_input_controller.d.ts +93 -15
  71. package/dist/controllers/currency_input_controller.js +241 -118
  72. package/dist/controllers/currency_input_controller.js.map +1 -1
  73. package/dist/controllers/data_grid_controller.d.ts +78 -22
  74. package/dist/controllers/data_grid_controller.js +229 -135
  75. package/dist/controllers/data_grid_controller.js.map +1 -1
  76. package/dist/controllers/date_range_picker_controller.d.ts +64 -11
  77. package/dist/controllers/date_range_picker_controller.js +359 -165
  78. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  79. package/dist/controllers/dialog_controller.d.ts +22 -3
  80. package/dist/controllers/dialog_controller.js +887 -225
  81. package/dist/controllers/dialog_controller.js.map +1 -1
  82. package/dist/controllers/direct_upload_controller.d.ts +24 -7
  83. package/dist/controllers/direct_upload_controller.js +80 -142
  84. package/dist/controllers/direct_upload_controller.js.map +1 -1
  85. package/dist/controllers/dirty_form_controller.d.ts +2 -2
  86. package/dist/controllers/dirty_form_controller.js +26 -47
  87. package/dist/controllers/dirty_form_controller.js.map +1 -1
  88. package/dist/controllers/dismissible_controller.d.ts +19 -0
  89. package/dist/controllers/dismissible_controller.js +175 -20
  90. package/dist/controllers/dismissible_controller.js.map +1 -1
  91. package/dist/controllers/drawer_controller.d.ts +52 -16
  92. package/dist/controllers/drawer_controller.js +963 -336
  93. package/dist/controllers/drawer_controller.js.map +1 -1
  94. package/dist/controllers/dropdown_controller.d.ts +39 -3
  95. package/dist/controllers/dropdown_controller.js +342 -85
  96. package/dist/controllers/dropdown_controller.js.map +1 -1
  97. package/dist/controllers/editable_controller.d.ts +12 -1
  98. package/dist/controllers/editable_controller.js +182 -58
  99. package/dist/controllers/editable_controller.js.map +1 -1
  100. package/dist/controllers/empty_state_controller.js +67 -53
  101. package/dist/controllers/empty_state_controller.js.map +1 -1
  102. package/dist/controllers/file_dropzone_controller.d.ts +60 -18
  103. package/dist/controllers/file_dropzone_controller.js +426 -229
  104. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  105. package/dist/controllers/filter_controller.d.ts +10 -4
  106. package/dist/controllers/filter_controller.js +78 -36
  107. package/dist/controllers/filter_controller.js.map +1 -1
  108. package/dist/controllers/flash_controller.d.ts +57 -14
  109. package/dist/controllers/flash_controller.js +328 -211
  110. package/dist/controllers/flash_controller.js.map +1 -1
  111. package/dist/controllers/focus_controller.d.ts +12 -3
  112. package/dist/controllers/focus_controller.js +654 -239
  113. package/dist/controllers/focus_controller.js.map +1 -1
  114. package/dist/controllers/form_field_controller.js +153 -136
  115. package/dist/controllers/form_field_controller.js.map +1 -1
  116. package/dist/controllers/form_validation_controller.js +29 -96
  117. package/dist/controllers/form_validation_controller.js.map +1 -1
  118. package/dist/controllers/frame_loading_controller.d.ts +41 -9
  119. package/dist/controllers/frame_loading_controller.js +263 -198
  120. package/dist/controllers/frame_loading_controller.js.map +1 -1
  121. package/dist/controllers/highlight_controller.d.ts +22 -2
  122. package/dist/controllers/highlight_controller.js +119 -70
  123. package/dist/controllers/highlight_controller.js.map +1 -1
  124. package/dist/controllers/hover_card_controller.d.ts +65 -4
  125. package/dist/controllers/hover_card_controller.js +335 -118
  126. package/dist/controllers/hover_card_controller.js.map +1 -1
  127. package/dist/controllers/idle_controller.d.ts +58 -4
  128. package/dist/controllers/idle_controller.js +316 -65
  129. package/dist/controllers/idle_controller.js.map +1 -1
  130. package/dist/controllers/input_mask_controller.d.ts +5 -2
  131. package/dist/controllers/input_mask_controller.js +116 -61
  132. package/dist/controllers/input_mask_controller.js.map +1 -1
  133. package/dist/controllers/intersection_controller.d.ts +32 -13
  134. package/dist/controllers/intersection_controller.js +147 -103
  135. package/dist/controllers/intersection_controller.js.map +1 -1
  136. package/dist/controllers/lazy_frame_controller.d.ts +16 -0
  137. package/dist/controllers/lazy_frame_controller.js +9 -56
  138. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  139. package/dist/controllers/listbox_controller.d.ts +84 -10
  140. package/dist/controllers/listbox_controller.js +413 -153
  141. package/dist/controllers/listbox_controller.js.map +1 -1
  142. package/dist/controllers/local_time_controller.d.ts +1 -1
  143. package/dist/controllers/local_time_controller.js +54 -64
  144. package/dist/controllers/local_time_controller.js.map +1 -1
  145. package/dist/controllers/masonry_controller.d.ts +11 -3
  146. package/dist/controllers/masonry_controller.js +70 -95
  147. package/dist/controllers/masonry_controller.js.map +1 -1
  148. package/dist/controllers/menu_controller.d.ts +40 -9
  149. package/dist/controllers/menu_controller.js +254 -167
  150. package/dist/controllers/menu_controller.js.map +1 -1
  151. package/dist/controllers/menubar_controller.d.ts +15 -4
  152. package/dist/controllers/menubar_controller.js +206 -331
  153. package/dist/controllers/menubar_controller.js.map +1 -1
  154. package/dist/controllers/meter_controller.d.ts +20 -0
  155. package/dist/controllers/meter_controller.js +159 -71
  156. package/dist/controllers/meter_controller.js.map +1 -1
  157. package/dist/controllers/multi_select_controller.d.ts +50 -7
  158. package/dist/controllers/multi_select_controller.js +797 -388
  159. package/dist/controllers/multi_select_controller.js.map +1 -1
  160. package/dist/controllers/navigation_menu_controller.d.ts +19 -1
  161. package/dist/controllers/navigation_menu_controller.js +156 -231
  162. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  163. package/dist/controllers/nested_form_controller.d.ts +10 -0
  164. package/dist/controllers/nested_form_controller.js +373 -174
  165. package/dist/controllers/nested_form_controller.js.map +1 -1
  166. package/dist/controllers/network_status_controller.d.ts +23 -0
  167. package/dist/controllers/network_status_controller.js +241 -45
  168. package/dist/controllers/network_status_controller.js.map +1 -1
  169. package/dist/controllers/number_input_controller.d.ts +62 -10
  170. package/dist/controllers/number_input_controller.js +387 -227
  171. package/dist/controllers/number_input_controller.js.map +1 -1
  172. package/dist/controllers/optimistic_controller.js +28 -75
  173. package/dist/controllers/optimistic_controller.js.map +1 -1
  174. package/dist/controllers/otp_controller.d.ts +38 -7
  175. package/dist/controllers/otp_controller.js +344 -196
  176. package/dist/controllers/otp_controller.js.map +1 -1
  177. package/dist/controllers/overflow_indicator_controller.d.ts +13 -12
  178. package/dist/controllers/overflow_indicator_controller.js +167 -93
  179. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  180. package/dist/controllers/overflow_menu_controller.d.ts +66 -9
  181. package/dist/controllers/overflow_menu_controller.js +408 -277
  182. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  183. package/dist/controllers/pagination_controller.d.ts +52 -15
  184. package/dist/controllers/pagination_controller.js +342 -120
  185. package/dist/controllers/pagination_controller.js.map +1 -1
  186. package/dist/controllers/password_reveal_controller.d.ts +60 -9
  187. package/dist/controllers/password_reveal_controller.js +424 -99
  188. package/dist/controllers/password_reveal_controller.js.map +1 -1
  189. package/dist/controllers/password_strength_controller.d.ts +14 -5
  190. package/dist/controllers/password_strength_controller.js +99 -153
  191. package/dist/controllers/password_strength_controller.js.map +1 -1
  192. package/dist/controllers/persist_controller.d.ts +11 -4
  193. package/dist/controllers/persist_controller.js +252 -96
  194. package/dist/controllers/persist_controller.js.map +1 -1
  195. package/dist/controllers/pointer_drag_controller.d.ts +19 -7
  196. package/dist/controllers/pointer_drag_controller.js +263 -164
  197. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  198. package/dist/controllers/popover_controller.d.ts +46 -4
  199. package/dist/controllers/popover_controller.js +267 -94
  200. package/dist/controllers/popover_controller.js.map +1 -1
  201. package/dist/controllers/portal_controller.d.ts +44 -4
  202. package/dist/controllers/portal_controller.js +209 -72
  203. package/dist/controllers/portal_controller.js.map +1 -1
  204. package/dist/controllers/preview_guard_controller.d.ts +10 -4
  205. package/dist/controllers/preview_guard_controller.js +243 -112
  206. package/dist/controllers/preview_guard_controller.js.map +1 -1
  207. package/dist/controllers/progress_controller.d.ts +11 -0
  208. package/dist/controllers/progress_controller.js +132 -59
  209. package/dist/controllers/progress_controller.js.map +1 -1
  210. package/dist/controllers/radio_group_controller.d.ts +19 -8
  211. package/dist/controllers/radio_group_controller.js +138 -133
  212. package/dist/controllers/radio_group_controller.js.map +1 -1
  213. package/dist/controllers/range_slider_controller.d.ts +92 -4
  214. package/dist/controllers/range_slider_controller.js +245 -112
  215. package/dist/controllers/range_slider_controller.js.map +1 -1
  216. package/dist/controllers/rating_controller.d.ts +33 -6
  217. package/dist/controllers/rating_controller.js +429 -194
  218. package/dist/controllers/rating_controller.js.map +1 -1
  219. package/dist/controllers/read_more_controller.d.ts +26 -2
  220. package/dist/controllers/read_more_controller.js +185 -47
  221. package/dist/controllers/read_more_controller.js.map +1 -1
  222. package/dist/controllers/reading_progress_controller.d.ts +1 -1
  223. package/dist/controllers/reading_progress_controller.js +147 -135
  224. package/dist/controllers/reading_progress_controller.js.map +1 -1
  225. package/dist/controllers/relative_time_controller.d.ts +18 -4
  226. package/dist/controllers/relative_time_controller.js +145 -110
  227. package/dist/controllers/relative_time_controller.js.map +1 -1
  228. package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
  229. package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +97 -38
  230. package/dist/controllers/reset_on_restore_controller.js.map +1 -0
  231. package/dist/controllers/resizable_controller.d.ts +44 -4
  232. package/dist/controllers/resizable_controller.js +294 -118
  233. package/dist/controllers/resizable_controller.js.map +1 -1
  234. package/dist/controllers/roving_controller.js +39 -84
  235. package/dist/controllers/roving_controller.js.map +1 -1
  236. package/dist/controllers/scroll_area_controller.d.ts +7 -3
  237. package/dist/controllers/scroll_area_controller.js +428 -221
  238. package/dist/controllers/scroll_area_controller.js.map +1 -1
  239. package/dist/controllers/scroll_restore_controller.js +0 -53
  240. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  241. package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
  242. package/dist/controllers/scroll_visibility_controller.js +395 -146
  243. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  244. package/dist/controllers/scrollspy_controller.d.ts +9 -3
  245. package/dist/controllers/scrollspy_controller.js +181 -236
  246. package/dist/controllers/scrollspy_controller.js.map +1 -1
  247. package/dist/controllers/separator_controller.d.ts +59 -17
  248. package/dist/controllers/separator_controller.js +288 -132
  249. package/dist/controllers/separator_controller.js.map +1 -1
  250. package/dist/controllers/sidebar_controller.d.ts +81 -7
  251. package/dist/controllers/sidebar_controller.js +1071 -375
  252. package/dist/controllers/sidebar_controller.js.map +1 -1
  253. package/dist/controllers/skeleton_controller.d.ts +23 -0
  254. package/dist/controllers/skeleton_controller.js +248 -92
  255. package/dist/controllers/skeleton_controller.js.map +1 -1
  256. package/dist/controllers/slider_controller.d.ts +72 -8
  257. package/dist/controllers/slider_controller.js +211 -96
  258. package/dist/controllers/slider_controller.js.map +1 -1
  259. package/dist/controllers/smart_sticky_header_controller.d.ts +21 -3
  260. package/dist/controllers/smart_sticky_header_controller.js +163 -54
  261. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  262. package/dist/controllers/sortable_controller.js +13 -110
  263. package/dist/controllers/sortable_controller.js.map +1 -1
  264. package/dist/controllers/spinner_controller.d.ts +39 -4
  265. package/dist/controllers/spinner_controller.js +277 -161
  266. package/dist/controllers/spinner_controller.js.map +1 -1
  267. package/dist/controllers/step_indicator_controller.d.ts +24 -17
  268. package/dist/controllers/step_indicator_controller.js +107 -53
  269. package/dist/controllers/step_indicator_controller.js.map +1 -1
  270. package/dist/controllers/stepper_controller.d.ts +43 -9
  271. package/dist/controllers/stepper_controller.js +171 -48
  272. package/dist/controllers/stepper_controller.js.map +1 -1
  273. package/dist/controllers/stick_to_bottom_controller.d.ts +25 -0
  274. package/dist/controllers/stick_to_bottom_controller.js +310 -116
  275. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  276. package/dist/controllers/sticky_observer_controller.d.ts +11 -0
  277. package/dist/controllers/sticky_observer_controller.js +214 -49
  278. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  279. package/dist/controllers/submit_once_controller.d.ts +22 -6
  280. package/dist/controllers/submit_once_controller.js +294 -192
  281. package/dist/controllers/submit_once_controller.js.map +1 -1
  282. package/dist/controllers/switch_controller.d.ts +40 -7
  283. package/dist/controllers/switch_controller.js +107 -43
  284. package/dist/controllers/switch_controller.js.map +1 -1
  285. package/dist/controllers/tabs_controller.d.ts +13 -1
  286. package/dist/controllers/tabs_controller.js +50 -25
  287. package/dist/controllers/tabs_controller.js.map +1 -1
  288. package/dist/controllers/tags_input_controller.d.ts +27 -3
  289. package/dist/controllers/tags_input_controller.js +290 -149
  290. package/dist/controllers/tags_input_controller.js.map +1 -1
  291. package/dist/controllers/textarea_autosize_controller.d.ts +10 -0
  292. package/dist/controllers/textarea_autosize_controller.js +71 -58
  293. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  294. package/dist/controllers/theme_controller.d.ts +37 -8
  295. package/dist/controllers/theme_controller.js +148 -80
  296. package/dist/controllers/theme_controller.js.map +1 -1
  297. package/dist/controllers/time_picker_controller.d.ts +18 -1
  298. package/dist/controllers/time_picker_controller.js +162 -81
  299. package/dist/controllers/time_picker_controller.js.map +1 -1
  300. package/dist/controllers/toast_controller.d.ts +85 -23
  301. package/dist/controllers/toast_controller.js +365 -193
  302. package/dist/controllers/toast_controller.js.map +1 -1
  303. package/dist/controllers/toggle_group_controller.d.ts +60 -9
  304. package/dist/controllers/toggle_group_controller.js +194 -99
  305. package/dist/controllers/toggle_group_controller.js.map +1 -1
  306. package/dist/controllers/toolbar_controller.js +92 -90
  307. package/dist/controllers/toolbar_controller.js.map +1 -1
  308. package/dist/controllers/tooltip_controller.d.ts +52 -2
  309. package/dist/controllers/tooltip_controller.js +185 -125
  310. package/dist/controllers/tooltip_controller.js.map +1 -1
  311. package/dist/controllers/transition_controller.d.ts +22 -4
  312. package/dist/controllers/transition_controller.js +123 -115
  313. package/dist/controllers/transition_controller.js.map +1 -1
  314. package/dist/controllers/tree_view_controller.d.ts +59 -18
  315. package/dist/controllers/tree_view_controller.js +248 -290
  316. package/dist/controllers/tree_view_controller.js.map +1 -1
  317. package/dist/index.d.ts +33 -3
  318. package/dist/index.js +8649 -8572
  319. package/dist/index.js.map +1 -1
  320. package/dist/inspector/cli.d.ts +95 -9
  321. package/dist/inspector/cli.js +343 -77
  322. package/dist/inspector/cli.js.map +1 -1
  323. package/dist/inspector/cli_bin.js +390 -96
  324. package/dist/inspector/cli_bin.js.map +1 -1
  325. package/dist/inspector/examples.json +45 -45
  326. package/dist/inspector/manifest.json +1308 -155
  327. package/dist/positioning/index.d.ts +8 -0
  328. package/dist/positioning/index.js +148 -45
  329. package/dist/positioning/index.js.map +1 -1
  330. package/package.json +7 -7
  331. package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
  332. 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,113 +314,180 @@ function isScrollable(element) {
164
314
  return /auto|scroll|overlay/.test(style.overflow + style.overflowX + style.overflowY);
165
315
  }
166
316
 
167
- // src/controllers/hover_card_controller.ts
168
- var HoverCardController = class extends Controller {
317
+ var FOCUS_EVENTS = /* @__PURE__ */ new Set(["blur", "focus", "focusin", "focusout"]);
318
+ var POINTER_EVENTS = /* @__PURE__ */ new Set(["mouseenter", "mouseleave", "pointerenter", "pointerleave"]);
319
+ function stateReasonFor(event) {
320
+ if (!event) return "api";
321
+ if (FOCUS_EVENTS.has(event.type)) return "focus";
322
+ if (POINTER_EVENTS.has(event.type)) return "pointer";
323
+ return "user";
324
+ }
325
+
326
+ var HoverCardController = class _HoverCardController extends Controller {
327
+ #numbers = new NumberValueReader();
169
328
  static targets = ["trigger", "card"];
170
329
  static values = {
171
330
  openDelay: { type: Number, default: 300 },
172
331
  closeDelay: { type: Number, default: 200 },
173
332
  closeOnScroll: { type: Boolean, default: false }
174
333
  };
334
+ static valueConstraints = {
335
+ openDelay: NUMBER_BOUNDS.timer,
336
+ closeDelay: NUMBER_BOUNDS.timer
337
+ };
175
338
  static actions = ["close", "open"];
176
- /** Pending open/close timers, with their IDs reset on every lifecycle boundary. */
339
+ static events = ["close", "open"];
177
340
  #timers = new SafeTimeout();
178
- /** Escape-stack membership while open; the shared resolver dismisses via it. */
179
341
  #escapeLayer = new EscapeLayer();
342
+ #expanded = new AttributeLease("aria-expanded", this.identifier);
180
343
  #pendingOpen = null;
181
344
  #pendingClose = null;
182
- /** Cleanup for the dismiss-on-scroll listeners while open, or `null`. */
183
345
  #stopScrollDismiss = null;
184
- /** Starts closed and discards any stale pending state from a prior connection. */
346
+ #shownCard = null;
347
+ #connected = false;
348
+ #reporting = false;
185
349
  connect() {
186
- this.#cancelOpen();
187
- this.#cancelClose();
188
- this.#conceal();
350
+ this.#cancelTimers();
351
+ this.#conceal("api");
352
+ this.#connected = true;
353
+ this.#reporting = true;
189
354
  }
190
- /** Clears timers, the Escape-stack membership, and scroll listeners so nothing outlives the element. */
191
355
  disconnect() {
192
- this.#cancelOpen();
193
- this.#cancelClose();
194
- this.#escapeLayer.deactivate();
195
- this.#stopScrollDismiss?.();
196
- this.#stopScrollDismiss = null;
356
+ this.#connected = false;
357
+ this.#reporting = false;
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();
197
372
  }
198
- /** Opens the card, after `openDelay` ms (or immediately at 0). Cancels a pending close. */
199
- open() {
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();
379
+ }
380
+ open(event) {
381
+ const reason = stateReasonFor(event);
200
382
  this.#cancelClose();
201
383
  if (this.#isOpen || this.#pendingOpen !== null) return;
202
- if (this.openDelayValue <= 0) {
203
- this.#reveal();
384
+ if (this.#safeOpenDelay <= 0) {
385
+ this.#reveal(reason);
204
386
  return;
205
387
  }
206
388
  this.#pendingOpen = this.#timers.set(() => {
207
389
  this.#pendingOpen = null;
208
- this.#reveal();
209
- }, this.openDelayValue);
210
- }
211
- /**
212
- * Schedules the card to close after `closeDelay`. Cancels a pending open. The
213
- * delayed callback re-checks whether focus has landed inside the controller
214
- * (e.g. a link in the card) and, if so, aborts the close — covering keyboard
215
- * traversal that the pointer-only hoverable bridge cannot.
216
- */
217
- close() {
390
+ this.#reveal(reason);
391
+ }, this.#safeOpenDelay);
392
+ }
393
+ close(event) {
394
+ const reason = stateReasonFor(event);
218
395
  this.#cancelOpen();
219
- if (!this.#isOpen || this.#pendingClose !== null) return;
396
+ if (!this.#closable || this.#pendingClose !== null) return;
220
397
  this.#pendingClose = this.#timers.set(() => {
221
398
  this.#pendingClose = null;
222
399
  if (this.element.contains(document.activeElement)) return;
223
- this.#conceal();
224
- }, this.closeDelayValue);
400
+ this.#conceal(reason);
401
+ }, this.#safeCloseDelay);
225
402
  }
226
- /** Reveals the card, reflects state, and joins the Escape stack / scroll watcher. */
227
- #reveal() {
403
+ #reveal(reason) {
228
404
  if (!this.hasCardTarget) return;
229
- this.cardTarget.hidden = false;
230
- this.cardTarget.setAttribute("data-state", "open");
231
- if (this.hasTriggerTarget) this.triggerTarget.setAttribute("aria-expanded", "true");
232
- this.#escapeLayer.activate(document, { onDismiss: () => this.#dismiss() });
233
- if (this.closeOnScrollValue && !this.#stopScrollDismiss) {
234
- this.#stopScrollDismiss = observeScrollDismiss(this.element, () => this.#dismiss());
405
+ const card = this.cardTarget;
406
+ const was = this.#isOpen;
407
+ card.hidden = false;
408
+ card.setAttribute("data-state", "open");
409
+ if (this.hasTriggerTarget) this.#expanded.write(this.triggerTarget, "true");
410
+ this.#shownCard = card;
411
+ if (!was && this.#reporting) this.dispatch("open", { detail: { reason }, cancelable: false });
412
+ if (this.#shownCard !== card) return;
413
+ this.#escapeLayer.activate(document, { onDismiss: () => this.#dismiss("escape") });
414
+ this.#syncScrollDismiss();
415
+ }
416
+ #conceal(reason) {
417
+ const was = this.#isOpen;
418
+ this.#release();
419
+ this.#reflectClosed();
420
+ if (was && this.#reporting) this.dispatch("close", { detail: { reason }, cancelable: false });
421
+ }
422
+ #reflectClosed() {
423
+ if (this.hasCardTarget) {
424
+ this.cardTarget.hidden = true;
425
+ this.cardTarget.setAttribute("data-state", "closed");
235
426
  }
427
+ if (this.hasTriggerTarget) this.#expanded.write(this.triggerTarget, "false");
236
428
  }
237
- /** Hides the card, reflects state, and leaves the Escape stack / scroll watcher. */
238
- #conceal() {
429
+ #reflectTrigger() {
430
+ if (this.hasTriggerTarget) this.#expanded.write(this.triggerTarget, String(this.#isOpen));
431
+ }
432
+ #release() {
433
+ this.#shownCard = null;
239
434
  this.#escapeLayer.deactivate();
240
435
  this.#stopScrollDismiss?.();
241
436
  this.#stopScrollDismiss = null;
242
- if (this.hasCardTarget) {
243
- this.cardTarget.hidden = true;
244
- this.cardTarget.setAttribute("data-state", "closed");
437
+ }
438
+ #syncScrollDismiss() {
439
+ if (this.closeOnScrollValue) {
440
+ this.#stopScrollDismiss ??= observeScrollDismiss(this.element, () => this.#dismiss("scroll"));
441
+ return;
245
442
  }
246
- if (this.hasTriggerTarget) this.triggerTarget.setAttribute("aria-expanded", "false");
443
+ this.#stopScrollDismiss?.();
444
+ this.#stopScrollDismiss = null;
247
445
  }
248
- /** Cancels pending timers and conceals immediately (shared Escape path). */
249
- #dismiss() {
446
+ #dismiss(reason) {
447
+ this.#cancelTimers();
448
+ this.#conceal(reason);
449
+ }
450
+ #cancelTimers() {
250
451
  this.#cancelOpen();
251
452
  this.#cancelClose();
252
- this.#conceal();
253
453
  }
254
- /** Cancels any pending open timer. */
255
454
  #cancelOpen() {
256
455
  if (this.#pendingOpen !== null) {
257
456
  this.#timers.clear(this.#pendingOpen);
258
457
  this.#pendingOpen = null;
259
458
  }
260
459
  }
261
- /** Cancels any pending close timer. */
262
460
  #cancelClose() {
263
461
  if (this.#pendingClose !== null) {
264
462
  this.#timers.clear(this.#pendingClose);
265
463
  this.#pendingClose = null;
266
464
  }
267
465
  }
268
- /** Whether the card is currently visible. */
269
466
  get #isOpen() {
270
467
  return this.hasCardTarget && !this.cardTarget.hidden;
271
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
+ }
272
490
  };
273
491
 
274
492
  export { HoverCardController };
275
- //# sourceMappingURL=hover_card_controller.js.map
276
493
  //# sourceMappingURL=hover_card_controller.js.map