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/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,143 +10,331 @@ 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
+ }));
107
+ }
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;
36
112
  }
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);
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
160
+ var COMPOSITION_INPUT_TYPES = /* @__PURE__ */ new Set([
161
+ "insertCompositionText",
162
+ "insertFromComposition",
163
+ "deleteCompositionText",
164
+ "deleteByComposition"
165
+ ]);
46
166
  var CompositionTracker = class {
47
167
  #observedTargets = /* @__PURE__ */ new Set();
48
168
  #activeTargets = /* @__PURE__ */ new Set();
49
169
  #onStart;
50
170
  #onEnd;
171
+ #confirmedTarget = null;
51
172
  constructor(options = {}) {
52
173
  this.#onStart = options.onStart;
53
174
  this.#onEnd = options.onEnd;
54
175
  }
55
- /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */
56
176
  observe(target) {
57
177
  if (this.#observedTargets.has(target)) return;
58
178
  target.addEventListener("compositionstart", this.#handleStart);
59
179
  target.addEventListener("compositionend", this.#handleEnd);
180
+ target.addEventListener("keydown", this.#handleKeydown);
60
181
  this.#observedTargets.add(target);
61
182
  }
62
- /** Stops tracking one target and clears any active composition it owned. */
63
183
  unobserve(target) {
64
184
  if (!this.#observedTargets.delete(target)) return;
65
185
  target.removeEventListener("compositionstart", this.#handleStart);
66
186
  target.removeEventListener("compositionend", this.#handleEnd);
187
+ target.removeEventListener("keydown", this.#handleKeydown);
67
188
  this.#activeTargets.delete(target);
189
+ if (this.#confirmedTarget === target) this.#confirmedTarget = null;
68
190
  }
69
- /** Releases every listener and clears state so reconnect starts cleanly. */
70
191
  disconnect() {
71
192
  for (const target of this.#observedTargets) {
72
193
  target.removeEventListener("compositionstart", this.#handleStart);
73
194
  target.removeEventListener("compositionend", this.#handleEnd);
195
+ target.removeEventListener("keydown", this.#handleKeydown);
74
196
  }
75
197
  this.#observedTargets.clear();
76
198
  this.#activeTargets.clear();
199
+ this.#confirmedTarget = null;
77
200
  }
78
- /** True when lifecycle tracking or the current event reports composition. */
79
201
  isComposing(event) {
80
202
  return this.#activeTargets.size > 0 || event?.isComposing === true;
81
203
  }
204
+ consumesConfirmedInput(event) {
205
+ const confirmed = this.#confirmedTarget;
206
+ this.#confirmedTarget = null;
207
+ if (confirmed === null || confirmed !== event.target) return false;
208
+ const inputType = event.inputType;
209
+ return !inputType || COMPOSITION_INPUT_TYPES.has(inputType);
210
+ }
82
211
  #handleStart = (event) => {
212
+ this.#confirmedTarget = null;
83
213
  if (event.currentTarget) this.#activeTargets.add(event.currentTarget);
84
214
  this.#onStart?.(event);
85
215
  };
86
216
  #handleEnd = (event) => {
87
217
  if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);
218
+ this.#confirmedTarget = event.target;
88
219
  this.#onEnd?.(event);
89
220
  };
221
+ #handleKeydown = () => {
222
+ this.#confirmedTarget = null;
223
+ };
224
+ };
225
+
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
+ }
90
261
  };
91
262
 
92
- // src/utils/listener_set.ts
93
263
  var ListenerSet = class {
94
- /** The generation every `add` joins until the next `dispose()`. */
95
264
  #abort = new AbortController();
96
- /**
97
- * Attaches `handler` to the open generation, exactly as the caller spelled it.
98
- *
99
- * The set supplies the signal, so `options` carries everything else the DOM
100
- * accepts — `capture` included, which has to match at release time and no
101
- * longer has a second place to drift from.
102
- */
103
265
  add(target, type, handler, options) {
104
266
  target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
105
267
  }
106
- /**
107
- * Releases every listener of the open generation, synchronously, and opens the
108
- * next one. Idempotent, and safe before anything has been added.
109
- */
110
268
  dispose() {
111
269
  this.#abort.abort();
112
270
  this.#abort = new AbortController();
113
271
  }
114
272
  };
115
273
 
116
- // 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
+
117
320
  var TimerRegistry = class {
118
- /** Live timer ids that have not yet been cleared (or, for timeouts, fired). */
119
321
  ids = /* @__PURE__ */ new Set();
120
- /**
121
- * Cancels a single tracked timer.
122
- *
123
- * No-ops if the id is unknown (already cleared, fired, or never owned by this
124
- * registry), so callers can clear defensively without guarding.
125
- */
126
322
  clear(id) {
127
323
  if (this.ids.delete(id)) {
128
324
  this.cancel(id);
129
325
  }
130
326
  }
131
- /**
132
- * Cancels every tracked timer. Call this from a controller's `disconnect()`
133
- * to guarantee no timer outlives the element.
134
- */
135
327
  clearAll() {
136
328
  for (const id of this.ids) {
137
329
  this.cancel(id);
138
330
  }
139
331
  this.ids.clear();
140
332
  }
141
- /** Number of timers currently tracked (pending). */
142
333
  get size() {
143
334
  return this.ids.size;
144
335
  }
145
336
  };
146
337
  var SafeTimeout = class extends TimerRegistry {
147
- /**
148
- * Schedules `callback` after `delay` ms and returns the timer id.
149
- *
150
- * The id is removed from the registry automatically when the timeout fires,
151
- * so {@link TimerRegistry.size | size} reflects only still-pending timers.
152
- */
153
338
  set(callback, delay) {
154
339
  const id = this.schedule(() => {
155
340
  this.ids.delete(id);
@@ -166,8 +351,19 @@ var SafeTimeout = class extends TimerRegistry {
166
351
  }
167
352
  };
168
353
 
169
- // src/controllers/auto_submit_controller.ts
170
- 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();
171
367
  static targets = ["form"];
172
368
  static values = {
173
369
  debounce: { type: Number, default: 300 },
@@ -175,61 +371,60 @@ var AutoSubmitController = class extends Controller {
175
371
  announce: { type: Boolean, default: false },
176
372
  message: { type: String, default: "" }
177
373
  };
374
+ static valueConstraints = {
375
+ debounce: NUMBER_BOUNDS.timer
376
+ };
178
377
  static actions = ["submit"];
179
378
  static events = ["submit", "done", "reconcile"];
180
- /** Debounce timer registry; one `clearAll()` in disconnect tears it down. */
181
379
  #timers = new SafeTimeout();
182
- /** Id of the pending debounce timer, so a new keystroke can reset it. */
183
380
  #pendingId = 0;
184
- /** Listeners that live with the bound form rather than with the connection. */
185
381
  #formListeners = new ListenerSet();
186
- /** The form the listeners are attached to; target callbacks rebind it. */
187
382
  #boundForm = null;
188
- /** Rewinds the transient state hooks just before Turbo snapshots the page. */
189
- #beforeCache = new BeforeCacheReset(() => this.#rewindForCache());
190
- /** Clears `aria-busy` and emits completion once Turbo finishes the submit. */
383
+ #busy = new AttributeLease("aria-busy", this.identifier);
384
+ #gate = new DetachGate();
191
385
  #onSubmitEnd = () => {
192
- this.#boundForm?.removeAttribute("aria-busy");
386
+ if (this.#boundForm) this.#busy.return(this.#boundForm);
193
387
  const message = this.messageValue;
194
388
  this.dispatch("done", { detail: { message: message || void 0 } });
195
389
  if (this.announceValue) announce(message);
196
390
  };
197
- /** Owns delegated IME lifecycle state and submits confirmed input text. */
198
391
  #composition = new CompositionTracker({
199
392
  onEnd: (event) => {
200
393
  if (this.#triggers("input")) this.#schedule(event.target ?? null);
201
394
  }
202
395
  });
203
396
  connect() {
204
- this.#beforeCache.activate();
205
- 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: {} });
206
409
  }
207
410
  disconnect() {
208
- this.#beforeCache.deactivate();
209
- this.#bindForm(null);
210
411
  this.#composition.disconnect();
211
- this.#timers.clearAll();
212
- this.#pendingId = 0;
412
+ this.#gate.disconnected(this, () => {
413
+ this.#bindForm(null);
414
+ this.#pendingId = 0;
415
+ });
213
416
  }
214
- /** Follows a `form` target added (or swapped in) at runtime. */
215
417
  formTargetConnected() {
216
418
  this.#bindForm(this.#resolveForm());
217
419
  }
218
- /** Follows a `form` target removed (or swapped out) at runtime. */
219
420
  formTargetDisconnected() {
220
421
  this.#bindForm(this.#resolveForm());
221
422
  }
222
- /**
223
- * Schedules a debounced submit. Wired to `input`/`change`; the `on` value is an
224
- * allowlist so a configured subset (e.g. only `change`) is honored even when both
225
- * are bound in markup. Coalesces rapid events into a single `requestSubmit`.
226
- */
227
423
  submit(event) {
228
424
  if (!this.#triggers(event.type)) return;
229
425
  if (event.type === "input" && this.#composition.isComposing(event)) return;
230
426
  this.#schedule(event.target ?? null);
231
427
  }
232
- /** Schedules (and coalesces) the debounced submit for the given trigger. */
233
428
  #schedule(trigger) {
234
429
  const form = this.#boundForm;
235
430
  if (!form) return;
@@ -240,23 +435,15 @@ var AutoSubmitController = class extends Controller {
240
435
  form.removeAttribute("data-auto-submit-pending");
241
436
  this.dispatch("submit", { detail: { trigger } });
242
437
  if (form.checkValidity()) {
243
- form.setAttribute("aria-busy", "true");
438
+ this.#busy.write(form, "true");
244
439
  }
245
440
  form.requestSubmit();
246
- }, this.debounceValue);
441
+ }, this.#safeDebounce);
247
442
  }
248
- /** Cancels the pending debounced submit, if any (`clear` no-ops on unknown ids). */
249
443
  #cancelPending() {
250
444
  this.#timers.clear(this.#pendingId);
251
445
  this.#pendingId = 0;
252
446
  }
253
- /**
254
- * Replaces the subscribed form symmetrically. The outgoing form loses the
255
- * `turbo:submit-end`/composition listeners, its pending hook, and any pending
256
- * debounced submit (which described the outgoing form). An in-flight `aria-busy`
257
- * is left for `turbo:submit-end` or the pre-cache rewind — removing it here
258
- * would wipe a legitimately in-progress submission.
259
- */
260
447
  #bindForm(form) {
261
448
  if (form === this.#boundForm) return;
262
449
  const previous = this.#boundForm;
@@ -271,25 +458,23 @@ var AutoSubmitController = class extends Controller {
271
458
  this.#formListeners.add(form, "turbo:submit-end", this.#onSubmitEnd);
272
459
  this.#composition.observe(form);
273
460
  }
274
- /** Resolves the form: the explicit `form` target, else a `<form>` root, else null. */
275
461
  #resolveForm() {
276
462
  if (this.hasFormTarget) return this.formTarget;
277
463
  return this.element instanceof HTMLFormElement ? this.element : null;
278
464
  }
279
- /** Returns the transient state hooks to their initial (absent) state. */
280
- #rewindForCache() {
281
- const inProgress = this.#pendingId !== 0 || this.#boundForm?.hasAttribute("aria-busy") === true;
282
- this.#cancelPending();
283
- this.#boundForm?.removeAttribute("data-auto-submit-pending");
284
- this.#boundForm?.removeAttribute("aria-busy");
285
- if (inProgress) this.dispatch("reconcile", { detail: {} });
286
- }
287
- /** Whether `type` is one of the whitespace-separated event types in `on`. */
288
465
  #triggers(type) {
289
466
  return this.onValue.split(/\s+/).filter(Boolean).includes(type);
290
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
+ }
291
477
  };
292
478
 
293
479
  export { AutoSubmitController };
294
- //# sourceMappingURL=auto_submit_controller.js.map
295
480
  //# sourceMappingURL=auto_submit_controller.js.map