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,8 +1,5 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
3
- // src/controllers/form_field_controller.ts
4
-
5
- // src/utils/announce.ts
6
3
  function announce(message, options = {}) {
7
4
  const text = message.trim();
8
5
  if (text.length === 0) return;
@@ -13,13 +10,22 @@ function announce(message, options = {}) {
13
10
  );
14
11
  }
15
12
 
16
- // src/utils/aria_ids.ts
17
- var counter = 0;
13
+ function sharedRegistry(key, create) {
14
+ const symbol = Symbol.for(key);
15
+ const scope = globalThis;
16
+ const existing = scope[symbol];
17
+ if (existing !== void 0) return existing;
18
+ const registry = create();
19
+ Object.defineProperty(globalThis, symbol, { value: registry });
20
+ return registry;
21
+ }
22
+
23
+ var ids = sharedRegistry("stimeo-ui.aria-ids.registry.v1", () => ({ counter: 0 }));
18
24
  function uniqueId(prefix = "stimeo") {
19
25
  let candidate;
20
26
  do {
21
- counter += 1;
22
- candidate = `${prefix}-${counter}`;
27
+ ids.counter += 1;
28
+ candidate = `${prefix}-${ids.counter}`;
23
29
  } while (typeof document !== "undefined" && document.getElementById(candidate) !== null);
24
30
  return candidate;
25
31
  }
@@ -30,103 +36,164 @@ function ensureId(element, prefix = "stimeo") {
30
36
  return id;
31
37
  }
32
38
 
33
- // src/utils/attribute_lease.ts
34
- var AttributeLease = class {
39
+ function isAttributeValue(value) {
40
+ return value === null || typeof value === "string";
41
+ }
42
+ function readLeaseRecord(element, record) {
43
+ try {
44
+ const parsed = JSON.parse(element.getAttribute(record) ?? "null");
45
+ if (!Array.isArray(parsed)) return void 0;
46
+ const [original, written, ...rest] = parsed;
47
+ const linked = rest[0] !== false;
48
+ const beneath = linked ? rest : rest.slice(1);
49
+ if (!beneath.every((under) => typeof under === "string")) return void 0;
50
+ return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
51
+ } catch {
52
+ return void 0;
53
+ }
54
+ }
55
+ var AttributeLease = class _AttributeLease {
56
+ static #registry = sharedRegistry(
57
+ "stimeo-ui.attribute-lease.registry.v1",
58
+ () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
59
+ );
35
60
  #attribute;
36
- #records = /* @__PURE__ */ new Map();
37
- /** @param attribute - The attribute whose temporary values this lease owns. */
38
- constructor(attribute) {
61
+ #record;
62
+ #base;
63
+ #held = /* @__PURE__ */ new Set();
64
+ constructor(attribute, owner, options = {}) {
39
65
  this.#attribute = attribute;
66
+ this.#record = `data-${owner}-${attribute}-lease`;
67
+ this.#base = options.base === true;
68
+ const names = _AttributeLease.#registry.names;
69
+ names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
40
70
  }
41
- /** Writes or removes the leased attribute while preserving its authored value. */
42
71
  write(element, value) {
43
- const existing = this.#records.get(element);
44
- if (existing) {
45
- existing.written = value;
46
- } else {
47
- this.#records.set(element, {
48
- original: element.getAttribute(this.#attribute),
49
- written: value
50
- });
51
- }
52
- this.#reflect(element, value);
72
+ const stack = this.#stack(element);
73
+ const hold = this.#take(stack) ?? this.#acquire(element, stack);
74
+ this.#held.add(element);
75
+ const shows = !this.#covered(element, stack, hold);
76
+ hold.written = value;
77
+ this.#mark(element, stack);
78
+ if (shows) this.#reflect(element, value);
53
79
  }
54
- /** Returns one lease without overwriting a value subsequently authored by a consumer. */
55
80
  return(element) {
56
- const record = this.#records.get(element);
57
- if (!record) return;
58
- this.#records.delete(element);
59
- const stillOwned = element.getAttribute(this.#attribute) === record.written;
60
- if (stillOwned) this.#reflect(element, record.original);
81
+ const held = this.#held.delete(element);
82
+ const known = _AttributeLease.#registry.stacks.get(element)?.has(this.#attribute);
83
+ const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
84
+ const hold = this.#take(stack);
85
+ if (!hold) return false;
86
+ const carries = element.getAttribute(this.#attribute) === hold.written;
87
+ const owns = carries && !this.#covered(element, stack, hold);
88
+ const index = stack.indexOf(hold);
89
+ stack.splice(index, 1);
90
+ const above = stack[index];
91
+ if (above) above.linked &&= hold.linked;
92
+ this.#mark(element, stack);
93
+ if (!owns) return true;
94
+ const below = hold.linked ? stack[index - 1] : void 0;
95
+ this.#reflect(element, below ? below.written : hold.original);
96
+ return true;
97
+ }
98
+ returnAll() {
99
+ for (const element of Array.from(this.#held)) this.return(element);
100
+ }
101
+ #stack(element) {
102
+ const stacks = _AttributeLease.#registry.stacks;
103
+ const byAttribute = stacks.get(element) ?? /* @__PURE__ */ new Map();
104
+ stacks.set(element, byAttribute);
105
+ const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);
106
+ byAttribute.set(this.#attribute, stack);
107
+ return stack;
108
+ }
109
+ #seed(element) {
110
+ const found = [];
111
+ for (const record of _AttributeLease.#registry.names.get(this.#attribute) ?? []) {
112
+ const read = readLeaseRecord(element, record);
113
+ if (read) found.push({ ...read, record });
114
+ }
115
+ const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
116
+ return found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
117
+ lease: null,
118
+ record,
119
+ written,
120
+ original,
121
+ linked: linked && index > 0
122
+ }));
123
+ }
124
+ #take(stack) {
125
+ const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
126
+ if (hold) hold.lease = this;
127
+ return hold;
128
+ }
129
+ #acquire(element, stack) {
130
+ const current = element.getAttribute(this.#attribute);
131
+ const top = stack.at(-1);
132
+ const bottom = stack[0];
133
+ const over = top?.written === current ? top : void 0;
134
+ const from = this.#base ? bottom : over;
135
+ const hold = {
136
+ lease: this,
137
+ record: this.#record,
138
+ written: current,
139
+ original: from ? from.original : current,
140
+ linked: !this.#base && over !== void 0
141
+ };
142
+ if (this.#base && bottom) {
143
+ bottom.linked = true;
144
+ stack.unshift(hold);
145
+ } else stack.push(hold);
146
+ return hold;
147
+ }
148
+ #covered(element, stack, hold) {
149
+ const current = element.getAttribute(this.#attribute);
150
+ return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
151
+ }
152
+ #mark(element, stack) {
153
+ const records = /* @__PURE__ */ new Map([[this.#record, null]]);
154
+ stack.forEach((hold, index) => {
155
+ const names = stack.slice(0, index).map((under) => under.record);
156
+ const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
157
+ const marker = hold.linked || beneath.length === 0 ? [] : [false];
158
+ records.set(
159
+ hold.record,
160
+ hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
161
+ );
162
+ });
163
+ for (const [name, recorded] of records) {
164
+ if (element.getAttribute(name) === recorded) continue;
165
+ if (recorded === null) element.removeAttribute(name);
166
+ else element.setAttribute(name, recorded);
167
+ }
61
168
  }
62
- /** Reflects only a real value transition, avoiding self-triggered mutation work. */
63
169
  #reflect(element, value) {
64
170
  if (element.getAttribute(this.#attribute) === value) return;
65
171
  if (value === null) element.removeAttribute(this.#attribute);
66
172
  else element.setAttribute(this.#attribute, value);
67
173
  }
68
- /** Returns every outstanding lease using the same ownership check as {@link return}. */
69
- returnAll() {
70
- for (const element of Array.from(this.#records.keys())) this.return(element);
71
- }
72
- };
73
-
74
- // src/utils/before_cache_reset.ts
75
- var BeforeCacheReset = class _BeforeCacheReset {
76
- /** Every subscribed instance, iterated by the one shared document listener. */
77
- static #subscribers = /* @__PURE__ */ new Set();
78
- /** The shared listener; installed while at least one instance is subscribed. */
79
- static #onBeforeCache = () => {
80
- for (const subscriber of _BeforeCacheReset.#subscribers) subscriber.#rewind();
81
- };
82
- #rewind;
83
- /** @param rewind - the pass that returns this controller's state to its initial form. */
84
- constructor(rewind) {
85
- this.#rewind = rewind;
86
- }
87
- /** Subscribes to `turbo:before-cache`; call from `connect()`. Idempotent. */
88
- activate() {
89
- const first = _BeforeCacheReset.#subscribers.size === 0;
90
- _BeforeCacheReset.#subscribers.add(this);
91
- if (first) {
92
- document.addEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
93
- }
94
- }
95
- /** Unsubscribes; call from `disconnect()`. Safe when never subscribed. */
96
- deactivate() {
97
- _BeforeCacheReset.#subscribers.delete(this);
98
- if (_BeforeCacheReset.#subscribers.size > 0) return;
99
- document.removeEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
100
- }
101
174
  };
102
175
 
103
- // src/utils/event_owner.ts
104
176
  function ownerIndex(candidates, node) {
105
177
  if (!(node instanceof Node)) return -1;
106
178
  return candidates.findIndex((candidate) => candidate.contains(node));
107
179
  }
108
180
 
109
- // src/utils/microtask_coalescer.ts
110
181
  var MicrotaskCoalescer = class {
111
182
  #run;
112
183
  #queued = false;
113
184
  #active = false;
114
185
  #generation = 0;
115
- /** @param run - the single reconciliation pass, invoked at most once per batch. */
116
186
  constructor(run) {
117
187
  this.#run = run;
118
188
  }
119
- /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
120
189
  activate() {
121
190
  this.#active = true;
122
191
  }
123
- /** Closes the window and drops any pending pass; call from `disconnect()`. */
124
192
  cancel() {
125
193
  this.#active = false;
126
194
  this.#queued = false;
127
195
  this.#generation += 1;
128
196
  }
129
- /** Requests one pass after the batch settles. Idempotent; inert outside the window. */
130
197
  schedule() {
131
198
  if (!this.#active || this.#queued) return;
132
199
  this.#queued = true;
@@ -139,7 +206,6 @@ var MicrotaskCoalescer = class {
139
206
  }
140
207
  };
141
208
 
142
- // src/controllers/form_field_controller.ts
143
209
  var OBSERVED_ATTRIBUTES = ["hidden", "id"];
144
210
  var FormFieldController = class extends Controller {
145
211
  static targets = ["control", "description", "error"];
@@ -148,18 +214,21 @@ var FormFieldController = class extends Controller {
148
214
  };
149
215
  static actions = ["clearError", "setError"];
150
216
  static events = ["validate"];
151
- /** Root attribute (CSS hook) reflecting the invalid state, in this controller's namespace. */
152
217
  get #invalidAttribute() {
153
218
  return `data-${this.identifier}-invalid`;
154
219
  }
155
- /** Collapses one target/morph batch into one silent ARIA reconciliation. */
156
220
  #reconcile = new MicrotaskCoalescer(() => this.#reconcileDom());
157
- /** Returns borrowed control ARIA before Turbo snapshots the page. */
158
- #beforeCache = new BeforeCacheReset(() => this.#rewindForCache());
159
- #ariaDescribedBy = new AttributeLease("aria-describedby");
160
- #ariaErrorMessage = new AttributeLease("aria-errormessage");
161
- #ariaInvalid = new AttributeLease("aria-invalid");
162
- /** Watches retained target ids, error visibility, and error content. */
221
+ #ariaDescribedBy = new AttributeLease("aria-describedby", this.identifier, {
222
+ base: true
223
+ });
224
+ #ariaErrorMessage = new AttributeLease(
225
+ "aria-errormessage",
226
+ this.identifier,
227
+ { base: true }
228
+ );
229
+ #ariaInvalid = new AttributeLease("aria-invalid", this.identifier, {
230
+ base: true
231
+ });
163
232
  #observer = new MutationObserver((records) => {
164
233
  if (records.some((record) => this.#isRelevantMutation(record))) {
165
234
  this.#reconcile.schedule();
@@ -169,11 +238,8 @@ var FormFieldController = class extends Controller {
169
238
  #baseDescribedBy = [];
170
239
  #explicitInvalid = false;
171
240
  #initialized = false;
172
- /** Wires the initial graph and starts retained-target reconciliation. */
173
241
  connect() {
174
242
  this.#reconcile.activate();
175
- this.#ensureAssociationIds();
176
- this.#beforeCache.activate();
177
243
  if (!this.#initialized) {
178
244
  this.#explicitInvalid = this.element.hasAttribute(this.#invalidAttribute) && this.#shownErrors().length === 0;
179
245
  this.#initialized = true;
@@ -187,49 +253,29 @@ var FormFieldController = class extends Controller {
187
253
  subtree: true
188
254
  });
189
255
  }
190
- /** Releases observers, queued work, and ARIA borrowed on the current control. */
191
256
  disconnect() {
192
257
  this.#reconcile.cancel();
193
258
  this.#observer.disconnect();
194
- this.#beforeCache.deactivate();
195
259
  this.#activeControl && this.#releaseControl(this.#activeControl);
196
260
  }
197
- /** Reconciles a control inserted or replaced at runtime. */
198
261
  controlTargetConnected() {
199
262
  this.#reconcile.schedule();
200
263
  }
201
- /** Schedules restoration of authored ARIA when a control leaves this field. */
202
264
  controlTargetDisconnected() {
203
265
  this.#reconcile.schedule();
204
266
  }
205
- /** Reconciles a description inserted or replaced at runtime. */
206
267
  descriptionTargetConnected() {
207
268
  this.#reconcile.schedule();
208
269
  }
209
- /** Removes a departed description from the control's association graph. */
210
270
  descriptionTargetDisconnected() {
211
271
  this.#reconcile.schedule();
212
272
  }
213
- /** Reconciles an error region inserted or replaced at runtime. */
214
273
  errorTargetConnected() {
215
274
  this.#reconcile.schedule();
216
275
  }
217
- /** Removes a departed error from invalid state and the association graph. */
218
276
  errorTargetDisconnected() {
219
277
  this.#reconcile.schedule();
220
278
  }
221
- /**
222
- * Marks the field invalid and shows the error message. Bound via `data-action`
223
- * (`#setError`) or callable directly.
224
- *
225
- * A non-empty shown message is announced exactly once through the shared
226
- * assertive announcer. Initial/server reconciliation is deliberately silent.
227
- *
228
- * @param arg - Either the message string, or the action event whose
229
- * `data-stimeo--form-field-message-param` supplies it. When no message is
230
- * resolvable, any already-populated error targets are simply (re)shown.
231
- * @param options - Programmatic overrides. Stimulus actions use the Values.
232
- */
233
279
  setError(arg, options = {}) {
234
280
  const message = this.#resolveMessage(arg);
235
281
  if (message !== null && this.hasErrorTarget) {
@@ -246,13 +292,6 @@ var FormFieldController = class extends Controller {
246
292
  announce(shownMessage, { assertive: true });
247
293
  if (options.focus ?? this.focusOnErrorValue) this.#activeControl?.focus();
248
294
  }
249
- /**
250
- * Clears the error: empties and hides every error target and marks the field
251
- * valid. Bound via `data-action` (`#clearError`) or callable directly.
252
- *
253
- * Clearing is silent: the visual/ARIA state and validation event are sufficient,
254
- * while success wording remains an explicit consumer announcement.
255
- */
256
295
  clearError() {
257
296
  for (const error of this.errorTargets) {
258
297
  error.replaceChildren();
@@ -263,10 +302,6 @@ var FormFieldController = class extends Controller {
263
302
  const detail = { valid: true, message: "" };
264
303
  this.dispatch("validate", { detail });
265
304
  }
266
- /**
267
- * Rebuilds ids and derived ARIA from the settled target graph without reporting
268
- * a user validation action.
269
- */
270
305
  #reconcileDom() {
271
306
  this.#ensureAssociationIds();
272
307
  this.#adoptCurrentControl();
@@ -284,7 +319,6 @@ var FormFieldController = class extends Controller {
284
319
  const describedBy = this.#uniqueTokens([...this.#baseDescribedBy, ...associationIds]);
285
320
  this.#ariaDescribedBy.write(control, describedBy.length > 0 ? describedBy.join(" ") : null);
286
321
  }
287
- /** Assigns stable ids before either capture or reflection uses them. */
288
322
  #ensureAssociationIds() {
289
323
  for (const description of this.descriptionTargets) {
290
324
  ensureId(description, "stimeo--form-field-desc");
@@ -293,7 +327,6 @@ var FormFieldController = class extends Controller {
293
327
  ensureId(error, "stimeo--form-field-error");
294
328
  }
295
329
  }
296
- /** Switches ARIA ownership when the singular current control target changes. */
297
330
  #adoptCurrentControl() {
298
331
  const next = this.hasControlTarget ? this.controlTarget : null;
299
332
  if (next === this.#activeControl) return;
@@ -301,7 +334,6 @@ var FormFieldController = class extends Controller {
301
334
  this.#activeControl = next;
302
335
  this.#baseDescribedBy = next ? this.#externalDescribedByTokens(next) : [];
303
336
  }
304
- /** Restores one departed control without overwriting later consumer edits. */
305
337
  #releaseControl(control) {
306
338
  this.#ariaDescribedBy.return(control);
307
339
  this.#ariaErrorMessage.return(control);
@@ -311,26 +343,19 @@ var FormFieldController = class extends Controller {
311
343
  this.#baseDescribedBy = [];
312
344
  }
313
345
  }
314
- /** Error targets currently visible and non-empty, in document order. */
315
346
  #shownErrors() {
316
347
  return this.#orderedElements(
317
348
  this.errorTargets.filter((error) => !error.hidden && (error.textContent ?? "").trim() !== "")
318
349
  );
319
350
  }
320
- /** Text of the first shown error, for validation detail and announcement. */
321
351
  #shownMessage() {
322
352
  return (this.#shownErrors()[0]?.textContent ?? "").trim();
323
353
  }
324
- /** Resolves a message from a string argument or an action event's params. */
325
354
  #resolveMessage(arg) {
326
355
  if (typeof arg === "string") return arg;
327
356
  const message = arg?.params?.message;
328
357
  return typeof message === "string" ? message : null;
329
358
  }
330
- /**
331
- * Tokens authored on a newly adopted control, excluding ids this controller
332
- * owns through its current description/error targets.
333
- */
334
359
  #externalDescribedByTokens(control) {
335
360
  const owned = /* @__PURE__ */ new Set([
336
361
  ...this.descriptionTargets.map((description) => description.id),
@@ -341,7 +366,6 @@ var FormFieldController = class extends Controller {
341
366
  existing.split(/\s+/).filter((token) => token.length > 0 && !owned.has(token))
342
367
  );
343
368
  }
344
- /** Deduplicates ARIA tokens without disturbing their first occurrence. */
345
369
  #uniqueTokens(tokens) {
346
370
  const seen = /* @__PURE__ */ new Set();
347
371
  return tokens.filter((token) => {
@@ -350,14 +374,12 @@ var FormFieldController = class extends Controller {
350
374
  return true;
351
375
  });
352
376
  }
353
- /** Returns unique current targets in DOM order before serializing IDREF lists. */
354
377
  #orderedElements(elements) {
355
378
  const candidates = new Set(elements);
356
379
  return [this.element, ...this.element.querySelectorAll("*")].filter(
357
380
  (element) => candidates.has(element)
358
381
  );
359
382
  }
360
- /** Whether one retained-node mutation can alter this controller's derived state. */
361
383
  #isRelevantMutation(record) {
362
384
  const target = record.target;
363
385
  if (record.type === "attributes") {
@@ -367,14 +389,7 @@ var FormFieldController = class extends Controller {
367
389
  }
368
390
  return ownerIndex(this.errorTargets, target) !== -1;
369
391
  }
370
- /** Returns borrowed control ARIA before Turbo snapshots the page. */
371
- #rewindForCache() {
372
- this.#ariaDescribedBy.returnAll();
373
- this.#ariaErrorMessage.returnAll();
374
- this.#ariaInvalid.returnAll();
375
- }
376
392
  };
377
393
 
378
394
  export { FormFieldController };
379
- //# sourceMappingURL=form_field_controller.js.map
380
395
  //# sourceMappingURL=form_field_controller.js.map