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/auto_submit_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,36 +10,153 @@ function announce(message, options = {}) {
13
10
  );
14
11
  }
15
12
 
16
- // src/utils/before_cache_reset.ts
17
- var BeforeCacheReset = class _BeforeCacheReset {
18
- /** Every subscribed instance, iterated by the one shared document listener. */
19
- static #subscribers = /* @__PURE__ */ new Set();
20
- /** The shared listener; installed while at least one instance is subscribed. */
21
- static #onBeforeCache = () => {
22
- for (const subscriber of _BeforeCacheReset.#subscribers) subscriber.#rewind();
23
- };
24
- #rewind;
25
- /** @param rewind - the pass that returns this controller's state to its initial form. */
26
- constructor(rewind) {
27
- this.#rewind = rewind;
28
- }
29
- /** Subscribes to `turbo:before-cache`; call from `connect()`. Idempotent. */
30
- activate() {
31
- const first = _BeforeCacheReset.#subscribers.size === 0;
32
- _BeforeCacheReset.#subscribers.add(this);
33
- if (first) {
34
- document.addEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
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
+ function isAttributeValue(value) {
24
+ return value === null || typeof value === "string";
25
+ }
26
+ function readLeaseRecord(element, record) {
27
+ try {
28
+ const parsed = JSON.parse(element.getAttribute(record) ?? "null");
29
+ if (!Array.isArray(parsed)) return void 0;
30
+ const [original, written, ...rest] = parsed;
31
+ const linked = rest[0] !== false;
32
+ const beneath = linked ? rest : rest.slice(1);
33
+ if (!beneath.every((under) => typeof under === "string")) return void 0;
34
+ return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
35
+ } catch {
36
+ return void 0;
37
+ }
38
+ }
39
+ var AttributeLease = class _AttributeLease {
40
+ static #registry = sharedRegistry(
41
+ "stimeo-ui.attribute-lease.registry.v1",
42
+ () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
43
+ );
44
+ #attribute;
45
+ #record;
46
+ #base;
47
+ #held = /* @__PURE__ */ new Set();
48
+ constructor(attribute, owner, options = {}) {
49
+ this.#attribute = attribute;
50
+ this.#record = `data-${owner}-${attribute}-lease`;
51
+ this.#base = options.base === true;
52
+ const names = _AttributeLease.#registry.names;
53
+ names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
54
+ }
55
+ write(element, value) {
56
+ const stack = this.#stack(element);
57
+ const hold = this.#take(stack) ?? this.#acquire(element, stack);
58
+ this.#held.add(element);
59
+ const shows = !this.#covered(element, stack, hold);
60
+ hold.written = value;
61
+ this.#mark(element, stack);
62
+ if (shows) this.#reflect(element, value);
63
+ }
64
+ return(element) {
65
+ const held = this.#held.delete(element);
66
+ const known = _AttributeLease.#registry.stacks.get(element)?.has(this.#attribute);
67
+ const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
68
+ const hold = this.#take(stack);
69
+ if (!hold) return false;
70
+ const carries = element.getAttribute(this.#attribute) === hold.written;
71
+ const owns = carries && !this.#covered(element, stack, hold);
72
+ const index = stack.indexOf(hold);
73
+ stack.splice(index, 1);
74
+ const above = stack[index];
75
+ if (above) above.linked &&= hold.linked;
76
+ this.#mark(element, stack);
77
+ if (!owns) return true;
78
+ const below = hold.linked ? stack[index - 1] : void 0;
79
+ this.#reflect(element, below ? below.written : hold.original);
80
+ return true;
81
+ }
82
+ returnAll() {
83
+ for (const element of Array.from(this.#held)) this.return(element);
84
+ }
85
+ #stack(element) {
86
+ const stacks = _AttributeLease.#registry.stacks;
87
+ const byAttribute = stacks.get(element) ?? /* @__PURE__ */ new Map();
88
+ stacks.set(element, byAttribute);
89
+ const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);
90
+ byAttribute.set(this.#attribute, stack);
91
+ return stack;
92
+ }
93
+ #seed(element) {
94
+ const found = [];
95
+ for (const record of _AttributeLease.#registry.names.get(this.#attribute) ?? []) {
96
+ const read = readLeaseRecord(element, record);
97
+ if (read) found.push({ ...read, record });
35
98
  }
99
+ const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
100
+ return found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
101
+ lease: null,
102
+ record,
103
+ written,
104
+ original,
105
+ linked: linked && index > 0
106
+ }));
36
107
  }
37
- /** Unsubscribes; call from `disconnect()`. Safe when never subscribed. */
38
- deactivate() {
39
- _BeforeCacheReset.#subscribers.delete(this);
40
- if (_BeforeCacheReset.#subscribers.size > 0) return;
41
- document.removeEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
108
+ #take(stack) {
109
+ const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
110
+ if (hold) hold.lease = this;
111
+ return hold;
112
+ }
113
+ #acquire(element, stack) {
114
+ const current = element.getAttribute(this.#attribute);
115
+ const top = stack.at(-1);
116
+ const bottom = stack[0];
117
+ const over = top?.written === current ? top : void 0;
118
+ const from = this.#base ? bottom : over;
119
+ const hold = {
120
+ lease: this,
121
+ record: this.#record,
122
+ written: current,
123
+ original: from ? from.original : current,
124
+ linked: !this.#base && over !== void 0
125
+ };
126
+ if (this.#base && bottom) {
127
+ bottom.linked = true;
128
+ stack.unshift(hold);
129
+ } else stack.push(hold);
130
+ return hold;
131
+ }
132
+ #covered(element, stack, hold) {
133
+ const current = element.getAttribute(this.#attribute);
134
+ return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
135
+ }
136
+ #mark(element, stack) {
137
+ const records = /* @__PURE__ */ new Map([[this.#record, null]]);
138
+ stack.forEach((hold, index) => {
139
+ const names = stack.slice(0, index).map((under) => under.record);
140
+ const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
141
+ const marker = hold.linked || beneath.length === 0 ? [] : [false];
142
+ records.set(
143
+ hold.record,
144
+ hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
145
+ );
146
+ });
147
+ for (const [name, recorded] of records) {
148
+ if (element.getAttribute(name) === recorded) continue;
149
+ if (recorded === null) element.removeAttribute(name);
150
+ else element.setAttribute(name, recorded);
151
+ }
152
+ }
153
+ #reflect(element, value) {
154
+ if (element.getAttribute(this.#attribute) === value) return;
155
+ if (value === null) element.removeAttribute(this.#attribute);
156
+ else element.setAttribute(this.#attribute, value);
42
157
  }
43
158
  };
44
159
 
45
- // src/utils/composition_tracker.ts
46
160
  var COMPOSITION_INPUT_TYPES = /* @__PURE__ */ new Set([
47
161
  "insertCompositionText",
48
162
  "insertFromComposition",
@@ -54,13 +168,11 @@ var CompositionTracker = class {
54
168
  #activeTargets = /* @__PURE__ */ new Set();
55
169
  #onStart;
56
170
  #onEnd;
57
- /** The field whose confirming `input` is still owed, while the window is open. */
58
171
  #confirmedTarget = null;
59
172
  constructor(options = {}) {
60
173
  this.#onStart = options.onStart;
61
174
  this.#onEnd = options.onEnd;
62
175
  }
63
- /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */
64
176
  observe(target) {
65
177
  if (this.#observedTargets.has(target)) return;
66
178
  target.addEventListener("compositionstart", this.#handleStart);
@@ -68,7 +180,6 @@ var CompositionTracker = class {
68
180
  target.addEventListener("keydown", this.#handleKeydown);
69
181
  this.#observedTargets.add(target);
70
182
  }
71
- /** Stops tracking one target and clears any active composition it owned. */
72
183
  unobserve(target) {
73
184
  if (!this.#observedTargets.delete(target)) return;
74
185
  target.removeEventListener("compositionstart", this.#handleStart);
@@ -77,7 +188,6 @@ var CompositionTracker = class {
77
188
  this.#activeTargets.delete(target);
78
189
  if (this.#confirmedTarget === target) this.#confirmedTarget = null;
79
190
  }
80
- /** Releases every listener and clears state so reconnect starts cleanly. */
81
191
  disconnect() {
82
192
  for (const target of this.#observedTargets) {
83
193
  target.removeEventListener("compositionstart", this.#handleStart);
@@ -88,16 +198,9 @@ var CompositionTracker = class {
88
198
  this.#activeTargets.clear();
89
199
  this.#confirmedTarget = null;
90
200
  }
91
- /** True when lifecycle tracking or the current event reports composition. */
92
201
  isComposing(event) {
93
202
  return this.#activeTargets.size > 0 || event?.isComposing === true;
94
203
  }
95
- /**
96
- * Whether `event` is the `input` echoing the composition just confirmed.
97
- *
98
- * Asking closes the window either way, so one confirmation is folded at most
99
- * once and a consumer asks once per `input`.
100
- */
101
204
  consumesConfirmedInput(event) {
102
205
  const confirmed = this.#confirmedTarget;
103
206
  this.#confirmedTarget = null;
@@ -115,73 +218,123 @@ var CompositionTracker = class {
115
218
  this.#confirmedTarget = event.target;
116
219
  this.#onEnd?.(event);
117
220
  };
118
- /** A key on an observed field opens an edit of its own, so no echo is owed. */
119
221
  #handleKeydown = () => {
120
222
  this.#confirmedTarget = null;
121
223
  };
122
224
  };
123
225
 
124
- // src/utils/listener_set.ts
226
+ var DetachGate = class _DetachGate {
227
+ #pending = false;
228
+ get pending() {
229
+ return this.#pending;
230
+ }
231
+ static isDetached(host) {
232
+ return !host.element.isConnected || !_DetachGate.#listed(host);
233
+ }
234
+ disconnected(host, teardown) {
235
+ const carried = _DetachGate.#carried(host);
236
+ if (!carried && _DetachGate.isDetached(host)) {
237
+ this.#pending = false;
238
+ teardown();
239
+ return;
240
+ }
241
+ this.#pending = true;
242
+ const probe = () => {
243
+ if (!this.#pending) return;
244
+ this.#pending = false;
245
+ teardown();
246
+ };
247
+ if (carried) setTimeout(probe, 0);
248
+ else queueMicrotask(probe);
249
+ }
250
+ static #carried(host) {
251
+ const element = host.element;
252
+ return !element.isConnected && element.closest("[data-turbo-permanent]") !== null && _DetachGate.#listed(host);
253
+ }
254
+ static #listed(host) {
255
+ const tokens = (host.element.getAttribute("data-controller") ?? "").split(/\s+/);
256
+ return tokens.includes(host.identifier);
257
+ }
258
+ cancel() {
259
+ this.#pending = false;
260
+ }
261
+ };
262
+
125
263
  var ListenerSet = class {
126
- /** The generation every `add` joins until the next `dispose()`. */
127
264
  #abort = new AbortController();
128
- /**
129
- * Attaches `handler` to the open generation, exactly as the caller spelled it.
130
- *
131
- * The set supplies the signal, so `options` carries everything else the DOM
132
- * accepts — `capture` included, which has to match at release time and no
133
- * longer has a second place to drift from.
134
- */
135
265
  add(target, type, handler, options) {
136
266
  target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
137
267
  }
138
- /**
139
- * Releases every listener of the open generation, synchronously, and opens the
140
- * next one. Idempotent, and safe before anything has been added.
141
- */
142
268
  dispose() {
143
269
  this.#abort.abort();
144
270
  this.#abort = new AbortController();
145
271
  }
146
272
  };
147
273
 
148
- // src/utils/safe_timeout.ts
274
+ var MAX_TIMER_DELAY_MS = 2147483647;
275
+
276
+ var NUMBER_BOUNDS = {
277
+ timer: { finite: true, min: 0, max: MAX_TIMER_DELAY_MS }};
278
+ function matchesNumberBounds(value, bounds) {
279
+ if (!Number.isFinite(value)) {
280
+ const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
281
+ if (direction === null) return false;
282
+ if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
283
+ }
284
+ if (bounds.min !== void 0 && value < bounds.min) return false;
285
+ if (bounds.max !== void 0 && value > bounds.max) return false;
286
+ if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
287
+ if (bounds.integer && !Number.isInteger(value)) return false;
288
+ if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
289
+ return true;
290
+ }
291
+
292
+ function readNumber(raw, fallback, bounds) {
293
+ return matchesNumberBounds(raw, bounds) ? raw : fallback;
294
+ }
295
+
296
+ var NumberValueReader = class {
297
+ #lastRejected = /* @__PURE__ */ new Map();
298
+ read(owner, name, raw, fallback, bounds) {
299
+ const resolved = readNumber(raw, fallback, bounds);
300
+ if (matchesNumberBounds(raw, bounds)) {
301
+ this.#lastRejected.delete(name);
302
+ return resolved;
303
+ }
304
+ const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
305
+ const literal = owner.element.getAttribute(attribute);
306
+ if (literal === null) {
307
+ this.#lastRejected.delete(name);
308
+ return resolved;
309
+ }
310
+ if (this.#lastRejected.get(name) !== literal) {
311
+ this.#lastRejected.set(name, literal);
312
+ console.warn(
313
+ `Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
314
+ );
315
+ }
316
+ return resolved;
317
+ }
318
+ };
319
+
149
320
  var TimerRegistry = class {
150
- /** Live timer ids that have not yet been cleared (or, for timeouts, fired). */
151
321
  ids = /* @__PURE__ */ new Set();
152
- /**
153
- * Cancels a single tracked timer.
154
- *
155
- * No-ops if the id is unknown (already cleared, fired, or never owned by this
156
- * registry), so callers can clear defensively without guarding.
157
- */
158
322
  clear(id) {
159
323
  if (this.ids.delete(id)) {
160
324
  this.cancel(id);
161
325
  }
162
326
  }
163
- /**
164
- * Cancels every tracked timer. Call this from a controller's `disconnect()`
165
- * to guarantee no timer outlives the element.
166
- */
167
327
  clearAll() {
168
328
  for (const id of this.ids) {
169
329
  this.cancel(id);
170
330
  }
171
331
  this.ids.clear();
172
332
  }
173
- /** Number of timers currently tracked (pending). */
174
333
  get size() {
175
334
  return this.ids.size;
176
335
  }
177
336
  };
178
337
  var SafeTimeout = class extends TimerRegistry {
179
- /**
180
- * Schedules `callback` after `delay` ms and returns the timer id.
181
- *
182
- * The id is removed from the registry automatically when the timeout fires,
183
- * so {@link TimerRegistry.size | size} reflects only still-pending timers.
184
- */
185
338
  set(callback, delay) {
186
339
  const id = this.schedule(() => {
187
340
  this.ids.delete(id);
@@ -198,8 +351,19 @@ var SafeTimeout = class extends TimerRegistry {
198
351
  }
199
352
  };
200
353
 
201
- // src/controllers/auto_submit_controller.ts
202
- var AutoSubmitController = class extends Controller {
354
+ var TransientHooks = class {
355
+ #attributes;
356
+ constructor(options) {
357
+ this.#attributes = options.attributes;
358
+ }
359
+ reset(element) {
360
+ for (const attribute of this.#attributes) element.removeAttribute(attribute);
361
+ }
362
+ };
363
+
364
+ var PENDING = new TransientHooks({ attributes: ["data-auto-submit-pending"] });
365
+ var AutoSubmitController = class _AutoSubmitController extends Controller {
366
+ #numbers = new NumberValueReader();
203
367
  static targets = ["form"];
204
368
  static values = {
205
369
  debounce: { type: Number, default: 300 },
@@ -207,70 +371,60 @@ var AutoSubmitController = class extends Controller {
207
371
  announce: { type: Boolean, default: false },
208
372
  message: { type: String, default: "" }
209
373
  };
374
+ static valueConstraints = {
375
+ debounce: NUMBER_BOUNDS.timer
376
+ };
210
377
  static actions = ["submit"];
211
378
  static events = ["submit", "done", "reconcile"];
212
- /** Debounce timer registry; one `clearAll()` in disconnect tears it down. */
213
379
  #timers = new SafeTimeout();
214
- /** Id of the pending debounce timer, so a new keystroke can reset it. */
215
380
  #pendingId = 0;
216
- /** Listeners that live with the bound form rather than with the connection. */
217
381
  #formListeners = new ListenerSet();
218
- /** The form the listeners are attached to; target callbacks rebind it. */
219
382
  #boundForm = null;
220
- /** Rewinds the transient state hooks just before Turbo snapshots the page. */
221
- #beforeCache = new BeforeCacheReset(() => this.#rewindForCache());
222
- /**
223
- * Clears `aria-busy` and emits completion once Turbo finishes the submit.
224
- *
225
- * @stimeoRuntimeOnly `message` and `announce` shape the event and the announcement of one
226
- * finished submit; the busy flag it clears does not depend on them.
227
- */
383
+ #busy = new AttributeLease("aria-busy", this.identifier);
384
+ #gate = new DetachGate();
228
385
  #onSubmitEnd = () => {
229
- this.#boundForm?.removeAttribute("aria-busy");
386
+ if (this.#boundForm) this.#busy.return(this.#boundForm);
230
387
  const message = this.messageValue;
231
388
  this.dispatch("done", { detail: { message: message || void 0 } });
232
389
  if (this.announceValue) announce(message);
233
390
  };
234
- /** Owns delegated IME lifecycle state and submits confirmed input text. */
235
391
  #composition = new CompositionTracker({
236
392
  onEnd: (event) => {
237
393
  if (this.#triggers("input")) this.#schedule(event.target ?? null);
238
394
  }
239
395
  });
240
396
  connect() {
241
- this.#beforeCache.activate();
242
- this.#bindForm(this.#resolveForm());
397
+ const moved = this.#gate.pending;
398
+ this.#gate.cancel();
399
+ const form = this.#resolveForm();
400
+ if (moved && form && form === this.#boundForm) {
401
+ this.#composition.observe(form);
402
+ return;
403
+ }
404
+ const stale = form?.hasAttribute("data-auto-submit-pending") === true;
405
+ if (form) PENDING.reset(form);
406
+ const busy = form !== null && this.#busy.return(form);
407
+ this.#bindForm(form);
408
+ if (stale || busy) this.dispatch("reconcile", { detail: {} });
243
409
  }
244
410
  disconnect() {
245
- this.#beforeCache.deactivate();
246
- this.#bindForm(null);
247
411
  this.#composition.disconnect();
248
- this.#timers.clearAll();
249
- this.#pendingId = 0;
412
+ this.#gate.disconnected(this, () => {
413
+ this.#bindForm(null);
414
+ this.#pendingId = 0;
415
+ });
250
416
  }
251
- /** Follows a `form` target added (or swapped in) at runtime. */
252
417
  formTargetConnected() {
253
418
  this.#bindForm(this.#resolveForm());
254
419
  }
255
- /** Follows a `form` target removed (or swapped out) at runtime. */
256
420
  formTargetDisconnected() {
257
421
  this.#bindForm(this.#resolveForm());
258
422
  }
259
- /**
260
- * Schedules a debounced submit. Wired to `input`/`change`; the `on` value is an
261
- * allowlist so a configured subset (e.g. only `change`) is honored even when both
262
- * are bound in markup. Coalesces rapid events into a single `requestSubmit`.
263
- */
264
423
  submit(event) {
265
424
  if (!this.#triggers(event.type)) return;
266
425
  if (event.type === "input" && this.#composition.isComposing(event)) return;
267
426
  this.#schedule(event.target ?? null);
268
427
  }
269
- /**
270
- * Schedules (and coalesces) the debounced submit for the given trigger.
271
- *
272
- * @stimeoRuntimeOnly `debounce` is the delay of the one submit timer this call arms.
273
- */
274
428
  #schedule(trigger) {
275
429
  const form = this.#boundForm;
276
430
  if (!form) return;
@@ -281,23 +435,15 @@ var AutoSubmitController = class extends Controller {
281
435
  form.removeAttribute("data-auto-submit-pending");
282
436
  this.dispatch("submit", { detail: { trigger } });
283
437
  if (form.checkValidity()) {
284
- form.setAttribute("aria-busy", "true");
438
+ this.#busy.write(form, "true");
285
439
  }
286
440
  form.requestSubmit();
287
- }, this.debounceValue);
441
+ }, this.#safeDebounce);
288
442
  }
289
- /** Cancels the pending debounced submit, if any (`clear` no-ops on unknown ids). */
290
443
  #cancelPending() {
291
444
  this.#timers.clear(this.#pendingId);
292
445
  this.#pendingId = 0;
293
446
  }
294
- /**
295
- * Replaces the subscribed form symmetrically. The outgoing form loses the
296
- * `turbo:submit-end`/composition listeners, its pending hook, and any pending
297
- * debounced submit (which described the outgoing form). An in-flight `aria-busy`
298
- * is left for `turbo:submit-end` or the pre-cache rewind — removing it here
299
- * would wipe a legitimately in-progress submission.
300
- */
301
447
  #bindForm(form) {
302
448
  if (form === this.#boundForm) return;
303
449
  const previous = this.#boundForm;
@@ -312,25 +458,23 @@ var AutoSubmitController = class extends Controller {
312
458
  this.#formListeners.add(form, "turbo:submit-end", this.#onSubmitEnd);
313
459
  this.#composition.observe(form);
314
460
  }
315
- /** Resolves the form: the explicit `form` target, else a `<form>` root, else null. */
316
461
  #resolveForm() {
317
462
  if (this.hasFormTarget) return this.formTarget;
318
463
  return this.element instanceof HTMLFormElement ? this.element : null;
319
464
  }
320
- /** Returns the transient state hooks to their initial (absent) state. */
321
- #rewindForCache() {
322
- const inProgress = this.#pendingId !== 0 || this.#boundForm?.hasAttribute("aria-busy") === true;
323
- this.#cancelPending();
324
- this.#boundForm?.removeAttribute("data-auto-submit-pending");
325
- this.#boundForm?.removeAttribute("aria-busy");
326
- if (inProgress) this.dispatch("reconcile", { detail: {} });
327
- }
328
- /** Whether `type` is one of the whitespace-separated event types in `on`. */
329
465
  #triggers(type) {
330
466
  return this.onValue.split(/\s+/).filter(Boolean).includes(type);
331
467
  }
468
+ get #safeDebounce() {
469
+ return this.#numbers.read(
470
+ this,
471
+ "debounce",
472
+ this.debounceValue,
473
+ _AutoSubmitController.values.debounce.default,
474
+ _AutoSubmitController.valueConstraints.debounce
475
+ );
476
+ }
332
477
  };
333
478
 
334
479
  export { AutoSubmitController };
335
- //# sourceMappingURL=auto_submit_controller.js.map
336
480
  //# sourceMappingURL=auto_submit_controller.js.map