stimeo-ui 0.17.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 (297) hide show
  1. package/CHANGELOG.md +106 -1
  2. package/README.md +19 -10
  3. package/dist/cable/index.d.ts +9 -8
  4. package/dist/cable/index.js +22 -14
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/coerce-JtZVNG5h.d.ts +20 -0
  7. package/dist/controllers/accordion_controller.js +14 -6
  8. package/dist/controllers/accordion_controller.js.map +1 -1
  9. package/dist/controllers/alert_dialog_controller.js +145 -118
  10. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  11. package/dist/controllers/announcer_controller.d.ts +5 -3
  12. package/dist/controllers/announcer_controller.js +113 -17
  13. package/dist/controllers/announcer_controller.js.map +1 -1
  14. package/dist/controllers/auto_submit_controller.js +185 -60
  15. package/dist/controllers/auto_submit_controller.js.map +1 -1
  16. package/dist/controllers/avatar_controller.js +55 -43
  17. package/dist/controllers/avatar_controller.js.map +1 -1
  18. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  19. package/dist/controllers/bulk_select_controller.d.ts +3 -3
  20. package/dist/controllers/bulk_select_controller.js +64 -50
  21. package/dist/controllers/bulk_select_controller.js.map +1 -1
  22. package/dist/controllers/calendar_controller.d.ts +15 -12
  23. package/dist/controllers/calendar_controller.js +55 -53
  24. package/dist/controllers/calendar_controller.js.map +1 -1
  25. package/dist/controllers/carousel_controller.d.ts +9 -5
  26. package/dist/controllers/carousel_controller.js +124 -86
  27. package/dist/controllers/carousel_controller.js.map +1 -1
  28. package/dist/controllers/character_counter_controller.d.ts +27 -6
  29. package/dist/controllers/character_counter_controller.js +291 -95
  30. package/dist/controllers/character_counter_controller.js.map +1 -1
  31. package/dist/controllers/checkbox_controller.js +6 -0
  32. package/dist/controllers/checkbox_controller.js.map +1 -1
  33. package/dist/controllers/clipboard_controller.js +118 -27
  34. package/dist/controllers/clipboard_controller.js.map +1 -1
  35. package/dist/controllers/collapsible_controller.d.ts +1 -1
  36. package/dist/controllers/collapsible_controller.js +52 -49
  37. package/dist/controllers/collapsible_controller.js.map +1 -1
  38. package/dist/controllers/color_picker_controller.js +29 -7
  39. package/dist/controllers/color_picker_controller.js.map +1 -1
  40. package/dist/controllers/combobox_controller.d.ts +1 -1
  41. package/dist/controllers/combobox_controller.js +210 -71
  42. package/dist/controllers/combobox_controller.js.map +1 -1
  43. package/dist/controllers/command_palette_controller.d.ts +9 -9
  44. package/dist/controllers/command_palette_controller.js +289 -140
  45. package/dist/controllers/command_palette_controller.js.map +1 -1
  46. package/dist/controllers/conditional_fields_controller.js +145 -58
  47. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  48. package/dist/controllers/confirm_controller.js +145 -118
  49. package/dist/controllers/confirm_controller.js.map +1 -1
  50. package/dist/controllers/context_menu_controller.d.ts +49 -14
  51. package/dist/controllers/context_menu_controller.js +138 -73
  52. package/dist/controllers/context_menu_controller.js.map +1 -1
  53. package/dist/controllers/count_up_controller.js.map +1 -1
  54. package/dist/controllers/countdown_controller.d.ts +2 -2
  55. package/dist/controllers/countdown_controller.js +109 -21
  56. package/dist/controllers/countdown_controller.js.map +1 -1
  57. package/dist/controllers/currency_input_controller.d.ts +75 -11
  58. package/dist/controllers/currency_input_controller.js +446 -72
  59. package/dist/controllers/currency_input_controller.js.map +1 -1
  60. package/dist/controllers/data_grid_controller.d.ts +10 -8
  61. package/dist/controllers/data_grid_controller.js +134 -28
  62. package/dist/controllers/data_grid_controller.js.map +1 -1
  63. package/dist/controllers/date_range_picker_controller.d.ts +12 -9
  64. package/dist/controllers/date_range_picker_controller.js +93 -72
  65. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  66. package/dist/controllers/dialog_controller.d.ts +4 -5
  67. package/dist/controllers/dialog_controller.js +145 -118
  68. package/dist/controllers/dialog_controller.js.map +1 -1
  69. package/dist/controllers/direct_upload_controller.d.ts +1 -1
  70. package/dist/controllers/direct_upload_controller.js +24 -14
  71. package/dist/controllers/direct_upload_controller.js.map +1 -1
  72. package/dist/controllers/dirty_form_controller.d.ts +6 -1
  73. package/dist/controllers/dirty_form_controller.js +68 -31
  74. package/dist/controllers/dirty_form_controller.js.map +1 -1
  75. package/dist/controllers/dismissible_controller.js +64 -46
  76. package/dist/controllers/dismissible_controller.js.map +1 -1
  77. package/dist/controllers/drawer_controller.js +145 -118
  78. package/dist/controllers/drawer_controller.js.map +1 -1
  79. package/dist/controllers/dropdown_controller.js +76 -63
  80. package/dist/controllers/dropdown_controller.js.map +1 -1
  81. package/dist/controllers/editable_controller.js +199 -62
  82. package/dist/controllers/editable_controller.js.map +1 -1
  83. package/dist/controllers/empty_state_controller.js +13 -6
  84. package/dist/controllers/empty_state_controller.js.map +1 -1
  85. package/dist/controllers/file_dropzone_controller.d.ts +3 -0
  86. package/dist/controllers/file_dropzone_controller.js +55 -48
  87. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  88. package/dist/controllers/filter_controller.js +9 -2
  89. package/dist/controllers/filter_controller.js.map +1 -1
  90. package/dist/controllers/flash_controller.d.ts +4 -4
  91. package/dist/controllers/flash_controller.js +66 -33
  92. package/dist/controllers/flash_controller.js.map +1 -1
  93. package/dist/controllers/focus_controller.d.ts +3 -3
  94. package/dist/controllers/focus_controller.js +39 -14
  95. package/dist/controllers/focus_controller.js.map +1 -1
  96. package/dist/controllers/form_field_controller.js +52 -43
  97. package/dist/controllers/form_field_controller.js.map +1 -1
  98. package/dist/controllers/form_validation_controller.d.ts +3 -3
  99. package/dist/controllers/form_validation_controller.js +18 -11
  100. package/dist/controllers/form_validation_controller.js.map +1 -1
  101. package/dist/controllers/frame_loading_controller.d.ts +13 -12
  102. package/dist/controllers/frame_loading_controller.js +55 -48
  103. package/dist/controllers/frame_loading_controller.js.map +1 -1
  104. package/dist/controllers/highlight_controller.d.ts +5 -4
  105. package/dist/controllers/highlight_controller.js.map +1 -1
  106. package/dist/controllers/hover_card_controller.d.ts +4 -1
  107. package/dist/controllers/hover_card_controller.js +67 -61
  108. package/dist/controllers/hover_card_controller.js.map +1 -1
  109. package/dist/controllers/idle_controller.d.ts +6 -5
  110. package/dist/controllers/idle_controller.js +10 -6
  111. package/dist/controllers/idle_controller.js.map +1 -1
  112. package/dist/controllers/input_mask_controller.d.ts +30 -13
  113. package/dist/controllers/input_mask_controller.js +411 -24
  114. package/dist/controllers/input_mask_controller.js.map +1 -1
  115. package/dist/controllers/intersection_controller.js +3 -0
  116. package/dist/controllers/intersection_controller.js.map +1 -1
  117. package/dist/controllers/lazy_frame_controller.d.ts +3 -2
  118. package/dist/controllers/lazy_frame_controller.js +15 -3
  119. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  120. package/dist/controllers/listbox_controller.d.ts +10 -7
  121. package/dist/controllers/listbox_controller.js +260 -79
  122. package/dist/controllers/listbox_controller.js.map +1 -1
  123. package/dist/controllers/local_time_controller.d.ts +8 -6
  124. package/dist/controllers/local_time_controller.js +48 -13
  125. package/dist/controllers/local_time_controller.js.map +1 -1
  126. package/dist/controllers/masonry_controller.js +11 -4
  127. package/dist/controllers/masonry_controller.js.map +1 -1
  128. package/dist/controllers/menu_controller.d.ts +24 -5
  129. package/dist/controllers/menu_controller.js +138 -82
  130. package/dist/controllers/menu_controller.js.map +1 -1
  131. package/dist/controllers/menubar_controller.d.ts +49 -7
  132. package/dist/controllers/menubar_controller.js +65 -19
  133. package/dist/controllers/menubar_controller.js.map +1 -1
  134. package/dist/controllers/meter_controller.d.ts +13 -20
  135. package/dist/controllers/meter_controller.js +270 -24
  136. package/dist/controllers/meter_controller.js.map +1 -1
  137. package/dist/controllers/multi_select_controller.d.ts +17 -15
  138. package/dist/controllers/multi_select_controller.js +251 -94
  139. package/dist/controllers/multi_select_controller.js.map +1 -1
  140. package/dist/controllers/navigation_menu_controller.d.ts +19 -5
  141. package/dist/controllers/navigation_menu_controller.js +67 -19
  142. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  143. package/dist/controllers/nested_form_controller.js +98 -64
  144. package/dist/controllers/nested_form_controller.js.map +1 -1
  145. package/dist/controllers/network_status_controller.js +70 -52
  146. package/dist/controllers/network_status_controller.js.map +1 -1
  147. package/dist/controllers/number_input_controller.d.ts +24 -6
  148. package/dist/controllers/number_input_controller.js +344 -94
  149. package/dist/controllers/number_input_controller.js.map +1 -1
  150. package/dist/controllers/optimistic_controller.d.ts +8 -5
  151. package/dist/controllers/optimistic_controller.js +29 -11
  152. package/dist/controllers/optimistic_controller.js.map +1 -1
  153. package/dist/controllers/otp_controller.d.ts +35 -4
  154. package/dist/controllers/otp_controller.js +502 -104
  155. package/dist/controllers/otp_controller.js.map +1 -1
  156. package/dist/controllers/overflow_indicator_controller.js +6 -0
  157. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  158. package/dist/controllers/overflow_menu_controller.d.ts +10 -9
  159. package/dist/controllers/overflow_menu_controller.js +136 -21
  160. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  161. package/dist/controllers/pagination_controller.d.ts +3 -2
  162. package/dist/controllers/pagination_controller.js +47 -14
  163. package/dist/controllers/pagination_controller.js.map +1 -1
  164. package/dist/controllers/password_reveal_controller.d.ts +5 -4
  165. package/dist/controllers/password_reveal_controller.js +52 -49
  166. package/dist/controllers/password_reveal_controller.js.map +1 -1
  167. package/dist/controllers/password_strength_controller.d.ts +1 -1
  168. package/dist/controllers/password_strength_controller.js +13 -6
  169. package/dist/controllers/password_strength_controller.js.map +1 -1
  170. package/dist/controllers/persist_controller.js +48 -128
  171. package/dist/controllers/persist_controller.js.map +1 -1
  172. package/dist/controllers/pointer_drag_controller.d.ts +19 -8
  173. package/dist/controllers/pointer_drag_controller.js +249 -23
  174. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  175. package/dist/controllers/popover_controller.d.ts +3 -3
  176. package/dist/controllers/popover_controller.js +82 -65
  177. package/dist/controllers/popover_controller.js.map +1 -1
  178. package/dist/controllers/portal_controller.js +6 -0
  179. package/dist/controllers/portal_controller.js.map +1 -1
  180. package/dist/controllers/preview_guard_controller.js +14 -3
  181. package/dist/controllers/preview_guard_controller.js.map +1 -1
  182. package/dist/controllers/progress_controller.d.ts +9 -19
  183. package/dist/controllers/progress_controller.js +271 -27
  184. package/dist/controllers/progress_controller.js.map +1 -1
  185. package/dist/controllers/radio_group_controller.d.ts +11 -8
  186. package/dist/controllers/radio_group_controller.js +167 -80
  187. package/dist/controllers/radio_group_controller.js.map +1 -1
  188. package/dist/controllers/range_slider_controller.d.ts +4 -3
  189. package/dist/controllers/range_slider_controller.js +27 -7
  190. package/dist/controllers/range_slider_controller.js.map +1 -1
  191. package/dist/controllers/rating_controller.js +93 -57
  192. package/dist/controllers/rating_controller.js.map +1 -1
  193. package/dist/controllers/read_more_controller.js +10 -6
  194. package/dist/controllers/read_more_controller.js.map +1 -1
  195. package/dist/controllers/reading_progress_controller.js +22 -5
  196. package/dist/controllers/reading_progress_controller.js.map +1 -1
  197. package/dist/controllers/relative_time_controller.d.ts +4 -4
  198. package/dist/controllers/relative_time_controller.js +75 -11
  199. package/dist/controllers/relative_time_controller.js.map +1 -1
  200. package/dist/controllers/reset_on_restore_controller.d.ts +3 -3
  201. package/dist/controllers/reset_on_restore_controller.js +6 -0
  202. package/dist/controllers/reset_on_restore_controller.js.map +1 -1
  203. package/dist/controllers/resizable_controller.d.ts +3 -0
  204. package/dist/controllers/resizable_controller.js +55 -22
  205. package/dist/controllers/resizable_controller.js.map +1 -1
  206. package/dist/controllers/roving_controller.d.ts +3 -3
  207. package/dist/controllers/roving_controller.js +10 -4
  208. package/dist/controllers/roving_controller.js.map +1 -1
  209. package/dist/controllers/scroll_area_controller.js +129 -88
  210. package/dist/controllers/scroll_area_controller.js.map +1 -1
  211. package/dist/controllers/scroll_restore_controller.d.ts +3 -3
  212. package/dist/controllers/scroll_restore_controller.js +14 -2
  213. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  214. package/dist/controllers/scroll_visibility_controller.js +93 -60
  215. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  216. package/dist/controllers/scrollspy_controller.js +11 -5
  217. package/dist/controllers/scrollspy_controller.js.map +1 -1
  218. package/dist/controllers/separator_controller.d.ts +1 -1
  219. package/dist/controllers/separator_controller.js +59 -43
  220. package/dist/controllers/separator_controller.js.map +1 -1
  221. package/dist/controllers/sidebar_controller.d.ts +1 -1
  222. package/dist/controllers/sidebar_controller.js +150 -122
  223. package/dist/controllers/sidebar_controller.js.map +1 -1
  224. package/dist/controllers/skeleton_controller.js +55 -48
  225. package/dist/controllers/skeleton_controller.js.map +1 -1
  226. package/dist/controllers/slider_controller.d.ts +2 -1
  227. package/dist/controllers/slider_controller.js +27 -6
  228. package/dist/controllers/slider_controller.js.map +1 -1
  229. package/dist/controllers/smart_sticky_header_controller.d.ts +1 -1
  230. package/dist/controllers/smart_sticky_header_controller.js +13 -5
  231. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  232. package/dist/controllers/sortable_controller.d.ts +4 -4
  233. package/dist/controllers/sortable_controller.js +27 -14
  234. package/dist/controllers/sortable_controller.js.map +1 -1
  235. package/dist/controllers/spinner_controller.js +55 -48
  236. package/dist/controllers/spinner_controller.js.map +1 -1
  237. package/dist/controllers/step_indicator_controller.d.ts +4 -4
  238. package/dist/controllers/step_indicator_controller.js +6 -0
  239. package/dist/controllers/step_indicator_controller.js.map +1 -1
  240. package/dist/controllers/stepper_controller.d.ts +2 -3
  241. package/dist/controllers/stepper_controller.js +6 -0
  242. package/dist/controllers/stepper_controller.js.map +1 -1
  243. package/dist/controllers/stick_to_bottom_controller.d.ts +3 -1
  244. package/dist/controllers/stick_to_bottom_controller.js +19 -8
  245. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  246. package/dist/controllers/sticky_observer_controller.js +49 -43
  247. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  248. package/dist/controllers/submit_once_controller.d.ts +2 -1
  249. package/dist/controllers/submit_once_controller.js +145 -85
  250. package/dist/controllers/submit_once_controller.js.map +1 -1
  251. package/dist/controllers/switch_controller.d.ts +7 -4
  252. package/dist/controllers/switch_controller.js +172 -28
  253. package/dist/controllers/switch_controller.js.map +1 -1
  254. package/dist/controllers/tabs_controller.d.ts +7 -4
  255. package/dist/controllers/tabs_controller.js +6 -1
  256. package/dist/controllers/tabs_controller.js.map +1 -1
  257. package/dist/controllers/tags_input_controller.d.ts +4 -3
  258. package/dist/controllers/tags_input_controller.js +157 -28
  259. package/dist/controllers/tags_input_controller.js.map +1 -1
  260. package/dist/controllers/textarea_autosize_controller.d.ts +1 -1
  261. package/dist/controllers/textarea_autosize_controller.js +40 -19
  262. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  263. package/dist/controllers/theme_controller.d.ts +3 -2
  264. package/dist/controllers/theme_controller.js +10 -4
  265. package/dist/controllers/theme_controller.js.map +1 -1
  266. package/dist/controllers/time_picker_controller.d.ts +38 -5
  267. package/dist/controllers/time_picker_controller.js +192 -54
  268. package/dist/controllers/time_picker_controller.js.map +1 -1
  269. package/dist/controllers/toast_controller.d.ts +4 -5
  270. package/dist/controllers/toast_controller.js +58 -27
  271. package/dist/controllers/toast_controller.js.map +1 -1
  272. package/dist/controllers/toggle_group_controller.d.ts +2 -3
  273. package/dist/controllers/toggle_group_controller.js +158 -56
  274. package/dist/controllers/toggle_group_controller.js.map +1 -1
  275. package/dist/controllers/toolbar_controller.d.ts +8 -6
  276. package/dist/controllers/toolbar_controller.js +150 -21
  277. package/dist/controllers/toolbar_controller.js.map +1 -1
  278. package/dist/controllers/tooltip_controller.d.ts +4 -1
  279. package/dist/controllers/tooltip_controller.js.map +1 -1
  280. package/dist/controllers/transition_controller.js.map +1 -1
  281. package/dist/controllers/tree_view_controller.d.ts +1 -1
  282. package/dist/controllers/tree_view_controller.js +134 -25
  283. package/dist/controllers/tree_view_controller.js.map +1 -1
  284. package/dist/index.d.ts +2 -0
  285. package/dist/index.js +2451 -1312
  286. package/dist/index.js.map +1 -1
  287. package/dist/inspector/cli.d.ts +15 -11
  288. package/dist/inspector/cli.js +16 -3
  289. package/dist/inspector/cli.js.map +1 -1
  290. package/dist/inspector/cli_bin.js +53 -8
  291. package/dist/inspector/cli_bin.js.map +1 -1
  292. package/dist/inspector/examples.json +13 -13
  293. package/dist/inspector/manifest.json +19 -5
  294. package/dist/positioning/index.d.ts +7 -7
  295. package/dist/positioning/index.js +6 -0
  296. package/dist/positioning/index.js.map +1 -1
  297. package/package.json +10 -9
@@ -1,19 +1,6 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
+ import { N as NumericValueEvent } from '../coerce-JtZVNG5h.js';
2
3
 
3
- /**
4
- * Event shape `setValue` accepts: an action param `amount` or a `detail.value`.
5
- * Both are typed `number | string` because, while Stimulus coerces numeric action
6
- * params to numbers, a `meter:set` CustomEvent (or a non-numeric-looking param)
7
- * may carry a string; {@link MeterController.setValue} normalizes either form.
8
- */
9
- type SetValueEvent = Event & {
10
- params?: {
11
- amount?: number | string;
12
- };
13
- detail?: {
14
- value?: number | string;
15
- };
16
- };
17
4
  /**
18
5
  * Headless meter behavior backed by the WAI-ARIA `meter` role.
19
6
  *
@@ -26,7 +13,7 @@ type SetValueEvent = Event & {
26
13
  * </div>
27
14
  *
28
15
  * A `meter` is a *point-in-time* scalar within a known range (disk usage,
29
- * battery, score) — distinct from {@link ProgressController}'s task progress.
16
+ * battery, score) — distinct from `stimeo--progress`'s task progress.
30
17
  * The controller syncs the ARIA value attributes and, when `low`/`high`
31
18
  * thresholds are present, classifies the value into a `low`/`medium`/`high`
32
19
  * segment on `data-state` so the consumer can color the bar.
@@ -36,9 +23,12 @@ type SetValueEvent = Event & {
36
23
  * @remarks
37
24
  * Behavior only. Because state must not be conveyed by color alone (WCAG 1.4.1),
38
25
  * a consumer-provided `valueText` template feeds `aria-valuetext` so the segment
39
- * is also available as text; a consumer that authors `aria-valuetext` itself keeps
40
- * it instead: only text this controller marked as its own is ever taken back. Threshold presence is read from the
41
- * *attributes* (an absent attribute means "no threshold"), not from a sentinel value.
26
+ * is also available as text; with no template, a consumer that authors `aria-valuetext`
27
+ * itself keeps it across renders. While a `valueText` template is set its text replaces an
28
+ * authored `aria-valuetext`; clearing the template or disconnecting puts the authored value
29
+ * back unless the page wrote its own meanwhile, which then stays. A changed template takes
30
+ * the attribute over again. Threshold presence is read from the *attributes* (an absent
31
+ * attribute means "no threshold"), not from a sentinel value.
42
32
  */
43
33
  declare class MeterController extends Controller<HTMLElement> {
44
34
  #private;
@@ -110,14 +100,17 @@ declare class MeterController extends Controller<HTMLElement> {
110
100
  valueTextValue: string;
111
101
  announceTextValue: string;
112
102
  connect(): void;
113
- /** Closes the window in which a queued repaint may still run. */
103
+ /**
104
+ * Closes the window in which a queued repaint may still run, and returns
105
+ * `aria-valuetext` to the authored value unless the page wrote its own meanwhile.
106
+ */
114
107
  disconnect(): void;
115
108
  /**
116
109
  * Updates the measured value from an action param (`amount`) or a
117
110
  * `detail.value` CustomEvent, syncs ARIA and `data-state`, and dispatches
118
111
  * `change` with the value, ratio, and computed segment.
119
112
  */
120
- setValue(event: SetValueEvent): void;
113
+ setValue(event: NumericValueEvent): void;
121
114
  /** Repaints when application code (or a Turbo morph) changes `value` at runtime. */
122
115
  valueValueChanged(): void;
123
116
  /** Repaints when application code (or a Turbo morph) changes `min` at runtime. */
@@ -1,5 +1,12 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
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
+ }
9
+
3
10
  function announce(message, options = {}) {
4
11
  const text = message.trim();
5
12
  if (text.length === 0) return;
@@ -9,12 +16,6 @@ function announce(message, options = {}) {
9
16
  })
10
17
  );
11
18
  }
12
- function fillTemplate(template, values) {
13
- return template.replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (match, name) => {
14
- const replacement = values[name];
15
- return replacement === void 0 ? match : String(replacement);
16
- });
17
- }
18
19
 
19
20
  var NUMBER_BOUNDS = {
20
21
  finite: { finite: true }};
@@ -32,6 +33,9 @@ function matchesNumberBounds(value, bounds) {
32
33
  return true;
33
34
  }
34
35
 
36
+ function eventNumber(event) {
37
+ return toFiniteNumber(event.params?.amount ?? event.detail?.value);
38
+ }
35
39
  function toFiniteNumber(raw) {
36
40
  if (typeof raw !== "number" && typeof raw !== "string") return null;
37
41
  if (typeof raw === "string" && raw.trim().length === 0) return null;
@@ -69,6 +73,9 @@ var MicrotaskCoalescer = class {
69
73
  this.#queued = false;
70
74
  this.#generation += 1;
71
75
  }
76
+ get pending() {
77
+ return this.#queued;
78
+ }
72
79
  schedule() {
73
80
  if (!this.#active || this.#queued) return;
74
81
  this.#queued = true;
@@ -99,6 +106,9 @@ var MorphRenderWatcher = class {
99
106
  schedule() {
100
107
  this.#pass.schedule();
101
108
  }
109
+ get pending() {
110
+ return this.#pass.pending;
111
+ }
102
112
  disconnect() {
103
113
  this.#listeners.dispose();
104
114
  this.#pass.cancel();
@@ -133,7 +143,7 @@ var NumberValueReader = class {
133
143
  function rangeFraction(value, min, max) {
134
144
  const span = max - min;
135
145
  if (!(span > 0)) return 0;
136
- const clamped = Math.min(max, Math.max(min, value));
146
+ const clamped = clampRange(value, min, max);
137
147
  let fraction;
138
148
  if (Number.isFinite(span)) {
139
149
  fraction = (clamped - min) / span;
@@ -144,13 +154,254 @@ function rangeFraction(value, min, max) {
144
154
  if (!Number.isFinite(fraction)) return 0;
145
155
  return Math.min(1, Math.max(0, fraction));
146
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
+ }
177
+
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;
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
+ };
147
401
 
148
- var OWNED_VALUE_TEXT = "owns-valuetext";
149
402
  var MeterController = class _MeterController extends Controller {
150
403
  #numbers = new NumberValueReader();
151
- get #ownedValueText() {
152
- return `data-${this.identifier}-${OWNED_VALUE_TEXT}`;
153
- }
404
+ #valueText = new TemplateAttributeLease("aria-valuetext", this.identifier);
154
405
  static targets = ["bar"];
155
406
  static values = {
156
407
  announceText: { type: String, default: "" },
@@ -182,9 +433,10 @@ var MeterController = class _MeterController extends Controller {
182
433
  }
183
434
  disconnect() {
184
435
  this.#repaint.disconnect();
436
+ this.#valueText.release(this.element);
185
437
  }
186
438
  setValue(event) {
187
- const next = toFiniteNumber(event.params?.amount ?? event.detail?.value);
439
+ const next = eventNumber(event);
188
440
  if (next === null) return;
189
441
  this.valueValue = this.#clamp(next);
190
442
  const shown = this.#shownState;
@@ -215,7 +467,7 @@ var MeterController = class _MeterController extends Controller {
215
467
  this.#repaint.schedule();
216
468
  }
217
469
  #clamp(raw) {
218
- return Math.min(this.#safeMax, Math.max(this.#safeMin, raw));
470
+ return clampRange(raw, this.#safeMin, this.#safeMax);
219
471
  }
220
472
  #hasThreshold(name) {
221
473
  return this.element.hasAttribute(`data-${this.identifier}-${name}-value`);
@@ -242,17 +494,11 @@ var MeterController = class _MeterController extends Controller {
242
494
  return reading;
243
495
  }
244
496
  #applyValueText({ value, ratio, state }) {
245
- if (this.valueTextValue.length === 0) {
246
- if (this.element.hasAttribute(this.#ownedValueText)) {
247
- this.element.removeAttribute("aria-valuetext");
248
- this.element.removeAttribute(this.#ownedValueText);
249
- }
250
- return;
251
- }
252
- const percent = Math.round(ratio * 100);
253
- const text = this.valueTextValue.replaceAll("{value}", String(value)).replaceAll("{percent}", String(percent)).replaceAll("{state}", state);
254
- this.element.setAttribute("aria-valuetext", text);
255
- this.element.setAttribute(this.#ownedValueText, "");
497
+ this.#valueText.render(
498
+ this.element,
499
+ this.valueTextValue,
500
+ fillTemplate(this.valueTextValue, { value, percent: Math.round(ratio * 100), state })
501
+ );
256
502
  }
257
503
  get #safeValue() {
258
504
  return this.#numbers.read(