stimeo-ui 0.16.0 → 0.18.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 (337) hide show
  1. package/CHANGELOG.md +136 -0
  2. package/README.md +27 -11
  3. package/dist/cable/index.d.ts +88 -31
  4. package/dist/cable/index.js +384 -449
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/coerce-JtZVNG5h.d.ts +20 -0
  7. package/dist/controllers/accordion_controller.d.ts +4 -2
  8. package/dist/controllers/accordion_controller.js +174 -55
  9. package/dist/controllers/accordion_controller.js.map +1 -1
  10. package/dist/controllers/alert_dialog_controller.d.ts +12 -2
  11. package/dist/controllers/alert_dialog_controller.js +903 -235
  12. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  13. package/dist/controllers/announcer_controller.d.ts +37 -5
  14. package/dist/controllers/announcer_controller.js +238 -205
  15. package/dist/controllers/announcer_controller.js.map +1 -1
  16. package/dist/controllers/aspect_ratio_controller.js +0 -10
  17. package/dist/controllers/aspect_ratio_controller.js.map +1 -1
  18. package/dist/controllers/auto_submit_controller.d.ts +30 -6
  19. package/dist/controllers/auto_submit_controller.js +414 -145
  20. package/dist/controllers/auto_submit_controller.js.map +1 -1
  21. package/dist/controllers/avatar_controller.js +185 -107
  22. package/dist/controllers/avatar_controller.js.map +1 -1
  23. package/dist/controllers/breadcrumb_controller.js +0 -130
  24. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  25. package/dist/controllers/bulk_select_controller.d.ts +21 -3
  26. package/dist/controllers/bulk_select_controller.js +282 -58
  27. package/dist/controllers/bulk_select_controller.js.map +1 -1
  28. package/dist/controllers/calendar_controller.d.ts +38 -16
  29. package/dist/controllers/calendar_controller.js +228 -260
  30. package/dist/controllers/calendar_controller.js.map +1 -1
  31. package/dist/controllers/carousel_controller.d.ts +43 -12
  32. package/dist/controllers/carousel_controller.js +536 -436
  33. package/dist/controllers/carousel_controller.js.map +1 -1
  34. package/dist/controllers/character_counter_controller.d.ts +44 -7
  35. package/dist/controllers/character_counter_controller.js +493 -207
  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 +38 -74
  39. package/dist/controllers/checkbox_controller.js.map +1 -1
  40. package/dist/controllers/clipboard_controller.d.ts +16 -5
  41. package/dist/controllers/clipboard_controller.js +261 -149
  42. package/dist/controllers/clipboard_controller.js.map +1 -1
  43. package/dist/controllers/collapsible_controller.d.ts +17 -5
  44. package/dist/controllers/collapsible_controller.js +304 -120
  45. package/dist/controllers/collapsible_controller.js.map +1 -1
  46. package/dist/controllers/color_picker_controller.d.ts +18 -6
  47. package/dist/controllers/color_picker_controller.js +178 -146
  48. package/dist/controllers/color_picker_controller.js.map +1 -1
  49. package/dist/controllers/combobox_controller.d.ts +24 -6
  50. package/dist/controllers/combobox_controller.js +522 -156
  51. package/dist/controllers/combobox_controller.js.map +1 -1
  52. package/dist/controllers/command_palette_controller.d.ts +51 -20
  53. package/dist/controllers/command_palette_controller.js +1156 -395
  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 +300 -171
  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 +980 -262
  60. package/dist/controllers/confirm_controller.js.map +1 -1
  61. package/dist/controllers/context_menu_controller.d.ts +80 -18
  62. package/dist/controllers/context_menu_controller.js +346 -153
  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 +47 -3
  68. package/dist/controllers/countdown_controller.js +281 -158
  69. package/dist/controllers/countdown_controller.js.map +1 -1
  70. package/dist/controllers/currency_input_controller.d.ts +93 -10
  71. package/dist/controllers/currency_input_controller.js +575 -225
  72. package/dist/controllers/currency_input_controller.js.map +1 -1
  73. package/dist/controllers/data_grid_controller.d.ts +25 -12
  74. package/dist/controllers/data_grid_controller.js +248 -214
  75. package/dist/controllers/data_grid_controller.js.map +1 -1
  76. package/dist/controllers/date_range_picker_controller.d.ts +42 -14
  77. package/dist/controllers/date_range_picker_controller.js +338 -235
  78. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  79. package/dist/controllers/dialog_controller.d.ts +17 -6
  80. package/dist/controllers/dialog_controller.js +899 -237
  81. package/dist/controllers/dialog_controller.js.map +1 -1
  82. package/dist/controllers/direct_upload_controller.d.ts +25 -8
  83. package/dist/controllers/direct_upload_controller.js +97 -167
  84. package/dist/controllers/direct_upload_controller.js.map +1 -1
  85. package/dist/controllers/dirty_form_controller.d.ts +6 -1
  86. package/dist/controllers/dirty_form_controller.js +72 -69
  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 +196 -24
  90. package/dist/controllers/dismissible_controller.js.map +1 -1
  91. package/dist/controllers/drawer_controller.d.ts +39 -11
  92. package/dist/controllers/drawer_controller.js +974 -355
  93. package/dist/controllers/drawer_controller.js.map +1 -1
  94. package/dist/controllers/dropdown_controller.d.ts +31 -1
  95. package/dist/controllers/dropdown_controller.js +339 -96
  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 +315 -88
  99. package/dist/controllers/editable_controller.js.map +1 -1
  100. package/dist/controllers/empty_state_controller.js +79 -58
  101. package/dist/controllers/empty_state_controller.js.map +1 -1
  102. package/dist/controllers/file_dropzone_controller.d.ts +63 -18
  103. package/dist/controllers/file_dropzone_controller.js +322 -211
  104. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  105. package/dist/controllers/filter_controller.js +77 -42
  106. package/dist/controllers/filter_controller.js.map +1 -1
  107. package/dist/controllers/flash_controller.d.ts +35 -12
  108. package/dist/controllers/flash_controller.js +238 -347
  109. package/dist/controllers/flash_controller.js.map +1 -1
  110. package/dist/controllers/focus_controller.d.ts +15 -6
  111. package/dist/controllers/focus_controller.js +679 -240
  112. package/dist/controllers/focus_controller.js.map +1 -1
  113. package/dist/controllers/form_field_controller.js +156 -132
  114. package/dist/controllers/form_field_controller.js.map +1 -1
  115. package/dist/controllers/form_validation_controller.d.ts +3 -3
  116. package/dist/controllers/form_validation_controller.js +31 -97
  117. package/dist/controllers/form_validation_controller.js.map +1 -1
  118. package/dist/controllers/frame_loading_controller.d.ts +47 -14
  119. package/dist/controllers/frame_loading_controller.js +275 -217
  120. package/dist/controllers/frame_loading_controller.js.map +1 -1
  121. package/dist/controllers/highlight_controller.d.ts +27 -6
  122. package/dist/controllers/highlight_controller.js +107 -75
  123. package/dist/controllers/highlight_controller.js.map +1 -1
  124. package/dist/controllers/hover_card_controller.d.ts +60 -4
  125. package/dist/controllers/hover_card_controller.js +327 -130
  126. package/dist/controllers/hover_card_controller.js.map +1 -1
  127. package/dist/controllers/idle_controller.d.ts +48 -6
  128. package/dist/controllers/idle_controller.js +271 -101
  129. package/dist/controllers/idle_controller.js.map +1 -1
  130. package/dist/controllers/input_mask_controller.d.ts +30 -13
  131. package/dist/controllers/input_mask_controller.js +483 -97
  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 +150 -106
  135. package/dist/controllers/intersection_controller.js.map +1 -1
  136. package/dist/controllers/lazy_frame_controller.d.ts +19 -2
  137. package/dist/controllers/lazy_frame_controller.js +24 -68
  138. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  139. package/dist/controllers/listbox_controller.d.ts +44 -9
  140. package/dist/controllers/listbox_controller.js +523 -240
  141. package/dist/controllers/listbox_controller.js.map +1 -1
  142. package/dist/controllers/local_time_controller.d.ts +9 -7
  143. package/dist/controllers/local_time_controller.js +102 -77
  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 +80 -96
  147. package/dist/controllers/masonry_controller.js.map +1 -1
  148. package/dist/controllers/menu_controller.d.ts +55 -11
  149. package/dist/controllers/menu_controller.js +302 -188
  150. package/dist/controllers/menu_controller.js.map +1 -1
  151. package/dist/controllers/menubar_controller.d.ts +51 -9
  152. package/dist/controllers/menubar_controller.js +232 -345
  153. package/dist/controllers/menubar_controller.js.map +1 -1
  154. package/dist/controllers/meter_controller.d.ts +33 -20
  155. package/dist/controllers/meter_controller.js +417 -87
  156. package/dist/controllers/meter_controller.js.map +1 -1
  157. package/dist/controllers/multi_select_controller.d.ts +48 -18
  158. package/dist/controllers/multi_select_controller.js +785 -393
  159. package/dist/controllers/multi_select_controller.js.map +1 -1
  160. package/dist/controllers/navigation_menu_controller.d.ts +27 -6
  161. package/dist/controllers/navigation_menu_controller.js +190 -250
  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 +396 -192
  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 +268 -62
  168. package/dist/controllers/network_status_controller.js.map +1 -1
  169. package/dist/controllers/number_input_controller.d.ts +50 -8
  170. package/dist/controllers/number_input_controller.js +610 -303
  171. package/dist/controllers/number_input_controller.js.map +1 -1
  172. package/dist/controllers/optimistic_controller.d.ts +8 -5
  173. package/dist/controllers/optimistic_controller.js +45 -87
  174. package/dist/controllers/optimistic_controller.js.map +1 -1
  175. package/dist/controllers/otp_controller.d.ts +55 -8
  176. package/dist/controllers/otp_controller.js +658 -255
  177. package/dist/controllers/otp_controller.js.map +1 -1
  178. package/dist/controllers/overflow_indicator_controller.d.ts +5 -0
  179. package/dist/controllers/overflow_indicator_controller.js +122 -113
  180. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  181. package/dist/controllers/overflow_menu_controller.d.ts +58 -20
  182. package/dist/controllers/overflow_menu_controller.js +470 -295
  183. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  184. package/dist/controllers/pagination_controller.d.ts +37 -7
  185. package/dist/controllers/pagination_controller.js +332 -123
  186. package/dist/controllers/pagination_controller.js.map +1 -1
  187. package/dist/controllers/password_reveal_controller.d.ts +46 -8
  188. package/dist/controllers/password_reveal_controller.js +392 -121
  189. package/dist/controllers/password_reveal_controller.js.map +1 -1
  190. package/dist/controllers/password_strength_controller.d.ts +15 -6
  191. package/dist/controllers/password_strength_controller.js +111 -158
  192. package/dist/controllers/password_strength_controller.js.map +1 -1
  193. package/dist/controllers/persist_controller.d.ts +11 -4
  194. package/dist/controllers/persist_controller.js +165 -111
  195. package/dist/controllers/persist_controller.js.map +1 -1
  196. package/dist/controllers/pointer_drag_controller.d.ts +35 -12
  197. package/dist/controllers/pointer_drag_controller.js +434 -188
  198. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  199. package/dist/controllers/popover_controller.d.ts +41 -5
  200. package/dist/controllers/popover_controller.js +269 -113
  201. package/dist/controllers/popover_controller.js.map +1 -1
  202. package/dist/controllers/portal_controller.d.ts +44 -4
  203. package/dist/controllers/portal_controller.js +215 -76
  204. package/dist/controllers/portal_controller.js.map +1 -1
  205. package/dist/controllers/preview_guard_controller.d.ts +10 -4
  206. package/dist/controllers/preview_guard_controller.js +243 -116
  207. package/dist/controllers/preview_guard_controller.js.map +1 -1
  208. package/dist/controllers/progress_controller.d.ts +20 -19
  209. package/dist/controllers/progress_controller.js +391 -78
  210. package/dist/controllers/progress_controller.js.map +1 -1
  211. package/dist/controllers/radio_group_controller.d.ts +21 -9
  212. package/dist/controllers/radio_group_controller.js +278 -211
  213. package/dist/controllers/radio_group_controller.js.map +1 -1
  214. package/dist/controllers/range_slider_controller.d.ts +47 -6
  215. package/dist/controllers/range_slider_controller.js +220 -113
  216. package/dist/controllers/range_slider_controller.js.map +1 -1
  217. package/dist/controllers/rating_controller.d.ts +20 -4
  218. package/dist/controllers/rating_controller.js +458 -211
  219. package/dist/controllers/rating_controller.js.map +1 -1
  220. package/dist/controllers/read_more_controller.d.ts +2 -0
  221. package/dist/controllers/read_more_controller.js +138 -63
  222. package/dist/controllers/read_more_controller.js.map +1 -1
  223. package/dist/controllers/reading_progress_controller.d.ts +1 -1
  224. package/dist/controllers/reading_progress_controller.js +166 -137
  225. package/dist/controllers/reading_progress_controller.js.map +1 -1
  226. package/dist/controllers/relative_time_controller.d.ts +20 -6
  227. package/dist/controllers/relative_time_controller.js +211 -112
  228. package/dist/controllers/relative_time_controller.js.map +1 -1
  229. package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
  230. package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +103 -38
  231. package/dist/controllers/reset_on_restore_controller.js.map +1 -0
  232. package/dist/controllers/resizable_controller.d.ts +31 -2
  233. package/dist/controllers/resizable_controller.js +299 -150
  234. package/dist/controllers/resizable_controller.js.map +1 -1
  235. package/dist/controllers/roving_controller.d.ts +3 -3
  236. package/dist/controllers/roving_controller.js +49 -88
  237. package/dist/controllers/roving_controller.js.map +1 -1
  238. package/dist/controllers/scroll_area_controller.d.ts +7 -3
  239. package/dist/controllers/scroll_area_controller.js +490 -246
  240. package/dist/controllers/scroll_area_controller.js.map +1 -1
  241. package/dist/controllers/scroll_restore_controller.d.ts +3 -3
  242. package/dist/controllers/scroll_restore_controller.js +14 -55
  243. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  244. package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
  245. package/dist/controllers/scroll_visibility_controller.js +432 -149
  246. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  247. package/dist/controllers/scrollspy_controller.d.ts +6 -1
  248. package/dist/controllers/scrollspy_controller.js +193 -248
  249. package/dist/controllers/scrollspy_controller.js.map +1 -1
  250. package/dist/controllers/separator_controller.d.ts +20 -5
  251. package/dist/controllers/separator_controller.js +285 -142
  252. package/dist/controllers/separator_controller.js.map +1 -1
  253. package/dist/controllers/sidebar_controller.d.ts +65 -8
  254. package/dist/controllers/sidebar_controller.js +1069 -404
  255. package/dist/controllers/sidebar_controller.js.map +1 -1
  256. package/dist/controllers/skeleton_controller.d.ts +23 -0
  257. package/dist/controllers/skeleton_controller.js +259 -101
  258. package/dist/controllers/skeleton_controller.js.map +1 -1
  259. package/dist/controllers/slider_controller.d.ts +29 -2
  260. package/dist/controllers/slider_controller.js +187 -86
  261. package/dist/controllers/slider_controller.js.map +1 -1
  262. package/dist/controllers/smart_sticky_header_controller.d.ts +22 -4
  263. package/dist/controllers/smart_sticky_header_controller.js +173 -66
  264. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  265. package/dist/controllers/sortable_controller.d.ts +4 -4
  266. package/dist/controllers/sortable_controller.js +26 -125
  267. package/dist/controllers/sortable_controller.js.map +1 -1
  268. package/dist/controllers/spinner_controller.d.ts +39 -4
  269. package/dist/controllers/spinner_controller.js +288 -173
  270. package/dist/controllers/spinner_controller.js.map +1 -1
  271. package/dist/controllers/step_indicator_controller.d.ts +9 -4
  272. package/dist/controllers/step_indicator_controller.js +105 -46
  273. package/dist/controllers/step_indicator_controller.js.map +1 -1
  274. package/dist/controllers/stepper_controller.d.ts +14 -6
  275. package/dist/controllers/stepper_controller.js +120 -73
  276. package/dist/controllers/stepper_controller.js.map +1 -1
  277. package/dist/controllers/stick_to_bottom_controller.d.ts +9 -1
  278. package/dist/controllers/stick_to_bottom_controller.js +275 -140
  279. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  280. package/dist/controllers/sticky_observer_controller.d.ts +11 -0
  281. package/dist/controllers/sticky_observer_controller.js +220 -49
  282. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  283. package/dist/controllers/submit_once_controller.d.ts +24 -8
  284. package/dist/controllers/submit_once_controller.js +376 -227
  285. package/dist/controllers/submit_once_controller.js.map +1 -1
  286. package/dist/controllers/switch_controller.d.ts +18 -4
  287. package/dist/controllers/switch_controller.js +201 -84
  288. package/dist/controllers/switch_controller.js.map +1 -1
  289. package/dist/controllers/tabs_controller.d.ts +9 -6
  290. package/dist/controllers/tabs_controller.js +41 -30
  291. package/dist/controllers/tabs_controller.js.map +1 -1
  292. package/dist/controllers/tags_input_controller.d.ts +16 -3
  293. package/dist/controllers/tags_input_controller.js +293 -173
  294. package/dist/controllers/tags_input_controller.js.map +1 -1
  295. package/dist/controllers/textarea_autosize_controller.d.ts +11 -1
  296. package/dist/controllers/textarea_autosize_controller.js +108 -74
  297. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  298. package/dist/controllers/theme_controller.d.ts +24 -11
  299. package/dist/controllers/theme_controller.js +140 -116
  300. package/dist/controllers/theme_controller.js.map +1 -1
  301. package/dist/controllers/time_picker_controller.d.ts +55 -5
  302. package/dist/controllers/time_picker_controller.js +331 -127
  303. package/dist/controllers/time_picker_controller.js.map +1 -1
  304. package/dist/controllers/toast_controller.d.ts +40 -16
  305. package/dist/controllers/toast_controller.js +244 -324
  306. package/dist/controllers/toast_controller.js.map +1 -1
  307. package/dist/controllers/toggle_group_controller.d.ts +14 -6
  308. package/dist/controllers/toggle_group_controller.js +252 -191
  309. package/dist/controllers/toggle_group_controller.js.map +1 -1
  310. package/dist/controllers/toolbar_controller.d.ts +8 -6
  311. package/dist/controllers/toolbar_controller.js +219 -120
  312. package/dist/controllers/toolbar_controller.js.map +1 -1
  313. package/dist/controllers/tooltip_controller.d.ts +49 -4
  314. package/dist/controllers/tooltip_controller.js +158 -124
  315. package/dist/controllers/tooltip_controller.js.map +1 -1
  316. package/dist/controllers/transition_controller.d.ts +22 -4
  317. package/dist/controllers/transition_controller.js +123 -119
  318. package/dist/controllers/transition_controller.js.map +1 -1
  319. package/dist/controllers/tree_view_controller.d.ts +22 -12
  320. package/dist/controllers/tree_view_controller.js +283 -369
  321. package/dist/controllers/tree_view_controller.js.map +1 -1
  322. package/dist/index.d.ts +10 -5
  323. package/dist/index.js +8573 -10410
  324. package/dist/index.js.map +1 -1
  325. package/dist/inspector/cli.d.ts +38 -14
  326. package/dist/inspector/cli.js +108 -40
  327. package/dist/inspector/cli.js.map +1 -1
  328. package/dist/inspector/cli_bin.js +145 -64
  329. package/dist/inspector/cli_bin.js.map +1 -1
  330. package/dist/inspector/examples.json +20 -20
  331. package/dist/inspector/manifest.json +802 -101
  332. package/dist/positioning/index.d.ts +15 -7
  333. package/dist/positioning/index.js +154 -47
  334. package/dist/positioning/index.js.map +1 -1
  335. package/package.json +11 -10
  336. package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
  337. package/dist/controllers/reset_before_cache_controller.js.map +0 -1
@@ -1,8 +1,12 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
3
- // src/controllers/progress_controller.ts
3
+ function fillTemplate(template, values) {
4
+ return template.replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (match, name) => {
5
+ const replacement = Object.hasOwn(values, name) ? values[name] : void 0;
6
+ return replacement === void 0 ? match : String(replacement);
7
+ });
8
+ }
4
9
 
5
- // src/utils/announce.ts
6
10
  function announce(message, options = {}) {
7
11
  const text = message.trim();
8
12
  if (text.length === 0) return;
@@ -12,41 +16,66 @@ function announce(message, options = {}) {
12
16
  })
13
17
  );
14
18
  }
15
- function fillTemplate(template, values) {
16
- return template.replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (match, name) => {
17
- const replacement = values[name];
18
- return replacement === void 0 ? match : String(replacement);
19
- });
19
+
20
+ var NUMBER_BOUNDS = {
21
+ finite: { finite: true }};
22
+ function matchesNumberBounds(value, bounds) {
23
+ if (!Number.isFinite(value)) {
24
+ const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
25
+ if (direction === null) return false;
26
+ if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
27
+ }
28
+ if (bounds.min !== void 0 && value < bounds.min) return false;
29
+ if (bounds.max !== void 0 && value > bounds.max) return false;
30
+ if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
31
+ if (bounds.integer && !Number.isInteger(value)) return false;
32
+ if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
33
+ return true;
20
34
  }
21
35
 
22
- // src/utils/coerce.ts
36
+ function eventNumber(event) {
37
+ return toFiniteNumber(event.params?.amount ?? event.detail?.value);
38
+ }
23
39
  function toFiniteNumber(raw) {
24
- if (raw === null || raw === void 0 || raw === "") return null;
25
- const value = typeof raw === "number" ? raw : Number(raw);
40
+ if (typeof raw !== "number" && typeof raw !== "string") return null;
41
+ if (typeof raw === "string" && raw.trim().length === 0) return null;
42
+ const value = Number(raw);
26
43
  return Number.isFinite(value) ? value : null;
27
44
  }
45
+ function readNumber(raw, fallback, bounds) {
46
+ return matchesNumberBounds(raw, bounds) ? raw : fallback;
47
+ }
48
+
49
+ var ListenerSet = class {
50
+ #abort = new AbortController();
51
+ add(target, type, handler, options) {
52
+ target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
53
+ }
54
+ dispose() {
55
+ this.#abort.abort();
56
+ this.#abort = new AbortController();
57
+ }
58
+ };
28
59
 
29
- // src/utils/microtask_coalescer.ts
30
60
  var MicrotaskCoalescer = class {
31
61
  #run;
32
62
  #queued = false;
33
63
  #active = false;
34
64
  #generation = 0;
35
- /** @param run - the single reconciliation pass, invoked at most once per batch. */
36
65
  constructor(run) {
37
66
  this.#run = run;
38
67
  }
39
- /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
40
68
  activate() {
41
69
  this.#active = true;
42
70
  }
43
- /** Closes the window and drops any pending pass; call from `disconnect()`. */
44
71
  cancel() {
45
72
  this.#active = false;
46
73
  this.#queued = false;
47
74
  this.#generation += 1;
48
75
  }
49
- /** Requests one pass after the batch settles. Idempotent; inert outside the window. */
76
+ get pending() {
77
+ return this.#queued;
78
+ }
50
79
  schedule() {
51
80
  if (!this.#active || this.#queued) return;
52
81
  this.#queued = true;
@@ -59,11 +88,62 @@ var MicrotaskCoalescer = class {
59
88
  }
60
89
  };
61
90
 
62
- // src/utils/range.ts
91
+ var MorphRenderWatcher = class {
92
+ #listeners = new ListenerSet();
93
+ #pass;
94
+ #element = null;
95
+ #onMorph = () => this.#pass.schedule();
96
+ constructor(run) {
97
+ this.#pass = new MicrotaskCoalescer(run);
98
+ }
99
+ observe(element) {
100
+ if (this.#element === element) return;
101
+ this.disconnect();
102
+ this.#element = element;
103
+ this.#pass.activate();
104
+ this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
105
+ }
106
+ schedule() {
107
+ this.#pass.schedule();
108
+ }
109
+ get pending() {
110
+ return this.#pass.pending;
111
+ }
112
+ disconnect() {
113
+ this.#listeners.dispose();
114
+ this.#pass.cancel();
115
+ this.#element = null;
116
+ }
117
+ };
118
+
119
+ var NumberValueReader = class {
120
+ #lastRejected = /* @__PURE__ */ new Map();
121
+ read(owner, name, raw, fallback, bounds) {
122
+ const resolved = readNumber(raw, fallback, bounds);
123
+ if (matchesNumberBounds(raw, bounds)) {
124
+ this.#lastRejected.delete(name);
125
+ return resolved;
126
+ }
127
+ const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
128
+ const literal = owner.element.getAttribute(attribute);
129
+ if (literal === null) {
130
+ this.#lastRejected.delete(name);
131
+ return resolved;
132
+ }
133
+ if (this.#lastRejected.get(name) !== literal) {
134
+ this.#lastRejected.set(name, literal);
135
+ console.warn(
136
+ `Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
137
+ );
138
+ }
139
+ return resolved;
140
+ }
141
+ };
142
+
63
143
  function rangeFraction(value, min, max) {
64
144
  const span = max - min;
65
145
  if (!(span > 0)) return 0;
66
- const clamped = Math.min(max, Math.max(min, value));
146
+ const clamped = clampRange(value, min, max);
67
147
  let fraction;
68
148
  if (Number.isFinite(span)) {
69
149
  fraction = (clamped - min) / span;
@@ -74,14 +154,254 @@ function rangeFraction(value, min, max) {
74
154
  if (!Number.isFinite(fraction)) return 0;
75
155
  return Math.min(1, Math.max(0, fraction));
76
156
  }
157
+ function clampRange(value, min, max) {
158
+ return Math.min(max, Math.max(min, value));
159
+ }
160
+
161
+ function setAttributeIfChanged(element, name, value, beforeWrite) {
162
+ if (element.getAttribute(name) === value) return false;
163
+ if (value === null) element.removeAttribute(name);
164
+ else element.setAttribute(name, value);
165
+ return true;
166
+ }
167
+
168
+ function sharedRegistry(key, create) {
169
+ const symbol = Symbol.for(key);
170
+ const scope = globalThis;
171
+ const existing = scope[symbol];
172
+ if (existing !== void 0) return existing;
173
+ const registry2 = create();
174
+ Object.defineProperty(globalThis, symbol, { value: registry2 });
175
+ return registry2;
176
+ }
77
177
 
78
- // src/controllers/progress_controller.ts
79
- var OWNED_VALUE_TEXT = "owns-valuetext";
80
- var ProgressController = class extends Controller {
81
- /** The marker above, in the namespace this controller is registered under. */
82
- get #ownedValueText() {
83
- return `data-${this.identifier}-${OWNED_VALUE_TEXT}`;
178
+ var registry = sharedRegistry(
179
+ "stimeo-ui.attribute-lease.registry.v1",
180
+ () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
181
+ );
182
+ function isAttributeValue(value) {
183
+ return value === null || typeof value === "string";
184
+ }
185
+ function readLeaseRecord(element, record) {
186
+ try {
187
+ const parsed = JSON.parse(element.getAttribute(record) ?? "null");
188
+ if (!Array.isArray(parsed)) return void 0;
189
+ const [original, written, ...rest] = parsed;
190
+ const linked = rest[0] !== false;
191
+ const beneath = linked ? rest : rest.slice(1);
192
+ if (!beneath.every((under) => typeof under === "string")) return void 0;
193
+ return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
194
+ } catch {
195
+ return void 0;
84
196
  }
197
+ }
198
+ function attributeStack(element, attribute) {
199
+ const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
200
+ registry.stacks.set(element, byAttribute);
201
+ const known = byAttribute.get(attribute);
202
+ if (known) return known;
203
+ const found = [];
204
+ for (const record of registry.names.get(attribute) ?? []) {
205
+ const read = readLeaseRecord(element, record);
206
+ if (read) found.push({ ...read, record });
207
+ }
208
+ const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
209
+ const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
210
+ lease: null,
211
+ record,
212
+ written,
213
+ original,
214
+ linked: linked && index > 0
215
+ }));
216
+ byAttribute.set(attribute, stack);
217
+ return stack;
218
+ }
219
+ function findHold(stack, lease, record) {
220
+ return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
221
+ }
222
+ function readAttributeLease(element, attribute, owner, lease, expected) {
223
+ const stack = attributeStack(element, attribute);
224
+ const hold = findHold(stack, lease, `data-${owner}-${attribute}-lease`);
225
+ const current = element.getAttribute(attribute);
226
+ const covering = [...stack].reverse().find((other) => other.written === current);
227
+ const original = (hold ?? covering)?.original;
228
+ const authored = original === void 0 ? current : original;
229
+ return {
230
+ original: authored,
231
+ allowed: hold ? current === hold.written || stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current) : authored === expected
232
+ };
233
+ }
234
+ var AttributeLease = class {
235
+ #attribute;
236
+ #record;
237
+ #base;
238
+ #preserveAuthor;
239
+ #held = /* @__PURE__ */ new Set();
240
+ constructor(attribute, owner, options = {}) {
241
+ this.#attribute = attribute;
242
+ this.#record = `data-${owner}-${attribute}-lease`;
243
+ this.#base = options.base === true;
244
+ this.#preserveAuthor = options.preserveAuthor === true;
245
+ const names = registry.names;
246
+ names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
247
+ }
248
+ write(element, value) {
249
+ const stack = attributeStack(element, this.#attribute);
250
+ const hold = this.#take(stack) ?? this.#acquire(element, stack);
251
+ this.#held.add(element);
252
+ const shows = !this.#covered(element, stack, hold);
253
+ hold.written = value;
254
+ this.#mark(element, stack);
255
+ if (shows) this.#reflect(element, value);
256
+ }
257
+ return(element) {
258
+ const held = this.#held.delete(element);
259
+ const known = registry.stacks.get(element)?.has(this.#attribute);
260
+ const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
261
+ const hold = this.#take(stack);
262
+ if (!hold) return false;
263
+ const carries = element.getAttribute(this.#attribute) === hold.written;
264
+ const owns = carries && !this.#covered(element, stack, hold);
265
+ const index = stack.indexOf(hold);
266
+ stack.splice(index, 1);
267
+ const above = stack[index];
268
+ if (above) above.linked &&= hold.linked;
269
+ this.#mark(element, stack);
270
+ if (!owns) return true;
271
+ const below = hold.linked ? stack[index - 1] : void 0;
272
+ this.#reflect(element, below ? below.written : hold.original);
273
+ return true;
274
+ }
275
+ returnAll() {
276
+ for (const element of Array.from(this.#held)) this.return(element);
277
+ }
278
+ #take(stack) {
279
+ const hold = findHold(stack, this, this.#record);
280
+ if (hold) hold.lease = this;
281
+ return hold;
282
+ }
283
+ #acquire(element, stack) {
284
+ const current = element.getAttribute(this.#attribute);
285
+ const top = stack.at(-1);
286
+ const bottom = stack[0];
287
+ const over = top?.written === current ? top : void 0;
288
+ const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
289
+ const hold = {
290
+ lease: this,
291
+ record: this.#record,
292
+ written: current,
293
+ original: from ? from.original : current,
294
+ linked: !this.#base && over !== void 0
295
+ };
296
+ if (this.#base && bottom) {
297
+ bottom.linked = true;
298
+ stack.unshift(hold);
299
+ } else stack.push(hold);
300
+ return hold;
301
+ }
302
+ #covered(element, stack, hold) {
303
+ const current = element.getAttribute(this.#attribute);
304
+ return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
305
+ }
306
+ #mark(element, stack) {
307
+ const records = /* @__PURE__ */ new Map([[this.#record, null]]);
308
+ stack.forEach((hold, index) => {
309
+ const names = stack.slice(0, index).map((under) => under.record);
310
+ const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
311
+ const marker = hold.linked || beneath.length === 0 ? [] : [false];
312
+ records.set(
313
+ hold.record,
314
+ hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
315
+ );
316
+ });
317
+ for (const [name, recorded] of records) {
318
+ setAttributeIfChanged(element, name, recorded);
319
+ }
320
+ }
321
+ #reflect(element, value) {
322
+ setAttributeIfChanged(element, this.#attribute, value);
323
+ }
324
+ };
325
+
326
+ var TemplateAttributeLease = class {
327
+ #lease;
328
+ #record;
329
+ #attribute;
330
+ #owner;
331
+ #states = /* @__PURE__ */ new WeakMap();
332
+ constructor(attribute, owner) {
333
+ this.#attribute = attribute;
334
+ this.#owner = owner;
335
+ this.#lease = new AttributeLease(attribute, owner, { base: true, preserveAuthor: true });
336
+ this.#record = `data-${owner}-${attribute}-template`;
337
+ }
338
+ render(element, source, value) {
339
+ let state = this.#read(element);
340
+ if (!state && source.length === 0) {
341
+ this.#lease.return(element);
342
+ return;
343
+ }
344
+ if (!state || state.source !== source) {
345
+ this.#lease.return(element);
346
+ state = { source, expected: this.#view(element, null).original, yielded: false };
347
+ }
348
+ if (source.length === 0 || value === null) {
349
+ this.#states.set(element, state);
350
+ this.release(element);
351
+ return;
352
+ }
353
+ if (!state.yielded && this.#continues(element, state)) {
354
+ this.#lease.write(element, value);
355
+ state.expected = value;
356
+ } else {
357
+ state.yielded = true;
358
+ this.#lease.return(element);
359
+ }
360
+ this.#mark(element, state);
361
+ }
362
+ release(element) {
363
+ const state = this.#read(element);
364
+ if (state && !state.yielded) {
365
+ state.yielded = !this.#continues(element, state);
366
+ if (!state.yielded) state.expected = this.#view(element, null).original;
367
+ }
368
+ this.#lease.return(element);
369
+ if (state) this.#mark(element, state);
370
+ }
371
+ #continues(element, state) {
372
+ const view = this.#view(element, state.expected);
373
+ return view.allowed || !element.hasAttribute(this.#record) && element.getAttribute(this.#attribute) === view.original;
374
+ }
375
+ #view(element, expected) {
376
+ return readAttributeLease(element, this.#attribute, this.#owner, this.#lease, expected);
377
+ }
378
+ #read(element) {
379
+ const live = this.#states.get(element);
380
+ if (live) return live;
381
+ try {
382
+ const parsed = JSON.parse(element.getAttribute(this.#record) ?? "null");
383
+ if (!Array.isArray(parsed) || parsed.length !== 3) return void 0;
384
+ const [source, expected, yielded] = parsed;
385
+ if (typeof source !== "string" || expected !== null && typeof expected !== "string" || typeof yielded !== "boolean")
386
+ return void 0;
387
+ return { source, expected, yielded };
388
+ } catch {
389
+ return void 0;
390
+ }
391
+ }
392
+ #mark(element, state) {
393
+ this.#states.set(element, state);
394
+ setAttributeIfChanged(
395
+ element,
396
+ this.#record,
397
+ JSON.stringify([state.source, state.expected, state.yielded])
398
+ );
399
+ }
400
+ };
401
+
402
+ var ProgressController = class _ProgressController extends Controller {
403
+ #numbers = new NumberValueReader();
404
+ #valueText = new TemplateAttributeLease("aria-valuetext", this.identifier);
85
405
  static targets = ["bar"];
86
406
  static values = {
87
407
  value: { type: Number, default: 0 },
@@ -91,118 +411,111 @@ var ProgressController = class extends Controller {
91
411
  valueText: { type: String, default: "" },
92
412
  announceText: { type: String, default: "" }
93
413
  };
414
+ static valueConstraints = {
415
+ value: NUMBER_BOUNDS.finite,
416
+ min: NUMBER_BOUNDS.finite,
417
+ max: NUMBER_BOUNDS.finite
418
+ };
94
419
  static actions = ["setValue"];
95
420
  static events = ["change", "complete"];
96
- /**
97
- * Collapses a morph that swaps several render inputs at once into one repaint.
98
- * A single update usually rewrites the whole set, and each Value would otherwise
99
- * repaint on its own.
100
- */
101
- #repaint = new MicrotaskCoalescer(() => {
421
+ #repaint = new MorphRenderWatcher(() => {
102
422
  this.#render();
103
423
  });
104
424
  connect() {
105
- this.#repaint.activate();
425
+ this.#repaint.observe(this.element);
106
426
  this.#render();
107
427
  }
108
- /** Closes the window in which a queued repaint may still run. */
109
428
  disconnect() {
110
- this.#repaint.cancel();
429
+ this.#repaint.disconnect();
430
+ this.#valueText.release(this.element);
111
431
  }
112
- /**
113
- * Updates the progress value from an action param (`amount`) or a
114
- * `detail.value` CustomEvent, normalizes it into range, syncs ARIA, and
115
- * dispatches `change` (always) plus `complete` when `max` is reached.
116
- */
117
432
  setValue(event) {
118
- const next = toFiniteNumber(event.params?.amount ?? event.detail?.value);
433
+ const next = eventNumber(event);
119
434
  if (next === null) return;
120
435
  const value = this.#clamp(next);
121
436
  this.valueValue = value;
122
437
  this.indeterminateValue = false;
123
438
  this.#render();
124
439
  this.dispatch("change", { detail: { value, ratio: this.#ratio } });
125
- if (value >= this.maxValue) {
440
+ if (value >= this.#safeMax) {
126
441
  this.dispatch("complete", { detail: { value } });
127
442
  announce(
128
443
  fillTemplate(this.announceTextValue, { value, percent: Math.round(this.#ratio * 100) })
129
444
  );
130
445
  }
131
446
  }
132
- /** Repaints when application code (or a Turbo morph) changes `indeterminate` at runtime. */
133
447
  indeterminateValueChanged() {
134
448
  this.#repaint.schedule();
135
449
  }
136
- /** Repaints when application code (or a Turbo morph) changes `value` at runtime. */
137
450
  valueValueChanged() {
138
451
  this.#repaint.schedule();
139
452
  }
140
- /** Repaints when application code (or a Turbo morph) changes `min` at runtime. */
141
453
  minValueChanged() {
142
454
  this.#repaint.schedule();
143
455
  }
144
- /** Repaints when application code (or a Turbo morph) changes `max` at runtime. */
145
456
  maxValueChanged() {
146
457
  this.#repaint.schedule();
147
458
  }
148
- /** Repaints when application code (or a Turbo morph) changes `valueText` at runtime. */
149
459
  valueTextValueChanged() {
150
460
  this.#repaint.schedule();
151
461
  }
152
- /** Clamps `raw` into the configured `[min, max]` range. */
153
462
  #clamp(raw) {
154
- return Math.min(this.maxValue, Math.max(this.minValue, raw));
463
+ return clampRange(raw, this.#safeMin, this.#safeMax);
155
464
  }
156
- /** Current fraction of the range in `[0, 1]`; `0` when the range is empty. */
157
465
  get #ratio() {
158
- return rangeFraction(this.valueValue, this.minValue, this.maxValue);
466
+ return rangeFraction(this.#safeValue, this.#safeMin, this.#safeMax);
159
467
  }
160
- /**
161
- * Reflects value/range/indeterminate onto ARIA, `data-state`, and the ratio.
162
- *
163
- * @stimeoRenderRoot
164
- */
165
468
  #render() {
166
- this.element.setAttribute("aria-valuemin", String(this.minValue));
167
- this.element.setAttribute("aria-valuemax", String(this.maxValue));
469
+ this.element.setAttribute("aria-valuemin", String(this.#safeMin));
470
+ this.element.setAttribute("aria-valuemax", String(this.#safeMax));
168
471
  if (this.indeterminateValue) {
169
472
  this.element.removeAttribute("aria-valuenow");
170
- this.#clearOwnValueText();
473
+ this.#valueText.render(this.element, this.valueTextValue, null);
171
474
  this.element.style.removeProperty("--stimeo--progress-ratio");
172
475
  this.element.setAttribute("data-state", "indeterminate");
173
476
  return;
174
477
  }
175
- const value = this.#clamp(this.valueValue);
478
+ const value = this.#clamp(this.#safeValue);
176
479
  this.element.setAttribute("aria-valuenow", String(value));
177
480
  this.element.style.setProperty("--stimeo--progress-ratio", String(this.#ratio));
178
481
  this.element.setAttribute("data-state", "determinate");
179
482
  this.#applyValueText(value);
180
483
  }
181
- /**
182
- * Sets `aria-valuetext` from the consumer-provided template, substituting
183
- * `{value}` and `{percent}`. Left to the consumer so the human-readable text
184
- * stays i18n-neutral in the library. With no template the attribute belongs to
185
- * the consumer, so only a text this controller wrote is taken back
186
- * ({@link OWNED_VALUE_TEXT}).
187
- */
188
484
  #applyValueText(value) {
189
- if (this.valueTextValue.length === 0) {
190
- this.#clearOwnValueText();
191
- return;
192
- }
193
- const percent = Math.round(this.#ratio * 100);
194
- const text = this.valueTextValue.replaceAll("{value}", String(value)).replaceAll("{percent}", String(percent));
195
- this.element.setAttribute("aria-valuetext", text);
196
- this.element.setAttribute(this.#ownedValueText, "");
485
+ this.#valueText.render(
486
+ this.element,
487
+ this.valueTextValue,
488
+ fillTemplate(this.valueTextValue, { value, percent: Math.round(this.#ratio * 100) })
489
+ );
490
+ }
491
+ get #safeValue() {
492
+ return this.#numbers.read(
493
+ this,
494
+ "value",
495
+ this.valueValue,
496
+ _ProgressController.values.value.default,
497
+ _ProgressController.valueConstraints.value
498
+ );
499
+ }
500
+ get #safeMin() {
501
+ return this.#numbers.read(
502
+ this,
503
+ "min",
504
+ this.minValue,
505
+ _ProgressController.values.min.default,
506
+ _ProgressController.valueConstraints.min
507
+ );
197
508
  }
198
- /** Removes `aria-valuetext` only when this controller is the one that wrote it. */
199
- #clearOwnValueText() {
200
- if (!this.element.hasAttribute(this.#ownedValueText)) return;
201
- this.element.removeAttribute("aria-valuetext");
202
- this.element.removeAttribute(this.#ownedValueText);
509
+ get #safeMax() {
510
+ return this.#numbers.read(
511
+ this,
512
+ "max",
513
+ this.maxValue,
514
+ _ProgressController.values.max.default,
515
+ _ProgressController.valueConstraints.max
516
+ );
203
517
  }
204
518
  };
205
519
 
206
520
  export { ProgressController };
207
- //# sourceMappingURL=progress_controller.js.map
208
521
  //# sourceMappingURL=progress_controller.js.map