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,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
174
  };
73
175
 
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
- };
102
-
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,25 +206,29 @@ var MicrotaskCoalescer = class {
139
206
  }
140
207
  };
141
208
 
142
- // src/controllers/form_field_controller.ts
143
209
  var OBSERVED_ATTRIBUTES = ["hidden", "id"];
144
- var FormFieldController = class _FormFieldController extends Controller {
210
+ var FormFieldController = class extends Controller {
145
211
  static targets = ["control", "description", "error"];
146
212
  static values = {
147
213
  focusOnError: { type: Boolean, default: false }
148
214
  };
149
215
  static actions = ["clearError", "setError"];
150
216
  static events = ["validate"];
151
- /** Root attribute (CSS hook) reflecting the invalid state. */
152
- static #INVALID_ATTR = "data-stimeo--form-field-invalid";
153
- /** Collapses one target/morph batch into one silent ARIA reconciliation. */
217
+ get #invalidAttribute() {
218
+ return `data-${this.identifier}-invalid`;
219
+ }
154
220
  #reconcile = new MicrotaskCoalescer(() => this.#reconcileDom());
155
- /** Returns borrowed control ARIA before Turbo snapshots the page. */
156
- #beforeCache = new BeforeCacheReset(() => this.#rewindForCache());
157
- #ariaDescribedBy = new AttributeLease("aria-describedby");
158
- #ariaErrorMessage = new AttributeLease("aria-errormessage");
159
- #ariaInvalid = new AttributeLease("aria-invalid");
160
- /** 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
+ });
161
232
  #observer = new MutationObserver((records) => {
162
233
  if (records.some((record) => this.#isRelevantMutation(record))) {
163
234
  this.#reconcile.schedule();
@@ -167,13 +238,10 @@ var FormFieldController = class _FormFieldController extends Controller {
167
238
  #baseDescribedBy = [];
168
239
  #explicitInvalid = false;
169
240
  #initialized = false;
170
- /** Wires the initial graph and starts retained-target reconciliation. */
171
241
  connect() {
172
242
  this.#reconcile.activate();
173
- this.#ensureAssociationIds();
174
- this.#beforeCache.activate();
175
243
  if (!this.#initialized) {
176
- this.#explicitInvalid = this.element.hasAttribute(_FormFieldController.#INVALID_ATTR) && this.#shownErrors().length === 0;
244
+ this.#explicitInvalid = this.element.hasAttribute(this.#invalidAttribute) && this.#shownErrors().length === 0;
177
245
  this.#initialized = true;
178
246
  }
179
247
  this.#reconcileDom();
@@ -185,49 +253,29 @@ var FormFieldController = class _FormFieldController extends Controller {
185
253
  subtree: true
186
254
  });
187
255
  }
188
- /** Releases observers, queued work, and ARIA borrowed on the current control. */
189
256
  disconnect() {
190
257
  this.#reconcile.cancel();
191
258
  this.#observer.disconnect();
192
- this.#beforeCache.deactivate();
193
259
  this.#activeControl && this.#releaseControl(this.#activeControl);
194
260
  }
195
- /** Reconciles a control inserted or replaced at runtime. */
196
261
  controlTargetConnected() {
197
262
  this.#reconcile.schedule();
198
263
  }
199
- /** Schedules restoration of authored ARIA when a control leaves this field. */
200
264
  controlTargetDisconnected() {
201
265
  this.#reconcile.schedule();
202
266
  }
203
- /** Reconciles a description inserted or replaced at runtime. */
204
267
  descriptionTargetConnected() {
205
268
  this.#reconcile.schedule();
206
269
  }
207
- /** Removes a departed description from the control's association graph. */
208
270
  descriptionTargetDisconnected() {
209
271
  this.#reconcile.schedule();
210
272
  }
211
- /** Reconciles an error region inserted or replaced at runtime. */
212
273
  errorTargetConnected() {
213
274
  this.#reconcile.schedule();
214
275
  }
215
- /** Removes a departed error from invalid state and the association graph. */
216
276
  errorTargetDisconnected() {
217
277
  this.#reconcile.schedule();
218
278
  }
219
- /**
220
- * Marks the field invalid and shows the error message. Bound via `data-action`
221
- * (`#setError`) or callable directly.
222
- *
223
- * A non-empty shown message is announced exactly once through the shared
224
- * assertive announcer. Initial/server reconciliation is deliberately silent.
225
- *
226
- * @param arg - Either the message string, or the action event whose
227
- * `data-stimeo--form-field-message-param` supplies it. When no message is
228
- * resolvable, any already-populated error targets are simply (re)shown.
229
- * @param options - Programmatic overrides. Stimulus actions use the Values.
230
- */
231
279
  setError(arg, options = {}) {
232
280
  const message = this.#resolveMessage(arg);
233
281
  if (message !== null && this.hasErrorTarget) {
@@ -244,13 +292,6 @@ var FormFieldController = class _FormFieldController extends Controller {
244
292
  announce(shownMessage, { assertive: true });
245
293
  if (options.focus ?? this.focusOnErrorValue) this.#activeControl?.focus();
246
294
  }
247
- /**
248
- * Clears the error: empties and hides every error target and marks the field
249
- * valid. Bound via `data-action` (`#clearError`) or callable directly.
250
- *
251
- * Clearing is silent: the visual/ARIA state and validation event are sufficient,
252
- * while success wording remains an explicit consumer announcement.
253
- */
254
295
  clearError() {
255
296
  for (const error of this.errorTargets) {
256
297
  error.replaceChildren();
@@ -261,16 +302,12 @@ var FormFieldController = class _FormFieldController extends Controller {
261
302
  const detail = { valid: true, message: "" };
262
303
  this.dispatch("validate", { detail });
263
304
  }
264
- /**
265
- * Rebuilds ids and derived ARIA from the settled target graph without reporting
266
- * a user validation action.
267
- */
268
305
  #reconcileDom() {
269
306
  this.#ensureAssociationIds();
270
307
  this.#adoptCurrentControl();
271
308
  const shown = this.#shownErrors();
272
309
  const invalid = this.#explicitInvalid || shown.length > 0;
273
- this.element.toggleAttribute(_FormFieldController.#INVALID_ATTR, invalid);
310
+ this.element.toggleAttribute(this.#invalidAttribute, invalid);
274
311
  const control = this.#activeControl;
275
312
  if (!control) return;
276
313
  this.#ariaInvalid.write(control, invalid ? "true" : "false");
@@ -282,7 +319,6 @@ var FormFieldController = class _FormFieldController extends Controller {
282
319
  const describedBy = this.#uniqueTokens([...this.#baseDescribedBy, ...associationIds]);
283
320
  this.#ariaDescribedBy.write(control, describedBy.length > 0 ? describedBy.join(" ") : null);
284
321
  }
285
- /** Assigns stable ids before either capture or reflection uses them. */
286
322
  #ensureAssociationIds() {
287
323
  for (const description of this.descriptionTargets) {
288
324
  ensureId(description, "stimeo--form-field-desc");
@@ -291,7 +327,6 @@ var FormFieldController = class _FormFieldController extends Controller {
291
327
  ensureId(error, "stimeo--form-field-error");
292
328
  }
293
329
  }
294
- /** Switches ARIA ownership when the singular current control target changes. */
295
330
  #adoptCurrentControl() {
296
331
  const next = this.hasControlTarget ? this.controlTarget : null;
297
332
  if (next === this.#activeControl) return;
@@ -299,7 +334,6 @@ var FormFieldController = class _FormFieldController extends Controller {
299
334
  this.#activeControl = next;
300
335
  this.#baseDescribedBy = next ? this.#externalDescribedByTokens(next) : [];
301
336
  }
302
- /** Restores one departed control without overwriting later consumer edits. */
303
337
  #releaseControl(control) {
304
338
  this.#ariaDescribedBy.return(control);
305
339
  this.#ariaErrorMessage.return(control);
@@ -309,26 +343,19 @@ var FormFieldController = class _FormFieldController extends Controller {
309
343
  this.#baseDescribedBy = [];
310
344
  }
311
345
  }
312
- /** Error targets currently visible and non-empty, in document order. */
313
346
  #shownErrors() {
314
347
  return this.#orderedElements(
315
348
  this.errorTargets.filter((error) => !error.hidden && (error.textContent ?? "").trim() !== "")
316
349
  );
317
350
  }
318
- /** Text of the first shown error, for validation detail and announcement. */
319
351
  #shownMessage() {
320
352
  return (this.#shownErrors()[0]?.textContent ?? "").trim();
321
353
  }
322
- /** Resolves a message from a string argument or an action event's params. */
323
354
  #resolveMessage(arg) {
324
355
  if (typeof arg === "string") return arg;
325
356
  const message = arg?.params?.message;
326
357
  return typeof message === "string" ? message : null;
327
358
  }
328
- /**
329
- * Tokens authored on a newly adopted control, excluding ids this controller
330
- * owns through its current description/error targets.
331
- */
332
359
  #externalDescribedByTokens(control) {
333
360
  const owned = /* @__PURE__ */ new Set([
334
361
  ...this.descriptionTargets.map((description) => description.id),
@@ -339,7 +366,6 @@ var FormFieldController = class _FormFieldController extends Controller {
339
366
  existing.split(/\s+/).filter((token) => token.length > 0 && !owned.has(token))
340
367
  );
341
368
  }
342
- /** Deduplicates ARIA tokens without disturbing their first occurrence. */
343
369
  #uniqueTokens(tokens) {
344
370
  const seen = /* @__PURE__ */ new Set();
345
371
  return tokens.filter((token) => {
@@ -348,14 +374,12 @@ var FormFieldController = class _FormFieldController extends Controller {
348
374
  return true;
349
375
  });
350
376
  }
351
- /** Returns unique current targets in DOM order before serializing IDREF lists. */
352
377
  #orderedElements(elements) {
353
378
  const candidates = new Set(elements);
354
379
  return [this.element, ...this.element.querySelectorAll("*")].filter(
355
380
  (element) => candidates.has(element)
356
381
  );
357
382
  }
358
- /** Whether one retained-node mutation can alter this controller's derived state. */
359
383
  #isRelevantMutation(record) {
360
384
  const target = record.target;
361
385
  if (record.type === "attributes") {
@@ -365,14 +389,7 @@ var FormFieldController = class _FormFieldController extends Controller {
365
389
  }
366
390
  return ownerIndex(this.errorTargets, target) !== -1;
367
391
  }
368
- /** Returns borrowed control ARIA before Turbo snapshots the page. */
369
- #rewindForCache() {
370
- this.#ariaDescribedBy.returnAll();
371
- this.#ariaErrorMessage.returnAll();
372
- this.#ariaInvalid.returnAll();
373
- }
374
392
  };
375
393
 
376
394
  export { FormFieldController };
377
- //# sourceMappingURL=form_field_controller.js.map
378
395
  //# sourceMappingURL=form_field_controller.js.map