stimeo-ui 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +8 -1
  3. package/dist/cable/index.d.ts +79 -23
  4. package/dist/cable/index.js +363 -436
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/controllers/accordion_controller.d.ts +4 -2
  7. package/dist/controllers/accordion_controller.js +166 -55
  8. package/dist/controllers/accordion_controller.js.map +1 -1
  9. package/dist/controllers/alert_dialog_controller.d.ts +12 -2
  10. package/dist/controllers/alert_dialog_controller.js +862 -221
  11. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  12. package/dist/controllers/announcer_controller.d.ts +35 -5
  13. package/dist/controllers/announcer_controller.js +135 -198
  14. package/dist/controllers/announcer_controller.js.map +1 -1
  15. package/dist/controllers/aspect_ratio_controller.js +0 -10
  16. package/dist/controllers/aspect_ratio_controller.js.map +1 -1
  17. package/dist/controllers/auto_submit_controller.d.ts +30 -6
  18. package/dist/controllers/auto_submit_controller.js +271 -127
  19. package/dist/controllers/auto_submit_controller.js.map +1 -1
  20. package/dist/controllers/avatar_controller.js +171 -105
  21. package/dist/controllers/avatar_controller.js.map +1 -1
  22. package/dist/controllers/breadcrumb_controller.js +0 -130
  23. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  24. package/dist/controllers/bulk_select_controller.d.ts +18 -0
  25. package/dist/controllers/bulk_select_controller.js +262 -52
  26. package/dist/controllers/bulk_select_controller.js.map +1 -1
  27. package/dist/controllers/calendar_controller.d.ts +24 -5
  28. package/dist/controllers/calendar_controller.js +175 -209
  29. package/dist/controllers/calendar_controller.js.map +1 -1
  30. package/dist/controllers/carousel_controller.d.ts +34 -7
  31. package/dist/controllers/carousel_controller.js +461 -399
  32. package/dist/controllers/carousel_controller.js.map +1 -1
  33. package/dist/controllers/character_counter_controller.d.ts +17 -1
  34. package/dist/controllers/character_counter_controller.js +246 -156
  35. package/dist/controllers/character_counter_controller.js.map +1 -1
  36. package/dist/controllers/checkbox_controller.d.ts +7 -2
  37. package/dist/controllers/checkbox_controller.js +32 -74
  38. package/dist/controllers/checkbox_controller.js.map +1 -1
  39. package/dist/controllers/clipboard_controller.d.ts +16 -5
  40. package/dist/controllers/clipboard_controller.js +168 -147
  41. package/dist/controllers/clipboard_controller.js.map +1 -1
  42. package/dist/controllers/collapsible_controller.d.ts +16 -4
  43. package/dist/controllers/collapsible_controller.js +301 -120
  44. package/dist/controllers/collapsible_controller.js.map +1 -1
  45. package/dist/controllers/color_picker_controller.d.ts +18 -6
  46. package/dist/controllers/color_picker_controller.js +149 -139
  47. package/dist/controllers/color_picker_controller.js.map +1 -1
  48. package/dist/controllers/combobox_controller.d.ts +23 -5
  49. package/dist/controllers/combobox_controller.js +360 -133
  50. package/dist/controllers/combobox_controller.js.map +1 -1
  51. package/dist/controllers/command_palette_controller.d.ts +45 -14
  52. package/dist/controllers/command_palette_controller.js +970 -358
  53. package/dist/controllers/command_palette_controller.js.map +1 -1
  54. package/dist/controllers/conditional_fields_controller.d.ts +15 -2
  55. package/dist/controllers/conditional_fields_controller.js +166 -124
  56. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  57. package/dist/controllers/confirm_controller.d.ts +49 -12
  58. package/dist/controllers/confirm_controller.js +939 -248
  59. package/dist/controllers/confirm_controller.js.map +1 -1
  60. package/dist/controllers/context_menu_controller.d.ts +31 -4
  61. package/dist/controllers/context_menu_controller.js +256 -128
  62. package/dist/controllers/context_menu_controller.js.map +1 -1
  63. package/dist/controllers/count_up_controller.d.ts +13 -1
  64. package/dist/controllers/count_up_controller.js +73 -21
  65. package/dist/controllers/count_up_controller.js.map +1 -1
  66. package/dist/controllers/countdown_controller.d.ts +45 -1
  67. package/dist/controllers/countdown_controller.js +183 -148
  68. package/dist/controllers/countdown_controller.js.map +1 -1
  69. package/dist/controllers/currency_input_controller.d.ts +21 -2
  70. package/dist/controllers/currency_input_controller.js +134 -158
  71. package/dist/controllers/currency_input_controller.js.map +1 -1
  72. package/dist/controllers/data_grid_controller.d.ts +15 -4
  73. package/dist/controllers/data_grid_controller.js +114 -186
  74. package/dist/controllers/data_grid_controller.js.map +1 -1
  75. package/dist/controllers/date_range_picker_controller.d.ts +30 -5
  76. package/dist/controllers/date_range_picker_controller.js +288 -206
  77. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  78. package/dist/controllers/dialog_controller.d.ts +13 -1
  79. package/dist/controllers/dialog_controller.js +858 -223
  80. package/dist/controllers/dialog_controller.js.map +1 -1
  81. package/dist/controllers/direct_upload_controller.d.ts +24 -7
  82. package/dist/controllers/direct_upload_controller.js +73 -153
  83. package/dist/controllers/direct_upload_controller.js.map +1 -1
  84. package/dist/controllers/dirty_form_controller.js +14 -48
  85. package/dist/controllers/dirty_form_controller.js.map +1 -1
  86. package/dist/controllers/dismissible_controller.d.ts +19 -0
  87. package/dist/controllers/dismissible_controller.js +175 -21
  88. package/dist/controllers/dismissible_controller.js.map +1 -1
  89. package/dist/controllers/drawer_controller.d.ts +39 -11
  90. package/dist/controllers/drawer_controller.js +933 -341
  91. package/dist/controllers/drawer_controller.js.map +1 -1
  92. package/dist/controllers/dropdown_controller.d.ts +31 -1
  93. package/dist/controllers/dropdown_controller.js +312 -82
  94. package/dist/controllers/dropdown_controller.js.map +1 -1
  95. package/dist/controllers/editable_controller.d.ts +12 -1
  96. package/dist/controllers/editable_controller.js +158 -68
  97. package/dist/controllers/editable_controller.js.map +1 -1
  98. package/dist/controllers/empty_state_controller.js +67 -53
  99. package/dist/controllers/empty_state_controller.js.map +1 -1
  100. package/dist/controllers/file_dropzone_controller.d.ts +60 -18
  101. package/dist/controllers/file_dropzone_controller.js +311 -207
  102. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  103. package/dist/controllers/filter_controller.js +67 -39
  104. package/dist/controllers/filter_controller.js.map +1 -1
  105. package/dist/controllers/flash_controller.d.ts +31 -8
  106. package/dist/controllers/flash_controller.js +172 -314
  107. package/dist/controllers/flash_controller.js.map +1 -1
  108. package/dist/controllers/focus_controller.d.ts +12 -3
  109. package/dist/controllers/focus_controller.js +654 -240
  110. package/dist/controllers/focus_controller.js.map +1 -1
  111. package/dist/controllers/form_field_controller.js +147 -132
  112. package/dist/controllers/form_field_controller.js.map +1 -1
  113. package/dist/controllers/form_validation_controller.js +13 -86
  114. package/dist/controllers/form_validation_controller.js.map +1 -1
  115. package/dist/controllers/frame_loading_controller.d.ts +41 -9
  116. package/dist/controllers/frame_loading_controller.js +264 -213
  117. package/dist/controllers/frame_loading_controller.js.map +1 -1
  118. package/dist/controllers/highlight_controller.d.ts +22 -2
  119. package/dist/controllers/highlight_controller.js +107 -75
  120. package/dist/controllers/highlight_controller.js.map +1 -1
  121. package/dist/controllers/hover_card_controller.d.ts +56 -3
  122. package/dist/controllers/hover_card_controller.js +309 -118
  123. package/dist/controllers/hover_card_controller.js.map +1 -1
  124. package/dist/controllers/idle_controller.d.ts +42 -1
  125. package/dist/controllers/idle_controller.js +267 -101
  126. package/dist/controllers/idle_controller.js.map +1 -1
  127. package/dist/controllers/input_mask_controller.js +71 -72
  128. package/dist/controllers/input_mask_controller.js.map +1 -1
  129. package/dist/controllers/intersection_controller.d.ts +32 -13
  130. package/dist/controllers/intersection_controller.js +147 -106
  131. package/dist/controllers/intersection_controller.js.map +1 -1
  132. package/dist/controllers/lazy_frame_controller.d.ts +16 -0
  133. package/dist/controllers/lazy_frame_controller.js +9 -65
  134. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  135. package/dist/controllers/listbox_controller.d.ts +34 -2
  136. package/dist/controllers/listbox_controller.js +306 -204
  137. package/dist/controllers/listbox_controller.js.map +1 -1
  138. package/dist/controllers/local_time_controller.d.ts +1 -1
  139. package/dist/controllers/local_time_controller.js +54 -64
  140. package/dist/controllers/local_time_controller.js.map +1 -1
  141. package/dist/controllers/masonry_controller.d.ts +11 -3
  142. package/dist/controllers/masonry_controller.js +70 -93
  143. package/dist/controllers/masonry_controller.js.map +1 -1
  144. package/dist/controllers/menu_controller.d.ts +32 -7
  145. package/dist/controllers/menu_controller.js +214 -156
  146. package/dist/controllers/menu_controller.js.map +1 -1
  147. package/dist/controllers/menubar_controller.d.ts +4 -4
  148. package/dist/controllers/menubar_controller.js +170 -329
  149. package/dist/controllers/menubar_controller.js.map +1 -1
  150. package/dist/controllers/meter_controller.d.ts +20 -0
  151. package/dist/controllers/meter_controller.js +151 -67
  152. package/dist/controllers/meter_controller.js.map +1 -1
  153. package/dist/controllers/multi_select_controller.d.ts +32 -4
  154. package/dist/controllers/multi_select_controller.js +593 -358
  155. package/dist/controllers/multi_select_controller.js.map +1 -1
  156. package/dist/controllers/navigation_menu_controller.d.ts +8 -1
  157. package/dist/controllers/navigation_menu_controller.js +124 -232
  158. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  159. package/dist/controllers/nested_form_controller.d.ts +10 -0
  160. package/dist/controllers/nested_form_controller.js +352 -182
  161. package/dist/controllers/nested_form_controller.js.map +1 -1
  162. package/dist/controllers/network_status_controller.d.ts +23 -0
  163. package/dist/controllers/network_status_controller.js +242 -54
  164. package/dist/controllers/network_status_controller.js.map +1 -1
  165. package/dist/controllers/number_input_controller.d.ts +26 -2
  166. package/dist/controllers/number_input_controller.js +320 -263
  167. package/dist/controllers/number_input_controller.js.map +1 -1
  168. package/dist/controllers/optimistic_controller.js +16 -76
  169. package/dist/controllers/optimistic_controller.js.map +1 -1
  170. package/dist/controllers/otp_controller.d.ts +20 -4
  171. package/dist/controllers/otp_controller.js +198 -193
  172. package/dist/controllers/otp_controller.js.map +1 -1
  173. package/dist/controllers/overflow_indicator_controller.d.ts +5 -0
  174. package/dist/controllers/overflow_indicator_controller.js +116 -113
  175. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  176. package/dist/controllers/overflow_menu_controller.d.ts +48 -11
  177. package/dist/controllers/overflow_menu_controller.js +343 -283
  178. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  179. package/dist/controllers/pagination_controller.d.ts +35 -6
  180. package/dist/controllers/pagination_controller.js +295 -119
  181. package/dist/controllers/pagination_controller.js.map +1 -1
  182. package/dist/controllers/password_reveal_controller.d.ts +45 -8
  183. package/dist/controllers/password_reveal_controller.js +389 -121
  184. package/dist/controllers/password_reveal_controller.js.map +1 -1
  185. package/dist/controllers/password_strength_controller.d.ts +14 -5
  186. package/dist/controllers/password_strength_controller.js +99 -153
  187. package/dist/controllers/password_strength_controller.js.map +1 -1
  188. package/dist/controllers/persist_controller.d.ts +11 -4
  189. package/dist/controllers/persist_controller.js +237 -103
  190. package/dist/controllers/persist_controller.js.map +1 -1
  191. package/dist/controllers/pointer_drag_controller.d.ts +19 -7
  192. package/dist/controllers/pointer_drag_controller.js +185 -165
  193. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  194. package/dist/controllers/popover_controller.d.ts +38 -2
  195. package/dist/controllers/popover_controller.js +236 -97
  196. package/dist/controllers/popover_controller.js.map +1 -1
  197. package/dist/controllers/portal_controller.d.ts +44 -4
  198. package/dist/controllers/portal_controller.js +209 -76
  199. package/dist/controllers/portal_controller.js.map +1 -1
  200. package/dist/controllers/preview_guard_controller.d.ts +10 -4
  201. package/dist/controllers/preview_guard_controller.js +232 -116
  202. package/dist/controllers/preview_guard_controller.js.map +1 -1
  203. package/dist/controllers/progress_controller.d.ts +11 -0
  204. package/dist/controllers/progress_controller.js +125 -56
  205. package/dist/controllers/progress_controller.js.map +1 -1
  206. package/dist/controllers/radio_group_controller.d.ts +14 -5
  207. package/dist/controllers/radio_group_controller.js +117 -137
  208. package/dist/controllers/radio_group_controller.js.map +1 -1
  209. package/dist/controllers/range_slider_controller.d.ts +43 -3
  210. package/dist/controllers/range_slider_controller.js +192 -105
  211. package/dist/controllers/range_slider_controller.js.map +1 -1
  212. package/dist/controllers/rating_controller.d.ts +20 -4
  213. package/dist/controllers/rating_controller.js +418 -207
  214. package/dist/controllers/rating_controller.js.map +1 -1
  215. package/dist/controllers/read_more_controller.d.ts +2 -0
  216. package/dist/controllers/read_more_controller.js +134 -63
  217. package/dist/controllers/read_more_controller.js.map +1 -1
  218. package/dist/controllers/reading_progress_controller.d.ts +1 -1
  219. package/dist/controllers/reading_progress_controller.js +147 -135
  220. package/dist/controllers/reading_progress_controller.js.map +1 -1
  221. package/dist/controllers/relative_time_controller.d.ts +18 -4
  222. package/dist/controllers/relative_time_controller.js +145 -110
  223. package/dist/controllers/relative_time_controller.js.map +1 -1
  224. package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
  225. package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +97 -38
  226. package/dist/controllers/reset_on_restore_controller.js.map +1 -0
  227. package/dist/controllers/resizable_controller.d.ts +28 -2
  228. package/dist/controllers/resizable_controller.js +255 -139
  229. package/dist/controllers/resizable_controller.js.map +1 -1
  230. package/dist/controllers/roving_controller.js +39 -84
  231. package/dist/controllers/roving_controller.js.map +1 -1
  232. package/dist/controllers/scroll_area_controller.d.ts +7 -3
  233. package/dist/controllers/scroll_area_controller.js +428 -225
  234. package/dist/controllers/scroll_area_controller.js.map +1 -1
  235. package/dist/controllers/scroll_restore_controller.js +0 -53
  236. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  237. package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
  238. package/dist/controllers/scroll_visibility_controller.js +395 -145
  239. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  240. package/dist/controllers/scrollspy_controller.d.ts +6 -1
  241. package/dist/controllers/scrollspy_controller.js +181 -242
  242. package/dist/controllers/scrollspy_controller.js.map +1 -1
  243. package/dist/controllers/separator_controller.d.ts +19 -4
  244. package/dist/controllers/separator_controller.js +267 -140
  245. package/dist/controllers/separator_controller.js.map +1 -1
  246. package/dist/controllers/sidebar_controller.d.ts +64 -7
  247. package/dist/controllers/sidebar_controller.js +1023 -386
  248. package/dist/controllers/sidebar_controller.js.map +1 -1
  249. package/dist/controllers/skeleton_controller.d.ts +23 -0
  250. package/dist/controllers/skeleton_controller.js +248 -97
  251. package/dist/controllers/skeleton_controller.js.map +1 -1
  252. package/dist/controllers/slider_controller.d.ts +27 -1
  253. package/dist/controllers/slider_controller.js +159 -79
  254. package/dist/controllers/slider_controller.js.map +1 -1
  255. package/dist/controllers/smart_sticky_header_controller.d.ts +21 -3
  256. package/dist/controllers/smart_sticky_header_controller.js +162 -63
  257. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  258. package/dist/controllers/sortable_controller.js +0 -112
  259. package/dist/controllers/sortable_controller.js.map +1 -1
  260. package/dist/controllers/spinner_controller.d.ts +39 -4
  261. package/dist/controllers/spinner_controller.js +277 -169
  262. package/dist/controllers/spinner_controller.js.map +1 -1
  263. package/dist/controllers/step_indicator_controller.d.ts +5 -0
  264. package/dist/controllers/step_indicator_controller.js +99 -46
  265. package/dist/controllers/step_indicator_controller.js.map +1 -1
  266. package/dist/controllers/stepper_controller.d.ts +12 -3
  267. package/dist/controllers/stepper_controller.js +114 -73
  268. package/dist/controllers/stepper_controller.js.map +1 -1
  269. package/dist/controllers/stick_to_bottom_controller.d.ts +6 -0
  270. package/dist/controllers/stick_to_bottom_controller.js +262 -138
  271. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  272. package/dist/controllers/sticky_observer_controller.d.ts +11 -0
  273. package/dist/controllers/sticky_observer_controller.js +214 -49
  274. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  275. package/dist/controllers/submit_once_controller.d.ts +23 -8
  276. package/dist/controllers/submit_once_controller.js +294 -205
  277. package/dist/controllers/submit_once_controller.js.map +1 -1
  278. package/dist/controllers/switch_controller.d.ts +12 -1
  279. package/dist/controllers/switch_controller.js +33 -60
  280. package/dist/controllers/switch_controller.js.map +1 -1
  281. package/dist/controllers/tabs_controller.d.ts +2 -2
  282. package/dist/controllers/tabs_controller.js +35 -29
  283. package/dist/controllers/tabs_controller.js.map +1 -1
  284. package/dist/controllers/tags_input_controller.d.ts +12 -0
  285. package/dist/controllers/tags_input_controller.js +136 -145
  286. package/dist/controllers/tags_input_controller.js.map +1 -1
  287. package/dist/controllers/textarea_autosize_controller.d.ts +10 -0
  288. package/dist/controllers/textarea_autosize_controller.js +71 -58
  289. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  290. package/dist/controllers/theme_controller.d.ts +21 -9
  291. package/dist/controllers/theme_controller.js +130 -112
  292. package/dist/controllers/theme_controller.js.map +1 -1
  293. package/dist/controllers/time_picker_controller.d.ts +18 -1
  294. package/dist/controllers/time_picker_controller.js +146 -80
  295. package/dist/controllers/time_picker_controller.js.map +1 -1
  296. package/dist/controllers/toast_controller.d.ts +36 -11
  297. package/dist/controllers/toast_controller.js +186 -297
  298. package/dist/controllers/toast_controller.js.map +1 -1
  299. package/dist/controllers/toggle_group_controller.d.ts +12 -3
  300. package/dist/controllers/toggle_group_controller.js +95 -136
  301. package/dist/controllers/toggle_group_controller.js.map +1 -1
  302. package/dist/controllers/toolbar_controller.js +68 -98
  303. package/dist/controllers/toolbar_controller.js.map +1 -1
  304. package/dist/controllers/tooltip_controller.d.ts +45 -3
  305. package/dist/controllers/tooltip_controller.js +158 -124
  306. package/dist/controllers/tooltip_controller.js.map +1 -1
  307. package/dist/controllers/transition_controller.d.ts +22 -4
  308. package/dist/controllers/transition_controller.js +123 -119
  309. package/dist/controllers/transition_controller.js.map +1 -1
  310. package/dist/controllers/tree_view_controller.d.ts +21 -11
  311. package/dist/controllers/tree_view_controller.js +150 -345
  312. package/dist/controllers/tree_view_controller.js.map +1 -1
  313. package/dist/index.d.ts +8 -5
  314. package/dist/index.js +6370 -9346
  315. package/dist/index.js.map +1 -1
  316. package/dist/inspector/cli.d.ts +23 -3
  317. package/dist/inspector/cli.js +92 -37
  318. package/dist/inspector/cli.js.map +1 -1
  319. package/dist/inspector/cli_bin.js +92 -56
  320. package/dist/inspector/cli_bin.js.map +1 -1
  321. package/dist/inspector/examples.json +8 -8
  322. package/dist/inspector/manifest.json +787 -100
  323. package/dist/positioning/index.d.ts +8 -0
  324. package/dist/positioning/index.js +148 -47
  325. package/dist/positioning/index.js.map +1 -1
  326. package/package.json +6 -6
  327. package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
  328. package/dist/controllers/reset_before_cache_controller.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/composition_tracker.ts","../../src/utils/half_width.ts","../../src/utils/intl_format.ts","../../src/utils/locale.ts","../../src/controllers/currency_input_controller.ts"],"names":[],"mappings":"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","file":"currency_input_controller.js","sourcesContent":["/** Minimal event shape carrying the platform's per-event composition signal. */\nexport interface CompositionSignal {\n readonly isComposing?: boolean;\n}\n\n/** Minimal `input` shape needed to tell a composition echo from a fresh edit. */\nexport interface ConfirmedInputSignal {\n readonly target: EventTarget | null;\n readonly inputType?: string;\n}\n\n/**\n * The `inputType` values an engine reports on an `input` that belongs to a\n * composition rather than to an edit the user just made.\n */\nconst COMPOSITION_INPUT_TYPES = new Set([\n \"insertCompositionText\",\n \"insertFromComposition\",\n \"deleteCompositionText\",\n \"deleteByComposition\",\n]);\n\n/** Hooks that keep component-specific work outside {@link CompositionTracker}. */\nexport interface CompositionTrackerOptions {\n /** Runs after lifecycle state is set for a `compositionstart` event. */\n readonly onStart?: (event: Event) => void;\n /** Runs after lifecycle state is cleared for a `compositionend` event. */\n readonly onEnd?: (event: Event) => void;\n}\n\n/**\n * Owns IME composition listeners and transient state for one or more event targets.\n *\n * Some browsers omit `KeyboardEvent.isComposing` on the keydown that confirms a\n * conversion. Tracking `compositionstart` through `compositionend` supplies the\n * missing lifecycle signal without relying on deprecated numeric key codes.\n * Component policy stays with the consumer: filtering, validation, and submission\n * belong in the optional {@link CompositionTrackerOptions.onEnd} callback.\n *\n * The tracker also owns the other half of that lifecycle: **the `input` some\n * engines send after `compositionend` to echo the text just confirmed.** A\n * consumer that ran `onEnd` and then handled the echo would commit the same\n * confirmation twice, so {@link CompositionTracker.consumesConfirmedInput} tells\n * the echo apart and the consumer returns early on it.\n *\n * **What the echo is not, is the harder half.** Not every engine sends one —\n * Chromium ends a confirmation at `compositionend` with no `input` after it — so\n * a window that waits for the echo and only closes on the next key would swallow\n * the first edit that arrives without one: dictation, autofill, a drop,\n * `insertText`. Two things keep that from happening. The window closes on the\n * next anything — a key, a new composition, any `input`, losing the field — and\n * an `input` that reports an `inputType` outside {@link COMPOSITION_INPUT_TYPES}\n * is an edit, so it is never folded. Only an engine that reports no `inputType`\n * at all is left relying on the window alone.\n *\n * @example\n * ```ts\n * #composition = new CompositionTracker({ onEnd: () => this.filter() });\n *\n * connect(): void {\n * this.#composition.observe(this.inputTarget);\n * }\n *\n * disconnect(): void {\n * this.#composition.disconnect();\n * }\n *\n * onInput(event: InputEvent): void {\n * if (this.#composition.consumesConfirmedInput(event)) return;\n * if (this.#composition.isComposing(event)) return;\n * }\n *\n * onKeydown(event: KeyboardEvent): void {\n * if (this.#composition.isComposing(event)) return;\n * }\n * ```\n */\nexport class CompositionTracker {\n readonly #observedTargets = new Set<EventTarget>();\n readonly #activeTargets = new Set<EventTarget>();\n readonly #onStart: ((event: Event) => void) | undefined;\n readonly #onEnd: ((event: Event) => void) | undefined;\n /** The field whose confirming `input` is still owed, while the window is open. */\n #confirmedTarget: EventTarget | null = null;\n\n constructor(options: CompositionTrackerOptions = {}) {\n this.#onStart = options.onStart;\n this.#onEnd = options.onEnd;\n }\n\n /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */\n observe(target: EventTarget): void {\n if (this.#observedTargets.has(target)) return;\n target.addEventListener(\"compositionstart\", this.#handleStart);\n target.addEventListener(\"compositionend\", this.#handleEnd);\n target.addEventListener(\"keydown\", this.#handleKeydown);\n this.#observedTargets.add(target);\n }\n\n /** Stops tracking one target and clears any active composition it owned. */\n unobserve(target: EventTarget): void {\n if (!this.#observedTargets.delete(target)) return;\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n target.removeEventListener(\"keydown\", this.#handleKeydown);\n this.#activeTargets.delete(target);\n if (this.#confirmedTarget === target) this.#confirmedTarget = null;\n }\n\n /** Releases every listener and clears state so reconnect starts cleanly. */\n disconnect(): void {\n for (const target of this.#observedTargets) {\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n target.removeEventListener(\"keydown\", this.#handleKeydown);\n }\n this.#observedTargets.clear();\n this.#activeTargets.clear();\n this.#confirmedTarget = null;\n }\n\n /** True when lifecycle tracking or the current event reports composition. */\n isComposing(event?: CompositionSignal): boolean {\n return this.#activeTargets.size > 0 || event?.isComposing === true;\n }\n\n /**\n * Whether `event` is the `input` echoing the composition just confirmed.\n *\n * Asking closes the window either way, so one confirmation is folded at most\n * once and a consumer asks once per `input`.\n */\n consumesConfirmedInput(event: ConfirmedInputSignal): boolean {\n const confirmed = this.#confirmedTarget;\n this.#confirmedTarget = null;\n if (confirmed === null || confirmed !== event.target) return false;\n // An engine that reports no kind at all leaves `inputType` empty, and the\n // window is then the only signal there is.\n const inputType = event.inputType;\n return !inputType || COMPOSITION_INPUT_TYPES.has(inputType);\n }\n\n readonly #handleStart = (event: Event): void => {\n this.#confirmedTarget = null;\n if (event.currentTarget) this.#activeTargets.add(event.currentTarget);\n this.#onStart?.(event);\n };\n\n readonly #handleEnd = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);\n this.#confirmedTarget = event.target;\n this.#onEnd?.(event);\n };\n\n /** A key on an observed field opens an edit of its own, so no echo is owed. */\n readonly #handleKeydown = (): void => {\n this.#confirmedTarget = null;\n };\n}\n","/** The distance between a full-width ASCII code point and its half-width twin. */\nconst FULL_WIDTH_SHIFT = 0xfee0;\n\n/**\n * The half-width form of `char`, or `char` itself when it has none.\n *\n * An IME confirming in full-width mode produces U+FF01–U+FF5E (and U+3000 for\n * the space) where the page means ASCII — the digits of a phone number, the\n * letters of a code, the separators between them. Reading those as their ASCII\n * equivalents keeps confirmed text usable instead of discarding it. Characters\n * outside that block, including kana and astral code points, are returned\n * unchanged, so this never rewrites text a consumer meant to keep as typed.\n */\nexport function halfWidthChar(char: string): string {\n if (char >= \"!\" && char <= \"~\") {\n return String.fromCharCode(char.charCodeAt(0) - FULL_WIDTH_SHIFT);\n }\n return char === \" \" ? \" \" : char;\n}\n\n/** Every full-width ASCII character in `text` rewritten by {@link halfWidthChar}. */\nexport function toHalfWidth(text: string): string {\n let out = \"\";\n for (const char of text) out += halfWidthChar(char);\n return out;\n}\n","/**\n * Construction of `Intl` formatters for the controllers that take a locale, and\n * the options that go with it, from a declaration.\n *\n * Every `Intl` constructor resolves locale data on the way in, which makes it\n * too costly to rebuild on a hot path, and rejects a malformed language tag,\n * currency code, time zone or digit count with a `RangeError`. Both concerns are\n * handled here once. A formatter is built at most once per distinct request and\n * shared by every caller that asks for the same one. A `RangeError` is caught\n * and answered the way the caller asked: by rebuilding under a fallback locale,\n * or by returning `null` so the caller can leave its authored text alone. Any\n * other failure is a programming fault and propagates.\n */\n\n/** The constructor shape the `Intl` formatter classes share. */\nexport interface IntlFormatterConstructor<F, O extends object> {\n new (locales?: string | string[], options?: O): F;\n}\n\n/** Built formatters, and refusals, per constructor; see `cacheKey` for the key. */\nconst formatters = new WeakMap<object, Map<string, unknown>>();\n\n/**\n * A formatter for `locale` with `options`.\n *\n * With `fallbackLocale`, a `RangeError` from the constructor is answered by\n * building the same options under the fallback instead, so the result is never\n * `null`; the fallback's own failure propagates. Without it, a `RangeError`\n * yields `null` and the caller decides what to show. Errors of any other kind\n * propagate in both forms.\n *\n * Results are cached per constructor and `(locale, options, fallback)`, `null`\n * included, so asking again on every render costs one map lookup.\n */\nexport function intlFormatter<F, O extends object>(\n factory: IntlFormatterConstructor<F, O>,\n locale: string | undefined,\n options: O,\n fallbackLocale: string,\n): F;\nexport function intlFormatter<F, O extends object>(\n factory: IntlFormatterConstructor<F, O>,\n locale: string | undefined,\n options: O,\n): F | null;\nexport function intlFormatter<F, O extends object>(\n factory: IntlFormatterConstructor<F, O>,\n locale: string | undefined,\n options: O,\n fallbackLocale?: string,\n): F | null {\n const cache = cacheFor(factory);\n const key = cacheKey(locale, options, fallbackLocale);\n if (cache.has(key)) return cache.get(key) as F | null;\n const formatter = construct(factory, locale, options, fallbackLocale);\n cache.set(key, formatter);\n return formatter;\n}\n\n/** The cache for one constructor, created on first use. */\nfunction cacheFor(factory: object): Map<string, unknown> {\n const existing = formatters.get(factory);\n if (existing) return existing;\n const created = new Map<string, unknown>();\n formatters.set(factory, created);\n return created;\n}\n\n/**\n * One key per distinct request. `JSON.stringify` drops an option left\n * `undefined`, which is how the constructor reads it too. Two spellings of the\n * same options differing only in key order key separately; that costs one extra\n * formatter, never a wrong one, and call sites pass a fixed literal anyway.\n */\nfunction cacheKey(\n locale: string | undefined,\n options: object,\n fallbackLocale: string | undefined,\n): string {\n return JSON.stringify([locale, options, fallbackLocale]);\n}\n\n/** Builds the formatter under the `RangeError` contract described on `intlFormatter`. */\nfunction construct<F, O extends object>(\n factory: IntlFormatterConstructor<F, O>,\n locale: string | undefined,\n options: O,\n fallbackLocale: string | undefined,\n): F | null {\n try {\n return new factory(locale, options);\n } catch (error) {\n if (!(error instanceof RangeError)) throw error;\n if (fallbackLocale === undefined) return null;\n return new factory(fallbackLocale, options);\n }\n}\n","/**\n * The locale a component formats in: its own declaration, else the language of\n * the text around it, else the runtime default.\n *\n * `lang` is inherited in HTML, so the language that applies to an element is the\n * nearest one on the element itself or on an ancestor — not the document\n * element's, which is only the farthest of them. An empty `lang` there means the\n * language is unknown and stops the inheritance at that point, so it resolves to\n * the runtime default rather than to a `lang` further up.\n *\n * Resolution only, and the value is passed through as authored. Whether `Intl`\n * accepts the tag, and what to show when it does not, is the caller's contract.\n *\n * @example\n * ```ts\n * intlFormatter(Intl.DateTimeFormat, resolveLocale(this.element, this.localeValue), options);\n * ```\n */\nexport function resolveLocale(element: Element, declared = \"\"): string | undefined {\n return declared || element.closest(\"[lang]\")?.getAttribute(\"lang\") || undefined;\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { CompositionTracker } from \"../utils/composition_tracker\";\nimport { halfWidthChar } from \"../utils/half_width\";\nimport { intlFormatter } from \"../utils/intl_format\";\nimport { resolveLocale } from \"../utils/locale\";\n\n/** The number-shaped pieces of an in-progress entry, in typing order. */\ninterface EntryParts {\n /** The leading sign exactly as typed (`\"\"` when none). */\n sign: \"\" | \"-\" | \"+\";\n /** Integer digits with grouping stripped (may be empty mid-entry). */\n int: string;\n /** Whether a decimal mark was typed. */\n hasDot: boolean;\n /** Fraction digits exactly as typed; rounding happens only on blur. */\n frac: string;\n}\n\n/** One scan of the display text: its structure and the numeric value it holds. */\ninterface Scan {\n parts: EntryParts;\n /** The finite value, or `null` while no digit has been typed yet. */\n value: number | null;\n}\n\n/** Who moved the value: the user editing the display, or the page. */\ntype Cause = \"edit\" | \"reconcile\";\n\n/**\n * The locale a declaration falls back to when `Intl` rejects it, so a broken tag\n * still leaves a field that formats and parses the same way every time.\n */\nconst FALLBACK_LOCALE = \"en-US\";\n\n/**\n * Headless currency / amount input behavior: groups digits for display while\n * keeping a machine-readable number in a hidden field, and mirrors the\n * normalized value to a visually-hidden span so assistive tech reads the real\n * amount rather than the grouped display string.\n *\n * Markup contract (identifier: `stimeo--currency-input`):\n * <div data-controller=\"stimeo--currency-input\"\n * data-stimeo--currency-input-locale-value=\"en-US\"\n * data-stimeo--currency-input-currency-value=\"USD\"\n * data-stimeo--currency-input-precision-value=\"2\">\n * <input type=\"text\" inputmode=\"decimal\"\n * aria-describedby=\"amt-sr\"\n * data-stimeo--currency-input-target=\"display\"\n * data-action=\"input->stimeo--currency-input#onInput\n * blur->stimeo--currency-input#format\" />\n * <span id=\"amt-sr\" class=\"visually-hidden\"\n * data-stimeo--currency-input-target=\"srValue\"></span>\n * <input type=\"hidden\" data-stimeo--currency-input-target=\"field\" />\n * </div>\n *\n * `change` and `reconcile` dispatch `{ value: number | null, formatted: string }`\n * — `null` (with an empty `formatted`) when the amount is cleared, so consumers\n * hear every transition of the numeric value, including back to empty. `change`\n * is the user's edit: typing, or the rounding applied on `blur`. `reconcile` is a\n * value the page moved: a `locale`, `currency` or `precision` change that\n * re-rounds the committed amount, a display target swapped in holding another\n * amount, a reconnect that rounds an entry left unrounded mid-typing, or a move\n * that ends a composition before its `compositionend`. Connecting over a\n * server-rendered value reports neither.\n *\n * @remarks\n * Behavior only — no styling, no validation (range/required belong to the\n * consumer or `stimeo--form-field`). The display field is the sole Tab stop and keeps its\n * native text-editing behavior; this controller never steals focus.\n *\n * While typing, the entry is preserved as typed: grouping is applied to the\n * integer digits per locale, a leading sign and a trailing decimal mark stay in\n * place, fraction digits are kept verbatim, and the caret is restored after the\n * same significant character it followed. Negative amounts are in scope. The\n * fixed-precision rounding is applied on `blur`, never mid-entry.\n * Full-width digits, signs, and marks (an IME confirming 0-9/./-) are\n * normalized to their ASCII forms rather than stripped; the locale's own\n * digits (a non-Latin default numbering system such as ar-EG's) are mapped\n * back the same way; and U+2212 MINUS SIGN is read as a sign. An ASCII \".\"\n * only counts as a decimal mark in locales where it is not the grouping\n * separator. Together these keep the controller's own output re-parseable to\n * the same value in every locale. Events fired mid-IME-composition are\n * ignored; the confirmed text is formatted once on `compositionend`. A\n * `locale` / `currency` / `precision` change that arrives mid-composition\n * leaves the uncommitted text alone and applies right after that confirmed\n * text has been read. A composition this controller stops hearing — its display\n * leaves, or the controller disconnects, before `compositionend` — ends there:\n * a display still in place is read as `compositionend` would read it, and a\n * value that moves is reported as `reconcile`. A field or screen-reader span\n * arriving mid-composition takes the committed value.\n *\n * Display text is read with the declarations it was written for. This\n * controller's own rendering was written with the separators in force, so a\n * declaration change reads it before they change. Any other text is the page's\n * — a display swapped in, or text written into the display alongside a\n * declaration change — written for the declarations the page carries, so it is\n * read with those.\n *\n * With no `locale` declared the field formats in the nearest `lang` up the\n * ancestor chain, else in the runtime default. A malformed `locale` falls back\n * to `en-US`, and a malformed `currency` or `precision` to that Value's default,\n * instead of throwing. The declarations, the nearest `lang` among them, are\n * read and validated before a display is read after they may have moved — on a\n * Value change, when the controller connects, and when a display arrives; the\n * hot path only ever sees validated values through cached `Intl.NumberFormat`\n * instances, never built per keystroke. Late-arriving or swapped `field` /\n * `srValue` / `display` targets are re-synced on connection.\n *\n * Reconnecting starts from the committed value: a display still showing this\n * controller's own rendering is not read back but re-rendered from that value\n * under the current declarations, so a `locale` changed while the element was\n * away never re-reads its separators. The re-render is the fixed-precision\n * form, so it rounds whenever the value has more places than the current\n * `precision` allows — because `precision` changed while the element was away,\n * or because the entry was left unrounded mid-typing (`1.555` becomes `1.56`) —\n * and a value it moves is reported as `reconcile`. The composition listeners\n * are released on `disconnect()`.\n *\n * Honest a11y note: a hidden `<input>` is not exposed to assistive tech, so the\n * normalized value is *also* published as text in the `srValue` span referenced\n * by the display's `aria-describedby` — that, not the hidden field, is what a\n * screen reader announces.\n */\nexport class CurrencyInputController extends Controller<HTMLElement> {\n static override targets = [\"display\", \"field\", \"srValue\"];\n static override values = {\n locale: { type: String, default: \"\" },\n currency: { type: String, default: \"\" },\n precision: { type: Number, default: 2 },\n };\n static actions = [\"format\", \"onInput\"] as const;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly displayTarget: HTMLInputElement;\n declare readonly fieldTarget: HTMLInputElement;\n declare readonly srValueTarget: HTMLElement;\n declare readonly hasDisplayTarget: boolean;\n declare readonly hasFieldTarget: boolean;\n declare readonly hasSrValueTarget: boolean;\n declare localeValue: string;\n declare currencyValue: string;\n declare precisionValue: number;\n\n /** The numeric value last committed; both events report only a move away from it. */\n #lastValue: number | null = null;\n #started = false;\n /** A declaration change that arrived mid-composition, applied once nothing composes. */\n #changeHeld = false;\n /** The display a composition is running on, until that composition ends. */\n #composing: EventTarget | null = null;\n /**\n * The display text this controller last rendered. It tells this controller's own\n * text, written with the separators in force, from text the page wrote.\n */\n #rendered: string | null = null;\n\n /** Validated mirrors of the Values; the hot path never reads a raw Value. */\n #locale: string | undefined;\n #currency = \"\";\n #precision = 2;\n\n /** Formatters rebuilt when the declarations are taken in, never per keystroke. */\n #grouping!: Intl.NumberFormat;\n #fixed!: Intl.NumberFormat;\n #accessible!: Intl.NumberFormat;\n #group = \",\";\n #decimal = \".\";\n /** The locale's non-Latin digits mapped back to ASCII (empty for Latin locales). */\n readonly #digits = new Map<string, string>();\n\n /**\n * Holds mid-composition input so the IME's uncommitted text is never rewritten.\n * The confirmed text is formatted once, and a declaration change the composition\n * held back is applied after it.\n */\n readonly #composition = new CompositionTracker({\n onStart: (event) => {\n this.#composing = event.currentTarget;\n },\n onEnd: () => {\n this.#composing = null;\n this.#reformat(false, \"edit\");\n this.#applyHeldChange();\n },\n });\n\n /**\n * Re-validates on declaration changes and re-renders the committed display,\n * reporting a value the re-render moved as `reconcile`.\n */\n localeValueChanged(): void {\n this.#applyValueChange();\n }\n\n currencyValueChanged(): void {\n this.#applyValueChange();\n }\n\n precisionValueChanged(): void {\n this.#applyValueChange();\n }\n\n /**\n * Reads the display with the declarations its text was written for, then\n * re-renders it under the new ones — so a locale switch re-interprets the\n * value, never the old text with new separators, and text the page wrote for\n * the declarations it changes is never read with the old ones.\n *\n * While the display is composing, its text is the IME's: the change is held,\n * configuration and all, until the composition ends, so the confirmed text is\n * read with the separators it was typed against before the change applies.\n *\n * @stimeoRenderRoot\n */\n #applyValueChange(): void {\n if (this.#composition.isComposing()) {\n this.#changeHeld = true;\n return;\n }\n // With nothing to read, the next display or the next connect takes the\n // declarations in before reading.\n if (!this.#started || !this.hasDisplayTarget) return;\n const scan = this.#readDisplay();\n if (document.activeElement === this.displayTarget) {\n const formatted = this.#render(scan.parts);\n this.#show(formatted);\n this.#reflect(scan.value, formatted, \"reconcile\");\n } else {\n this.#renderFixed(scan.value, \"reconcile\");\n }\n }\n\n /** Applies a declaration change a composition held back. */\n #applyHeldChange(): void {\n if (!this.#changeHeld) return;\n this.#changeHeld = false;\n this.#applyValueChange();\n }\n\n /**\n * Reads the display and takes in the declarations the page carries now. This\n * controller's own rendering was written with the separators in force, so it\n * is read before they change; any other text is the page's, written for the\n * declarations it carries, so it is read after.\n */\n #readDisplay(): Scan {\n const text = this.displayTarget.value;\n const own = text === this.#rendered ? this.#scan(text) : null;\n this.#takeInDeclarations();\n return own ?? this.#scan(text);\n }\n\n /** Takes in the declarations the page carries now, a change a composition held among them. */\n #takeInDeclarations(): void {\n this.#changeHeld = false;\n this.#revalidate();\n }\n\n /**\n * Takes in the declarations the page carries now and normalizes the display\n * to its fixed-precision form.\n *\n * A display still showing this controller's own last rendering is not read\n * back: its separators may belong to declarations that changed while the\n * controller was away, and the committed value is known anyway. That value is\n * re-rendered at the current fixed precision, which rounds it whether\n * `precision` changed meanwhile or the entry was left unrounded mid-typing, and\n * a move the rounding causes is reported as `reconcile`. Any other text is the\n * page's, written for the declarations it carries, so it is read with them.\n */\n override connect(): void {\n this.#started = true;\n this.#takeInDeclarations();\n if (!this.hasDisplayTarget) return;\n if (this.displayTarget.value === this.#rendered) {\n this.#renderFixed(this.#lastValue, \"reconcile\");\n return;\n }\n // Seed the baseline with the *rounded* initial value: the idempotent\n // connect-time reformat describes the value the page rendered, so it\n // reports nothing.\n const { value } = this.#scan(this.displayTarget.value);\n this.#lastValue = value === null ? null : round(value, this.#precision);\n this.#renderFixed(value, \"reconcile\");\n }\n\n /**\n * Releases the composition listeners. A composition still running hears no\n * `compositionend` once they are gone, so it ends here; a change it held is\n * taken in on the next `connect()`.\n */\n override disconnect(): void {\n this.#endUntrackedComposition();\n this.#composition.disconnect();\n this.#started = false;\n }\n\n /**\n * Tracks composition on an arriving (or swapped-in) display and normalizes it\n * under the declarations the page carries now, reading this controller's own\n * rendering with the separators it was written under; an amount that differs\n * from the committed one is the page's, so it is reported as `reconcile`.\n */\n displayTargetConnected(target: HTMLInputElement): void {\n this.#composition.observe(target);\n if (!this.#started) return;\n this.#renderFixed(this.#readDisplay().value, \"reconcile\");\n }\n\n /**\n * Stops tracking a display that leaves. A composition running on it hears no\n * `compositionend` any more, so it ends here; a change it held waits for the\n * next display to be read.\n */\n displayTargetDisconnected(target: HTMLInputElement): void {\n this.#composition.unobserve(target);\n this.#endUntrackedComposition();\n }\n\n /**\n * Ends a composition no `compositionend` will reach. A display still in place —\n * one a move re-inserted, or the display of a controller that moves — holds the\n * text the composition left, typed against the declarations in force, so it is\n * read as `compositionend` would read it and becomes this controller's own\n * rendering. The page's move ended the composition, so a value it moves is\n * reported as `reconcile`. A display that left takes its composition along.\n */\n #endUntrackedComposition(): void {\n const display = this.#composing;\n this.#composing = null;\n if (this.hasDisplayTarget && this.displayTarget === display) {\n this.#reformat(false, \"reconcile\");\n }\n }\n\n /** Syncs a late-arriving hidden field without touching the display or events. */\n fieldTargetConnected(): void {\n if (this.#started) this.#resync();\n }\n\n /** Syncs a late-arriving screen-reader span the same way. */\n srValueTargetConnected(): void {\n if (this.#started) this.#resync();\n }\n\n /** Re-groups digits as the user types, preserving the caret position. */\n onInput(event: Event): void {\n if (this.#composition.isComposing(event as InputEvent)) return;\n this.#reformat(false, \"edit\");\n }\n\n /** Applies the fixed-precision rounding on blur. */\n format(): void {\n this.#reformat(true, \"edit\");\n }\n\n /**\n * Parses the display value, rewrites it grouped (optionally at fixed\n * precision), keeps the caret stable by significant characters, and syncs the\n * field, the screen-reader span, and the event `cause` selects.\n */\n #reformat(fixedPrecision: boolean, cause: Cause): void {\n if (!this.hasDisplayTarget) return;\n const raw = this.displayTarget.value;\n const { parts, value } = this.#scan(raw);\n\n if (fixedPrecision) {\n // Blur with no digits (an abandoned sign or dot) clears the entry.\n this.#renderFixed(value, cause);\n return;\n }\n\n const formatted = this.#render(parts);\n if (formatted !== raw) {\n const caret = this.displayTarget.selectionStart;\n const anchor = caret === null ? null : this.#significantBefore(raw, caret);\n this.displayTarget.value = formatted;\n if (anchor !== null) this.#restoreCaret(formatted, anchor);\n }\n this.#rendered = formatted;\n this.#reflect(value, formatted, cause);\n }\n\n /**\n * Shows `value` at the fixed precision — an empty display for no value — and\n * reports a move under the event `cause` selects.\n */\n #renderFixed(value: number | null, cause: Cause): void {\n if (value === null) {\n this.#show(\"\");\n this.#reflect(null, \"\", cause);\n return;\n }\n const rounded = round(value, this.#precision);\n const formatted = this.#fixed.format(rounded);\n this.#show(formatted);\n this.#reflect(rounded, formatted, cause);\n }\n\n /** Writes `text` to the display as this controller's own rendering. */\n #show(text: string): void {\n this.displayTarget.value = text;\n this.#rendered = text;\n }\n\n /**\n * The in-progress rendering: grouped integer, sign and fraction as typed.\n */\n #render(parts: EntryParts): string {\n const int = parts.int === \"\" ? \"\" : this.#grouping.format(BigInt(parts.int));\n const frac = parts.hasDot ? this.#decimal + parts.frac : \"\";\n return parts.sign + int + frac;\n }\n\n /** Restores the caret to sit just after the n-th significant character. */\n #restoreCaret(formatted: string, significantBefore: number): void {\n let seen = 0;\n let position = formatted.length;\n for (let i = 0; i < formatted.length; i++) {\n if (seen >= significantBefore) {\n position = i;\n break;\n }\n if (this.#isSignificant(formatted[i] as string)) seen += 1;\n }\n try {\n this.displayTarget.setSelectionRange(position, position);\n } catch {\n // Some hosts disallow selection on certain input states; the value is\n // already correct, so a failed caret restore is non-fatal.\n }\n }\n\n /**\n * Counts the characters before `caret` that survive into the rendering,\n * applying the same acceptance rules as {@link #scan} — a rejected keystroke\n * (a mid-string sign, a second decimal mark) must not shift the anchor.\n */\n #significantBefore(text: string, caret: number): number {\n let count = 0;\n let sawSign = false;\n let sawDigit = false;\n let sawDot = false;\n for (const ch of this.#normalize(text.slice(0, caret))) {\n if (ch >= \"0\" && ch <= \"9\") {\n count += 1;\n sawDigit = true;\n } else if ((ch === \"-\" || ch === \"+\") && !sawSign && !sawDigit && !sawDot) {\n count += 1;\n sawSign = true;\n } else if (this.#isDecimalMark(ch) && !sawDot) {\n count += 1;\n sawDot = true;\n }\n }\n return count;\n }\n\n /** Digits, signs, and the decimal mark anchor the caret; grouping does not. */\n #isSignificant(ch: string): boolean {\n if (ch >= \"0\" && ch <= \"9\") return true;\n if (ch === \"-\" || ch === \"+\") return true;\n return ch === this.#decimal || (ch === \".\" && this.#group !== \".\");\n }\n\n /** Writes the normalized value to the field, the SR span, and the empty hook. */\n #write(value: number | null): void {\n const isEmpty = value === null;\n if (this.hasFieldTarget) this.fieldTarget.value = isEmpty ? \"\" : String(value);\n if (this.hasSrValueTarget) {\n this.srValueTarget.textContent = isEmpty ? \"\" : this.#accessible.format(value);\n }\n this.element.toggleAttribute(`data-${this.identifier}-empty`, isEmpty);\n }\n\n /**\n * {@link #write}, then reports a moved value under the event `cause` selects:\n * `change` for the user's edit, `reconcile` for a move the page caused. The\n * display may hold an in-progress `-`, but a `null` value always rides with an\n * empty `formatted`, whichever event reports it, so consumers can treat the\n * pair as cleared.\n */\n #reflect(value: number | null, formatted: string, cause: Cause): void {\n this.#write(value);\n if (value === this.#lastValue) return;\n this.#lastValue = value;\n const detail = { value, formatted: value === null ? \"\" : formatted };\n if (cause === \"edit\") this.dispatch(\"change\", { detail });\n else this.dispatch(\"reconcile\", { detail });\n }\n\n /**\n * Scans arbitrary input text into its number-shaped parts and value. Keeps\n * digits, one leading sign, one decimal mark, and the fraction verbatim;\n * everything else (grouping, symbols, words) is dropped. An ASCII \".\" is only\n * a decimal mark where it is not the locale's grouping separator. Precision\n * plays no part here — rounding belongs to the blur-time format.\n */\n #scan(text: string): Scan {\n let sign: EntryParts[\"sign\"] = \"\";\n let int = \"\";\n let hasDot = false;\n let frac = \"\";\n for (const ch of this.#normalize(text)) {\n if (ch >= \"0\" && ch <= \"9\") {\n if (hasDot) frac += ch;\n else int += ch;\n } else if ((ch === \"-\" || ch === \"+\") && sign === \"\" && int === \"\" && !hasDot) {\n sign = ch;\n } else if (this.#isDecimalMark(ch) && !hasDot) {\n hasDot = true;\n }\n }\n const parts: EntryParts = { sign, int, hasDot, frac };\n // `Number` accepts \"12.\" and \".5\" alike, so one dotted form covers every\n // shape — and a digit-less entry (\"\", \"-\", \".\") reads as NaN, hence null.\n const value = Number(`${sign}${int}.${frac}`);\n return { parts, value: Number.isFinite(value) ? value : null };\n }\n\n /** Whether `ch` reads as this locale's decimal mark. */\n #isDecimalMark(ch: string): boolean {\n return ch === this.#decimal || (ch === \".\" && this.#group !== \".\");\n }\n\n /**\n * Re-syncs field / srValue / hook without dispatching: from the display, or —\n * while it is composing, when its text is not committed yet — from the value\n * last committed.\n */\n #resync(): void {\n if (!this.hasDisplayTarget) return;\n const value = this.#composition.isComposing()\n ? this.#lastValue\n : this.#scan(this.displayTarget.value).value;\n this.#write(value);\n }\n\n /**\n * Validates the declared Values, falling back to each Value's default when a\n * declaration cannot be interpreted (a malformed locale or currency tag, a\n * precision outside `Intl`'s 0–100 integer range), and rebuilds the cached\n * formatters from the validated set.\n */\n #revalidate(): void {\n const resolved = resolveLocale(this.element, this.localeValue);\n const usable = intlFormatter(Intl.NumberFormat, resolved, {});\n this.#locale = usable === null ? FALLBACK_LOCALE : resolved;\n\n const precision = this.precisionValue;\n this.#precision =\n Number.isInteger(precision) && precision >= 0 && precision <= 100 ? precision : 2;\n\n this.#currency = \"\";\n if (this.currencyValue !== \"\") {\n const declaredCurrency = intlFormatter(Intl.NumberFormat, this.#locale, {\n style: \"currency\",\n currency: this.currencyValue,\n });\n // An unknown code falls through to the plain-number accessible text.\n if (declaredCurrency !== null) this.#currency = this.currencyValue;\n }\n\n this.#grouping = intlFormatter(\n Intl.NumberFormat,\n this.#locale,\n { useGrouping: true, maximumFractionDigits: 0 },\n FALLBACK_LOCALE,\n );\n this.#fixed = intlFormatter(\n Intl.NumberFormat,\n this.#locale,\n {\n useGrouping: true,\n minimumFractionDigits: this.#precision,\n maximumFractionDigits: this.#precision,\n },\n FALLBACK_LOCALE,\n );\n this.#accessible = this.#currency\n ? intlFormatter(\n Intl.NumberFormat,\n this.#locale,\n { style: \"currency\", currency: this.#currency },\n FALLBACK_LOCALE,\n )\n : this.#fixed;\n\n const parts = intlFormatter(Intl.NumberFormat, this.#locale, {}, FALLBACK_LOCALE).formatToParts(\n 11111.1,\n );\n this.#group = parts.find((p) => p.type === \"group\")?.value ?? \",\";\n this.#decimal = parts.find((p) => p.type === \"decimal\")?.value ?? \".\";\n\n // Locales whose default numbering system is not Latin (ar-EG, fa-IR, …)\n // format with their own digits; mapping them back keeps the controller's\n // own output re-parseable to the same value.\n this.#digits.clear();\n const digitFormatter = intlFormatter(\n Intl.NumberFormat,\n this.#locale,\n { useGrouping: false },\n FALLBACK_LOCALE,\n );\n for (let i = 0; i <= 9; i++) {\n const digit = digitFormatter.format(i);\n if (digit !== String(i)) this.#digits.set(digit, String(i));\n }\n }\n\n /**\n * Maps the locale's own digits to ASCII, folds full-width forms (the digits,\n * signs, and marks an IME confirms as 0-9+-.,) through the shared\n * half-width mapping, and reads U+2212 MINUS SIGN as \"-\", which some locales'\n * formatted output uses for negatives.\n */\n #normalize(text: string): string {\n let out = \"\";\n for (const ch of text) {\n const mapped = this.#digits.get(ch);\n if (mapped !== undefined) {\n out += mapped;\n } else if (ch === \"−\") {\n out += \"-\";\n } else {\n out += halfWidthChar(ch);\n }\n }\n return out;\n }\n}\n\n/** Rounds `value` to `precision` decimal places, avoiding `-0`; overflow keeps `value`. */\nfunction round(value: number, precision: number): number {\n const factor = 10 ** Math.max(0, precision);\n const rounded = Math.round(value * factor) / factor;\n if (!Number.isFinite(rounded)) return value;\n return rounded === 0 ? 0 : rounded;\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/composition_tracker.ts","../../src/utils/half_width.ts","../../src/utils/intl_format.ts","../../src/utils/locale.ts","../../src/utils/listener_set.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/morph_render_watcher.ts","../../src/utils/number_bounds.ts","../../src/utils/coerce.ts","../../src/utils/number_value.ts","../../src/controllers/currency_input_controller.ts"],"names":[],"mappings":"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","file":"currency_input_controller.js","sourcesContent":["/** Minimal event shape carrying the platform's per-event composition signal. */\nexport interface CompositionSignal {\n readonly isComposing?: boolean;\n}\n\n/** Minimal `input` shape needed to tell a composition echo from a fresh edit. */\nexport interface ConfirmedInputSignal {\n readonly target: EventTarget | null;\n readonly inputType?: string;\n}\n\n/**\n * The `inputType` values an engine reports on an `input` that belongs to a\n * composition rather than to an edit the user just made.\n */\nconst COMPOSITION_INPUT_TYPES = new Set([\n \"insertCompositionText\",\n \"insertFromComposition\",\n \"deleteCompositionText\",\n \"deleteByComposition\",\n]);\n\n/** Hooks that keep component-specific work outside {@link CompositionTracker}. */\nexport interface CompositionTrackerOptions {\n /** Runs after lifecycle state is set for a `compositionstart` event. */\n readonly onStart?: (event: Event) => void;\n /** Runs after lifecycle state is cleared for a `compositionend` event. */\n readonly onEnd?: (event: Event) => void;\n}\n\n/**\n * Owns IME composition listeners and transient state for one or more event targets.\n *\n * Some browsers omit `KeyboardEvent.isComposing` on the keydown that confirms a\n * conversion. Tracking `compositionstart` through `compositionend` supplies the\n * missing lifecycle signal without relying on deprecated numeric key codes.\n * Component policy stays with the consumer: filtering, validation, and submission\n * belong in the optional {@link CompositionTrackerOptions.onEnd} callback.\n *\n * The tracker also owns the other half of that lifecycle: **the `input` some\n * engines send after `compositionend` to echo the text just confirmed.** A\n * consumer that ran `onEnd` and then handled the echo would commit the same\n * confirmation twice, so {@link CompositionTracker.consumesConfirmedInput} tells\n * the echo apart and the consumer returns early on it.\n *\n * **What the echo is not, is the harder half.** Not every engine sends one —\n * Chromium ends a confirmation at `compositionend` with no `input` after it — so\n * a window that waits for the echo and only closes on the next key would swallow\n * the first edit that arrives without one: dictation, autofill, a drop,\n * `insertText`. Two things keep that from happening. The window closes on the\n * next anything — a key, a new composition, any `input`, losing the field — and\n * an `input` that reports an `inputType` outside {@link COMPOSITION_INPUT_TYPES}\n * is an edit, so it is never folded. Only an engine that reports no `inputType`\n * at all is left relying on the window alone.\n *\n * @example\n * ```ts\n * #composition = new CompositionTracker({ onEnd: () => this.filter() });\n *\n * connect(): void {\n * this.#composition.observe(this.inputTarget);\n * }\n *\n * disconnect(): void {\n * this.#composition.disconnect();\n * }\n *\n * onInput(event: InputEvent): void {\n * if (this.#composition.consumesConfirmedInput(event)) return;\n * if (this.#composition.isComposing(event)) return;\n * }\n *\n * onKeydown(event: KeyboardEvent): void {\n * if (this.#composition.isComposing(event)) return;\n * }\n * ```\n */\nexport class CompositionTracker {\n readonly #observedTargets = new Set<EventTarget>();\n readonly #activeTargets = new Set<EventTarget>();\n readonly #onStart: ((event: Event) => void) | undefined;\n readonly #onEnd: ((event: Event) => void) | undefined;\n /** The field whose confirming `input` is still owed, while the window is open. */\n #confirmedTarget: EventTarget | null = null;\n\n constructor(options: CompositionTrackerOptions = {}) {\n this.#onStart = options.onStart;\n this.#onEnd = options.onEnd;\n }\n\n /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */\n observe(target: EventTarget): void {\n if (this.#observedTargets.has(target)) return;\n target.addEventListener(\"compositionstart\", this.#handleStart);\n target.addEventListener(\"compositionend\", this.#handleEnd);\n target.addEventListener(\"keydown\", this.#handleKeydown);\n this.#observedTargets.add(target);\n }\n\n /** Stops tracking one target and clears any active composition it owned. */\n unobserve(target: EventTarget): void {\n if (!this.#observedTargets.delete(target)) return;\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n target.removeEventListener(\"keydown\", this.#handleKeydown);\n this.#activeTargets.delete(target);\n if (this.#confirmedTarget === target) this.#confirmedTarget = null;\n }\n\n /** Releases every listener and clears state so reconnect starts cleanly. */\n disconnect(): void {\n for (const target of this.#observedTargets) {\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n target.removeEventListener(\"keydown\", this.#handleKeydown);\n }\n this.#observedTargets.clear();\n this.#activeTargets.clear();\n this.#confirmedTarget = null;\n }\n\n /** True when lifecycle tracking or the current event reports composition. */\n isComposing(event?: CompositionSignal): boolean {\n return this.#activeTargets.size > 0 || event?.isComposing === true;\n }\n\n /**\n * Whether `event` is the `input` echoing the composition just confirmed.\n *\n * Asking closes the window either way, so one confirmation is folded at most\n * once and a consumer asks once per `input`.\n */\n consumesConfirmedInput(event: ConfirmedInputSignal): boolean {\n const confirmed = this.#confirmedTarget;\n this.#confirmedTarget = null;\n if (confirmed === null || confirmed !== event.target) return false;\n // An engine that reports no kind at all leaves `inputType` empty, and the\n // window is then the only signal there is.\n const inputType = event.inputType;\n return !inputType || COMPOSITION_INPUT_TYPES.has(inputType);\n }\n\n readonly #handleStart = (event: Event): void => {\n this.#confirmedTarget = null;\n if (event.currentTarget) this.#activeTargets.add(event.currentTarget);\n this.#onStart?.(event);\n };\n\n readonly #handleEnd = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);\n this.#confirmedTarget = event.target;\n this.#onEnd?.(event);\n };\n\n /** A key on an observed field opens an edit of its own, so no echo is owed. */\n readonly #handleKeydown = (): void => {\n this.#confirmedTarget = null;\n };\n}\n","/** The distance between a full-width ASCII code point and its half-width twin. */\nconst FULL_WIDTH_SHIFT = 0xfee0;\n\n/**\n * The half-width form of `char`, or `char` itself when it has none.\n *\n * An IME confirming in full-width mode produces U+FF01–U+FF5E (and U+3000 for\n * the space) where the page means ASCII — the digits of a phone number, the\n * letters of a code, the separators between them. Reading those as their ASCII\n * equivalents keeps confirmed text usable instead of discarding it. Characters\n * outside that block, including kana and astral code points, are returned\n * unchanged, so this never rewrites text a consumer meant to keep as typed.\n */\nexport function halfWidthChar(char: string): string {\n if (char >= \"!\" && char <= \"~\") {\n return String.fromCharCode(char.charCodeAt(0) - FULL_WIDTH_SHIFT);\n }\n return char === \" \" ? \" \" : char;\n}\n\n/** Every full-width ASCII character in `text` rewritten by {@link halfWidthChar}. */\nexport function toHalfWidth(text: string): string {\n let out = \"\";\n for (const char of text) out += halfWidthChar(char);\n return out;\n}\n","/**\n * Construction of `Intl` formatters for the controllers that take a locale, and\n * the options that go with it, from a declaration.\n *\n * Every `Intl` constructor resolves locale data on the way in, which makes it\n * too costly to rebuild on a hot path, and rejects a malformed language tag,\n * currency code, time zone or digit count with a `RangeError`. Both concerns are\n * handled here once. A formatter is built at most once per distinct request and\n * shared by every caller that asks for the same one. A `RangeError` is caught\n * and answered the way the caller asked: by rebuilding under a fallback locale,\n * or by returning `null` so the caller can leave its authored text alone. Any\n * other failure is a programming fault and propagates.\n */\n\n/** The constructor shape the `Intl` formatter classes share. */\nexport interface IntlFormatterConstructor<F, O extends object> {\n new (locales?: string | string[], options?: O): F;\n}\n\n/** Built formatters, and refusals, per constructor; see `cacheKey` for the key. */\nconst formatters = new WeakMap<object, Map<string, unknown>>();\n\n/**\n * A formatter for `locale` with `options`.\n *\n * With `fallbackLocale`, a `RangeError` from the constructor is answered by\n * building the same options under the fallback instead, so the result is never\n * `null`; the fallback's own failure propagates. Without it, a `RangeError`\n * yields `null` and the caller decides what to show. Errors of any other kind\n * propagate in both forms.\n *\n * Results are cached per constructor and `(locale, options, fallback)`, `null`\n * included, so asking again on every render costs one map lookup.\n */\nexport function intlFormatter<F, O extends object>(\n factory: IntlFormatterConstructor<F, O>,\n locale: string | undefined,\n options: O,\n fallbackLocale: string,\n): F;\nexport function intlFormatter<F, O extends object>(\n factory: IntlFormatterConstructor<F, O>,\n locale: string | undefined,\n options: O,\n): F | null;\nexport function intlFormatter<F, O extends object>(\n factory: IntlFormatterConstructor<F, O>,\n locale: string | undefined,\n options: O,\n fallbackLocale?: string,\n): F | null {\n const cache = cacheFor(factory);\n const key = cacheKey(locale, options, fallbackLocale);\n if (cache.has(key)) return cache.get(key) as F | null;\n const formatter = construct(factory, locale, options, fallbackLocale);\n cache.set(key, formatter);\n return formatter;\n}\n\n/** The cache for one constructor, created on first use. */\nfunction cacheFor(factory: object): Map<string, unknown> {\n const existing = formatters.get(factory);\n if (existing) return existing;\n const created = new Map<string, unknown>();\n formatters.set(factory, created);\n return created;\n}\n\n/**\n * One key per distinct request. `JSON.stringify` drops an option left\n * `undefined`, which is how the constructor reads it too. Two spellings of the\n * same options differing only in key order key separately; that costs one extra\n * formatter, never a wrong one, and call sites pass a fixed literal anyway.\n */\nfunction cacheKey(\n locale: string | undefined,\n options: object,\n fallbackLocale: string | undefined,\n): string {\n return JSON.stringify([locale, options, fallbackLocale]);\n}\n\n/** Builds the formatter under the `RangeError` contract described on `intlFormatter`. */\nfunction construct<F, O extends object>(\n factory: IntlFormatterConstructor<F, O>,\n locale: string | undefined,\n options: O,\n fallbackLocale: string | undefined,\n): F | null {\n try {\n return new factory(locale, options);\n } catch (error) {\n if (!(error instanceof RangeError)) throw error;\n if (fallbackLocale === undefined) return null;\n return new factory(fallbackLocale, options);\n }\n}\n","/**\n * The locale a component formats in: its own declaration, else the language of\n * the text around it, else the runtime default.\n *\n * `lang` is inherited in HTML, so the language that applies to an element is the\n * nearest one on the element itself or on an ancestor — not the document\n * element's, which is only the farthest of them. An empty `lang` there means the\n * language is unknown and stops the inheritance at that point, so it resolves to\n * the runtime default rather than to a `lang` further up.\n *\n * Resolution only, and the value is passed through as authored. Whether `Intl`\n * accepts the tag, and what to show when it does not, is the caller's contract.\n *\n * @example\n * ```ts\n * intlFormatter(Intl.DateTimeFormat, resolveLocale(this.element, this.localeValue), options);\n * ```\n */\nexport function resolveLocale(element: Element, declared = \"\"): string | undefined {\n return declared || element.closest(\"[lang]\")?.getAttribute(\"lang\") || undefined;\n}\n","/**\n * Owns every listener a controller attaches for one connected lifetime and\n * releases them together, so an event name is spelled once and the release\n * cannot drift from the registration.\n *\n * Detaching by hand repeats three things at the release site — the type, the\n * handler reference and the capture flag — and any one of them drifting leaves\n * a listener alive on an element the controller no longer drives. Aborting the\n * signal a registration was created with releases it whatever it was made of,\n * so the release site names nothing.\n *\n * One set per lifetime, held as a field and never rebuilt. {@link\n * ListenerSet.dispose} is the only thing that closes a generation, and it opens\n * the next one in the same step, so the lifecycle hooks can call `add` and\n * `dispose` in any order any number of times, and no `add` ever meets an\n * already aborted signal — a DOM that registers a listener on such a signal\n * would keep it forever. Rebuilding the set instead would leak:\n * `addEventListener` matches an existing registration on target, type, callback\n * and capture alone, so re-adding the same handler while the first registration\n * is live is discarded, and that live registration keeps the signal it was\n * attached with — a set built by a second `connect()` can never release what it\n * appears to own.\n *\n * Scope is the registration only. Timers, observers, leases and the order they\n * are unwound in stay with the controller, which places `dispose()` in its\n * cleanup sequence. A receiver that changes at runtime (a\n * swapped target) is rebound by calling `dispose()` and then `add()` again from\n * the rebind, not by a second set.\n *\n * The set must own every registration of a tuple it holds: a listener the same\n * target already carries for the same type, callback and capture flag keeps the\n * right to remove it, and this set's `add` for that tuple is discarded. A\n * subscription shared between instances behind a participant count, or one that\n * lives for less than the connection, keeps its own pair of calls.\n *\n * @example\n * ```ts\n * readonly #listeners = new ListenerSet();\n *\n * connect(): void {\n * this.#listeners.add(this.element, \"submit\", this.#onNativeSubmit, { capture: true });\n * this.#listeners.add(this.element, \"turbo:submit-start\", this.#onSubmitStart);\n * this.#listeners.add(this.element, \"turbo:submit-end\", this.#onSubmitEnd);\n * }\n *\n * disconnect(): void {\n * this.#listeners.dispose();\n * }\n * ```\n */\nexport class ListenerSet {\n /** The generation every `add` joins until the next `dispose()`. */\n #abort = new AbortController();\n\n /**\n * Attaches `handler` to the open generation, exactly as the caller spelled it.\n *\n * The set supplies the signal, so `options` carries everything else the DOM\n * accepts — `capture` included, which has to match at release time and no\n * longer has a second place to drift from.\n */\n add(\n target: EventTarget,\n type: string,\n handler: EventListener,\n options?: Omit<AddEventListenerOptions, \"signal\">,\n ): void {\n target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });\n }\n\n /**\n * Releases every listener of the open generation, synchronously, and opens the\n * next one. Idempotent, and safe before anything has been added.\n */\n dispose(): void {\n this.#abort.abort();\n this.#abort = new AbortController();\n }\n}\n","/**\n * Collapses many Stimulus lifecycle callbacks from one DOM mutation into a\n * single pass.\n *\n * Stimulus fires `<name>TargetConnected` / `Disconnected` once per element and\n * `<name>ValueChanged` once per changed attribute. Replacing a list of N options\n * or morphing several render Values therefore delivers N callbacks — but the\n * useful unit of work is \"reconcile against the resulting declarative input\",\n * once, after the batch has settled. Every controller with reconcilable targets\n * or render Values needs the same shape: a `queued` flag plus `queueMicrotask`.\n *\n * **A microtask is the right horizon, and the reason is specific.** Stimulus\n * drives these callbacks from a `MutationObserver`, whose own callback already\n * runs as a microtask with the whole batch in hand; scheduling one more lands\n * after the last sibling callback of that batch and still before paint or any\n * event handler. A timer would be later than it needs to be, and reconciling\n * synchronously would run once per element against a half-applied DOM.\n *\n * **The two guards are not the same guard.** Scheduling is refused before the\n * controller connects, and running is refused after it disconnects:\n *\n * - **Before `connect()`** — Stimulus delivers initial target and Value callbacks\n * ahead of `connect()`. Reconciling there would compute output against a\n * controller whose own state has not been initialised, and `connect()` is\n * about to do a full pass anyway.\n * - **After `disconnect()`** — Stimulus fires a callback for **every** target\n * during teardown, and a microtask queued just before it would otherwise run\n * against a detached tree. {@link MicrotaskCoalescer.cancel} exists for the\n * teardown path to drop the pending pass outright.\n *\n * Both guards are part of one contract here rather than something each consumer\n * has to remember separately.\n *\n * Scope is the scheduling only. *What* to reconcile — keep the surviving active\n * option, fall back to the next / previous / first visible one, rebuild derived\n * chips or hidden fields — stays in the controller, because no two consumers\n * answer it the same way.\n *\n * @example\n * ```ts\n * readonly #reconcile = new MicrotaskCoalescer(() => this.#reconcileOptions());\n *\n * connect() { this.#reconcile.activate(); }\n * disconnect() { this.#reconcile.cancel(); }\n *\n * optionTargetConnected() { this.#reconcile.schedule(); }\n * optionTargetDisconnected() { this.#reconcile.schedule(); }\n * ```\n */\nexport class MicrotaskCoalescer {\n readonly #run: () => void;\n #queued = false;\n #active = false;\n #generation = 0;\n\n /** @param run - the single reconciliation pass, invoked at most once per batch. */\n constructor(run: () => void) {\n this.#run = run;\n }\n\n /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */\n activate(): void {\n this.#active = true;\n }\n\n /** Closes the window and drops any pending pass; call from `disconnect()`. */\n cancel(): void {\n this.#active = false;\n this.#queued = false;\n this.#generation += 1;\n }\n\n /** Requests one pass after the batch settles. Idempotent; inert outside the window. */\n schedule(): void {\n if (!this.#active || this.#queued) return;\n this.#queued = true;\n const generation = this.#generation;\n queueMicrotask(() => {\n // A cancelled callback must not consume a pass queued after reconnect.\n if (generation !== this.#generation || !this.#queued || !this.#active) return;\n this.#queued = false;\n this.#run();\n });\n }\n}\n","import { ListenerSet } from \"./listener_set\";\nimport { MicrotaskCoalescer } from \"./microtask_coalescer\";\n\n/**\n * Coalesces retained-element morphs and explicit lifecycle requests into one pass.\n *\n * Observe the controller's element after its initial state is settled. Morphs on\n * that element and bubbling morphs on its descendants share the same microtask\n * as {@link schedule}. The callback repairs derived output; the controller owns\n * any logical transition reporting. {@link disconnect} releases the listener and\n * cancels pending work, including work from an earlier connected lifetime.\n */\nexport class MorphRenderWatcher {\n readonly #listeners = new ListenerSet();\n readonly #pass: MicrotaskCoalescer;\n #element: Element | null = null;\n readonly #onMorph = (): void => this.#pass.schedule();\n\n /** @param run - the single pass that repairs the settled controller's output. */\n constructor(run: () => void) {\n this.#pass = new MicrotaskCoalescer(run);\n }\n\n /** Opens observation; observing the same element again preserves queued work. */\n observe(element: Element): void {\n if (this.#element === element) return;\n this.disconnect();\n this.#element = element;\n this.#pass.activate();\n this.#listeners.add(element, \"turbo:morph-element\", this.#onMorph);\n }\n\n /** Requests one pass; requests outside an observed lifetime are ignored. */\n schedule(): void {\n this.#pass.schedule();\n }\n\n /** Releases observation and pending work synchronously; safe to repeat. */\n disconnect(): void {\n this.#listeners.dispose();\n this.#pass.cancel();\n this.#element = null;\n }\n}\n","import { MAX_TIMER_DELAY_MS } from \"./timer_bounds\";\n\n/** Semantic constraints on an already decoded number, independent of the DOM. */\nexport interface NumberBounds {\n /** Finite numbers are required, including when this field is omitted. */\n readonly finite?: true;\n /** Inclusive lower endpoint. */\n readonly min?: number;\n /** Inclusive upper endpoint. */\n readonly max?: number;\n /** Exclusive lower endpoint. */\n readonly exclusiveMin?: number;\n /** Require a number without a fractional part. */\n readonly integer?: boolean;\n /** Exact decoded numbers accepted by a discrete contract. */\n readonly allowedValues?: readonly number[];\n /** JSON-safe exceptions to finite-number checking for unbounded endpoints. */\n readonly allowInfinity?: \"negative\" | \"positive\" | \"both\";\n}\n\n/** One constraint for each Number Value, including shorthand declarations. */\nexport type NumberValueConstraints<Values> = {\n readonly [Key in keyof Values as Values[Key] extends\n | NumberConstructor\n | { type: NumberConstructor }\n ? Key\n : never]: NumberBounds;\n};\n\n/** Reusable semantic domains; fractional inputs remain fractional unless excluded. */\nexport const NUMBER_BOUNDS = {\n finite: { finite: true },\n nonNegative: { finite: true, min: 0 },\n positive: { finite: true, exclusiveMin: 0 },\n nonNegativeInteger: { finite: true, min: 0, integer: true },\n positiveInteger: { finite: true, exclusiveMin: 0, integer: true },\n lowerBound: { finite: true, allowInfinity: \"negative\" },\n upperBound: { finite: true, allowInfinity: \"positive\" },\n timer: { finite: true, min: 0, max: MAX_TIMER_DELAY_MS },\n positiveTimer: { finite: true, exclusiveMin: 0, max: MAX_TIMER_DELAY_MS },\n} as const satisfies Record<string, NumberBounds>;\n\n/**\n * Checks all declared bounds without rounding, clamping, or coercing the input.\n * Infinity exceptions relax only finite checking; every other bound still applies.\n */\nexport function matchesNumberBounds(value: number, bounds: NumberBounds): boolean {\n if (!Number.isFinite(value)) {\n const direction = value === Infinity ? \"positive\" : value === -Infinity ? \"negative\" : null;\n if (direction === null) return false;\n if (bounds.allowInfinity !== \"both\" && bounds.allowInfinity !== direction) return false;\n }\n if (bounds.min !== undefined && value < bounds.min) return false;\n if (bounds.max !== undefined && value > bounds.max) return false;\n if (bounds.exclusiveMin !== undefined && value <= bounds.exclusiveMin) return false;\n if (bounds.integer && !Number.isInteger(value)) return false;\n if (bounds.allowedValues !== undefined && !bounds.allowedValues.includes(value)) return false;\n return true;\n}\n\n/** Decodes a Number Value literal; action params use their own JSON decoder. */\nexport function decodeNumberValue(raw: string): number {\n return Number(raw.replace(/_/g, \"\"));\n}\n","/**\n * Numeric coercion for controllers that accept a number through a Value, an action\n * param, or an event detail.\n *\n * Stimulus decodes action params as JSON when possible and leaves other text\n * untouched. CustomEvent detail can also supply a number or numeric string.\n * The reader accepts those two types while rejecting blank and non-finite input.\n */\n\nimport { matchesNumberBounds, type NumberBounds } from \"./number_bounds\";\n\n/**\n * Reads a finite number or nonblank numeric string; other input returns `null`.\n * Blank strings cannot silently reset a value to zero.\n */\nexport function toFiniteNumber(raw: unknown): number | null {\n if (typeof raw !== \"number\" && typeof raw !== \"string\") return null;\n if (typeof raw === \"string\" && raw.trim().length === 0) return null;\n const value = Number(raw);\n return Number.isFinite(value) ? value : null;\n}\n\n/**\n * Returns an accepted decoded Number Value or the caller's fallback unchanged.\n * The caller owns the fallback contract; this reader does not parse or write a Value.\n */\nexport function readNumber(raw: number, fallback: number, bounds: NumberBounds): number {\n return matchesNumberBounds(raw, bounds) ? raw : fallback;\n}\n","import { readNumber } from \"./coerce\";\nimport { matchesNumberBounds, type NumberBounds } from \"./number_bounds\";\n\n/** The instance identity carried by a Number Value read. */\nexport interface NumberValueOwner {\n readonly identifier: string;\n readonly element: Element;\n}\n\n/** Reads current declarations at the point of use without rewriting their attributes. */\nexport class NumberValueReader {\n /** The last rejected literal per Value; no history grows for an unchanged instance. */\n readonly #lastRejected = new Map<string, string>();\n\n /** Resolves the declared number using its own fallback and shared class contract. */\n read(\n owner: NumberValueOwner,\n name: string,\n raw: number,\n fallback: number,\n bounds: NumberBounds,\n ): number {\n const resolved = readNumber(raw, fallback, bounds);\n if (matchesNumberBounds(raw, bounds)) {\n this.#lastRejected.delete(name);\n return resolved;\n }\n const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;\n const literal = owner.element.getAttribute(attribute);\n if (literal === null) {\n this.#lastRejected.delete(name);\n return resolved;\n }\n if (this.#lastRejected.get(name) !== literal) {\n this.#lastRejected.set(name, literal);\n console.warn(\n `Stimeo UI: \"${owner.identifier}\" has an invalid number Value \"${name}\" declaration ${JSON.stringify(literal)}; using ${fallback}.`,\n );\n }\n return resolved;\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { CompositionTracker } from \"../utils/composition_tracker\";\nimport { halfWidthChar } from \"../utils/half_width\";\nimport { intlFormatter } from \"../utils/intl_format\";\nimport { resolveLocale } from \"../utils/locale\";\nimport { MorphRenderWatcher } from \"../utils/morph_render_watcher\";\nimport type { NumberValueConstraints } from \"../utils/number_bounds\";\nimport { NumberValueReader } from \"../utils/number_value\";\n\n/** The number-shaped pieces of an in-progress entry, in typing order. */\ninterface EntryParts {\n /** The leading sign exactly as typed (`\"\"` when none). */\n sign: \"\" | \"-\" | \"+\";\n /** Integer digits with grouping stripped (may be empty mid-entry). */\n int: string;\n /** Whether a decimal mark was typed. */\n hasDot: boolean;\n /** Fraction digits exactly as typed; rounding happens only on blur. */\n frac: string;\n}\n\n/** One scan of the display text: its structure and the numeric value it holds. */\ninterface Scan {\n parts: EntryParts;\n /** The finite value, or `null` while no digit has been typed yet. */\n value: number | null;\n}\n\n/** Who moved the value: the user editing the display, or the page. */\ntype Cause = \"edit\" | \"reconcile\";\n\n/**\n * The locale a declaration falls back to when `Intl` rejects it, so a broken tag\n * still leaves a field that formats and parses the same way every time.\n */\nconst FALLBACK_LOCALE = \"en-US\";\n\n/**\n * Headless currency / amount input behavior: groups digits for display while\n * keeping a machine-readable number in a hidden field, and mirrors the\n * normalized value to a visually-hidden span so assistive tech reads the real\n * amount rather than the grouped display string.\n *\n * Markup contract (identifier: `stimeo--currency-input`):\n * <div data-controller=\"stimeo--currency-input\"\n * data-stimeo--currency-input-locale-value=\"en-US\"\n * data-stimeo--currency-input-currency-value=\"USD\"\n * data-stimeo--currency-input-precision-value=\"2\">\n * <input type=\"text\" inputmode=\"decimal\"\n * aria-describedby=\"amt-sr\"\n * data-stimeo--currency-input-target=\"display\"\n * data-action=\"input->stimeo--currency-input#onInput\n * blur->stimeo--currency-input#format\" />\n * <span id=\"amt-sr\" class=\"visually-hidden\"\n * data-stimeo--currency-input-target=\"srValue\"></span>\n * <input type=\"hidden\" data-stimeo--currency-input-target=\"field\" />\n * </div>\n *\n * `change` and `reconcile` dispatch `{ value: number | null, formatted: string }`\n * — `null` (with an empty `formatted`) when the amount is cleared, so consumers\n * hear every transition of the numeric value, including back to empty. `change`\n * is the user's edit: typing, or the rounding applied on `blur`. `reconcile` is a\n * value the page moved: a `locale`, `currency` or `precision` change that\n * re-rounds the committed amount, a display target swapped in holding another\n * amount, a reconnect that rounds an entry left unrounded mid-typing, or a move\n * that ends a composition before its `compositionend`. Connecting over a\n * server-rendered value reports neither.\n *\n * @remarks\n * Behavior only — no styling, no validation (range/required belong to the\n * consumer or `stimeo--form-field`). The display field is the sole Tab stop and keeps its\n * native text-editing behavior; this controller never steals focus.\n *\n * While typing, the entry is preserved as typed: grouping is applied to the\n * integer digits per locale, a leading sign and a trailing decimal mark stay in\n * place, fraction digits are kept verbatim, and the caret is restored after the\n * same significant character it followed. Negative amounts are in scope. The\n * fixed-precision rounding is applied on `blur`, never mid-entry.\n * Full-width digits, signs, and marks (an IME confirming 0-9/./-) are\n * normalized to their ASCII forms rather than stripped; the locale's own\n * digits (a non-Latin default numbering system such as ar-EG's) are mapped\n * back the same way; and U+2212 MINUS SIGN is read as a sign. An ASCII \".\"\n * only counts as a decimal mark in locales where it is not the grouping\n * separator. Together these keep the controller's own output re-parseable to\n * the same value in every locale. Events fired mid-IME-composition are\n * ignored; the confirmed text is formatted once on `compositionend`. A\n * `locale` / `currency` / `precision` change that arrives mid-composition\n * leaves the uncommitted text alone and applies right after that confirmed\n * text has been read. A composition this controller stops hearing — its display\n * leaves, or the controller disconnects, before `compositionend` — ends there:\n * a display still in place is read as `compositionend` would read it, and a\n * value that moves is reported as `reconcile`. A field or screen-reader span\n * arriving mid-composition takes the committed value.\n *\n * Display text is read with the declarations it was written for. This\n * controller's own rendering was written with the separators in force, so a\n * declaration change reads it before they change. Any other text is the page's\n * — a display swapped in, or text written into the display alongside a\n * declaration change — written for the declarations the page carries, so it is\n * read with those.\n *\n * With no `locale` declared the field formats in the nearest `lang` up the\n * ancestor chain, else in the runtime default. A malformed `locale` falls back\n * to `en-US`, and a malformed `currency` or `precision` to that Value's default,\n * instead of throwing. The declarations, the nearest `lang` among them, are\n * read and validated before a display is read after they may have moved — on a\n * Value change, when the controller connects, and when a display arrives; the\n * hot path only ever sees validated values through cached `Intl.NumberFormat`\n * instances, never built per keystroke. Late-arriving or swapped `field` /\n * `srValue` / `display` targets are re-synced on connection; one that arrives\n * behind the target in charge is re-synced when that target leaves.\n *\n * Reconnecting starts from the committed value: a display still showing this\n * controller's own rendering is not read back but re-rendered from that value\n * under the current declarations, so a `locale` changed while the element was\n * away never re-reads its separators. The re-render is the fixed-precision\n * form, so it rounds whenever the value has more places than the current\n * `precision` allows — because `precision` changed while the element was away,\n * or because the entry was left unrounded mid-typing (`1.555` becomes `1.56`) —\n * and a value it moves is reported as `reconcile`. The composition listeners\n * are released on `disconnect()`.\n *\n * Honest a11y note: a hidden `<input>` is not exposed to assistive tech, so the\n * normalized value is *also* published as text in the `srValue` span referenced\n * by the display's `aria-describedby` — that, not the hidden field, is what a\n * screen reader announces.\n */\nexport class CurrencyInputController extends Controller<HTMLElement> {\n /** Numeric read boundaries share one reader for this controller instance. */\n readonly #numbers = new NumberValueReader();\n\n static override targets = [\"display\", \"field\", \"srValue\"];\n static override values = {\n locale: { type: String, default: \"\" },\n currency: { type: String, default: \"\" },\n precision: { type: Number, default: 2 },\n };\n\n static valueConstraints = {\n precision: { finite: true, integer: true, min: 0, max: 100 },\n } satisfies NumberValueConstraints<typeof CurrencyInputController.values>;\n static actions = [\"format\", \"onInput\"] as const;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly displayTarget: HTMLInputElement;\n declare readonly fieldTarget: HTMLInputElement;\n declare readonly srValueTarget: HTMLElement;\n declare readonly hasDisplayTarget: boolean;\n declare readonly hasFieldTarget: boolean;\n declare readonly hasSrValueTarget: boolean;\n declare localeValue: string;\n declare currencyValue: string;\n declare precisionValue: number;\n\n /** The numeric value last committed; both events report only a move away from it. */\n #lastValue: number | null = null;\n #started = false;\n /** A declaration change that arrived mid-composition, applied once nothing composes. */\n #changeHeld = false;\n /** The display a composition is running on, until that composition ends. */\n #composing: EventTarget | null = null;\n /**\n * The display text this controller last rendered. It tells this controller's own\n * text, written with the separators in force, from text the page wrote.\n */\n #rendered: string | null = null;\n\n /** Validated mirrors of the Values; the hot path never reads a raw Value. */\n #locale: string | undefined;\n #currency = \"\";\n #precision = 2;\n\n /** Formatters rebuilt when the declarations are taken in, never per keystroke. */\n #grouping!: Intl.NumberFormat;\n #fixed!: Intl.NumberFormat;\n #accessible!: Intl.NumberFormat;\n #group = \",\";\n #decimal = \".\";\n /** The locale's non-Latin digits mapped back to ASCII (empty for Latin locales). */\n readonly #digits = new Map<string, string>();\n\n /**\n * Holds mid-composition input so the IME's uncommitted text is never rewritten.\n * The confirmed text is formatted once, and a declaration change the composition\n * held back is applied after it.\n */\n readonly #composition = new CompositionTracker({\n onStart: (event) => {\n this.#composing = event.currentTarget;\n },\n onEnd: () => {\n this.#composing = null;\n this.#reformat(false, \"edit\");\n this.#applyHeldChange();\n },\n });\n\n /**\n * Re-validates on declaration changes and re-renders the committed display,\n * reporting a value the re-render moved as `reconcile`.\n */\n localeValueChanged(): void {\n this.#applyValueChange();\n }\n\n currencyValueChanged(): void {\n this.#applyValueChange();\n }\n\n precisionValueChanged(): void {\n this.#applyValueChange();\n }\n\n /**\n * Reads the display with the declarations its text was written for, then\n * re-renders it under the new ones — so a locale switch re-interprets the\n * value, never the old text with new separators, and text the page wrote for\n * the declarations it changes is never read with the old ones.\n *\n * While the display is composing, its text is the IME's: the change is held,\n * configuration and all, until the composition ends, so the confirmed text is\n * read with the separators it was typed against before the change applies.\n *\n * @stimeoRenderRoot\n */\n #applyValueChange(): void {\n if (this.#composition.isComposing()) {\n this.#changeHeld = true;\n return;\n }\n // With nothing to read, the next display or the next connect takes the\n // declarations in before reading.\n if (!this.#started || !this.hasDisplayTarget) return;\n const scan = this.#readDisplay();\n if (document.activeElement === this.displayTarget) {\n const formatted = this.#render(scan.parts);\n this.#show(formatted);\n this.#reflect(scan.value, formatted, \"reconcile\");\n } else {\n this.#renderFixed(scan.value, \"reconcile\");\n }\n }\n\n /** Applies a declaration change a composition held back. */\n #applyHeldChange(): void {\n if (!this.#changeHeld) return;\n this.#changeHeld = false;\n this.#applyValueChange();\n }\n\n /**\n * Reads the display and takes in the declarations the page carries now. This\n * controller's own rendering was written with the separators in force, so it\n * is read before they change; any other text is the page's, written for the\n * declarations it carries, so it is read after.\n */\n #readDisplay(): Scan {\n const text = this.displayTarget.value;\n const own = text === this.#rendered ? this.#scan(text) : null;\n this.#takeInDeclarations();\n return own ?? this.#scan(text);\n }\n\n /** Takes in the declarations the page carries now, a change a composition held among them. */\n #takeInDeclarations(): void {\n this.#changeHeld = false;\n this.#revalidate();\n }\n\n readonly #morph = new MorphRenderWatcher(() => this.#applyValueChange());\n\n /**\n * Takes in the declarations the page carries now and normalizes the display\n * to its fixed-precision form.\n *\n * A display still showing this controller's own last rendering is not read\n * back: its separators may belong to declarations that changed while the\n * controller was away, and the committed value is known anyway. That value is\n * re-rendered at the current fixed precision, which rounds it whether\n * `precision` changed meanwhile or the entry was left unrounded mid-typing, and\n * a move the rounding causes is reported as `reconcile`. Any other text is the\n * page's, written for the declarations it carries, so it is read with them.\n */\n override connect(): void {\n this.#morph.observe(this.element);\n this.#started = true;\n this.#takeInDeclarations();\n if (!this.hasDisplayTarget) return;\n if (this.displayTarget.value === this.#rendered) {\n this.#renderFixed(this.#lastValue, \"reconcile\");\n return;\n }\n // Seed the baseline with the *rounded* initial value: the idempotent\n // connect-time reformat describes the value the page rendered, so it\n // reports nothing.\n const { value } = this.#scan(this.displayTarget.value);\n this.#lastValue = value === null ? null : round(value, this.#precision);\n this.#renderFixed(value, \"reconcile\");\n }\n\n /**\n * Releases the composition listeners. A composition still running hears no\n * `compositionend` once they are gone, so it ends here; a change it held is\n * taken in on the next `connect()`.\n */\n override disconnect(): void {\n this.#morph.disconnect();\n this.#endUntrackedComposition();\n this.#composition.disconnect();\n this.#started = false;\n }\n\n /**\n * Tracks composition on an arriving (or swapped-in) display and normalizes it\n * under the declarations the page carries now, reading this controller's own\n * rendering with the separators it was written under; an amount that differs\n * from the committed one is the page's, so it is reported as `reconcile`.\n * A display that arrives behind the one in charge is only tracked: the one\n * ahead may be composing against the declarations in force, and the arrival\n * is read when that one leaves.\n */\n displayTargetConnected(target: HTMLInputElement): void {\n this.#composition.observe(target);\n if (!this.#started || !this.hasDisplayTarget || this.displayTarget !== target) return;\n this.#renderFixed(this.#readDisplay().value, \"reconcile\");\n }\n\n /**\n * Stops tracking a display that leaves. A composition running on it hears no\n * `compositionend` any more, so it ends here; a change it held waits for the\n * next display to be read. A composition running on another display still hears\n * its own `compositionend`, so its text is left to it. A display that stays is\n * read again as a declaration change reads it, so an amount it holds that\n * differs from the committed one is the page's and is reported as `reconcile`.\n */\n displayTargetDisconnected(target: HTMLInputElement): void {\n this.#composition.unobserve(target);\n if (target === this.#composing) this.#endUntrackedComposition();\n this.#applyValueChange();\n }\n\n /**\n * Ends a composition no `compositionend` will reach. A display still in place —\n * one a move re-inserted, or the display of a controller that moves — holds the\n * text the composition left, typed against the declarations in force, so it is\n * read as `compositionend` would read it and becomes this controller's own\n * rendering. The page's move ended the composition, so a value it moves is\n * reported as `reconcile`. A display that left takes its composition along.\n */\n #endUntrackedComposition(): void {\n const display = this.#composing;\n this.#composing = null;\n if (this.hasDisplayTarget && this.displayTarget === display) {\n this.#reformat(false, \"reconcile\");\n }\n }\n\n /** Syncs a late-arriving hidden field without touching the display or events. */\n fieldTargetConnected(): void {\n if (this.#started) this.#resync();\n }\n\n /** Syncs the hidden field that stays when an earlier one leaves, silently. */\n fieldTargetDisconnected(): void {\n if (this.#started) this.#resync();\n }\n\n /** Syncs a late-arriving screen-reader span the same way. */\n srValueTargetConnected(): void {\n if (this.#started) this.#resync();\n }\n\n /** Syncs the screen-reader span that stays when an earlier one leaves, silently. */\n srValueTargetDisconnected(): void {\n if (this.#started) this.#resync();\n }\n\n /** Re-groups digits as the user types, preserving the caret position. */\n onInput(event: Event): void {\n if (this.#composition.isComposing(event as InputEvent)) return;\n this.#reformat(false, \"edit\");\n }\n\n /** Applies the fixed-precision rounding on blur. */\n format(): void {\n this.#reformat(true, \"edit\");\n }\n\n /**\n * Parses the display value, rewrites it grouped (optionally at fixed\n * precision), keeps the caret stable by significant characters, and syncs the\n * field, the screen-reader span, and the event `cause` selects.\n */\n #reformat(fixedPrecision: boolean, cause: Cause): void {\n if (!this.hasDisplayTarget) return;\n const raw = this.displayTarget.value;\n const { parts, value } = this.#scan(raw);\n\n if (fixedPrecision) {\n // Blur with no digits (an abandoned sign or dot) clears the entry.\n this.#renderFixed(value, cause);\n return;\n }\n\n const formatted = this.#render(parts);\n if (formatted !== raw) {\n const caret = this.displayTarget.selectionStart;\n const anchor = caret === null ? null : this.#significantBefore(raw, caret);\n this.displayTarget.value = formatted;\n if (anchor !== null) this.#restoreCaret(formatted, anchor);\n }\n this.#rendered = formatted;\n this.#reflect(value, formatted, cause);\n }\n\n /**\n * Shows `value` at the fixed precision — an empty display for no value — and\n * reports a move under the event `cause` selects.\n */\n #renderFixed(value: number | null, cause: Cause): void {\n if (value === null) {\n this.#show(\"\");\n this.#reflect(null, \"\", cause);\n return;\n }\n const rounded = round(value, this.#precision);\n const formatted = this.#fixed.format(rounded);\n this.#show(formatted);\n this.#reflect(rounded, formatted, cause);\n }\n\n /** Writes `text` to the display as this controller's own rendering. */\n #show(text: string): void {\n if (this.displayTarget.value !== text) this.displayTarget.value = text;\n this.#rendered = text;\n }\n\n /**\n * The in-progress rendering: grouped integer, sign and fraction as typed.\n */\n #render(parts: EntryParts): string {\n const int = parts.int === \"\" ? \"\" : this.#grouping.format(BigInt(parts.int));\n const frac = parts.hasDot ? this.#decimal + parts.frac : \"\";\n return parts.sign + int + frac;\n }\n\n /** Restores the caret to sit just after the n-th significant character. */\n #restoreCaret(formatted: string, significantBefore: number): void {\n let seen = 0;\n let position = formatted.length;\n for (let i = 0; i < formatted.length; i++) {\n if (seen >= significantBefore) {\n position = i;\n break;\n }\n if (this.#isSignificant(formatted[i] as string)) seen += 1;\n }\n try {\n this.displayTarget.setSelectionRange(position, position);\n } catch {\n // Some hosts disallow selection on certain input states; the value is\n // already correct, so a failed caret restore is non-fatal.\n }\n }\n\n /**\n * Counts the characters before `caret` that survive into the rendering,\n * applying the same acceptance rules as {@link #scan} — a rejected keystroke\n * (a mid-string sign, a second decimal mark) must not shift the anchor.\n */\n #significantBefore(text: string, caret: number): number {\n let count = 0;\n let sawSign = false;\n let sawDigit = false;\n let sawDot = false;\n for (const ch of this.#normalize(text.slice(0, caret))) {\n if (ch >= \"0\" && ch <= \"9\") {\n count += 1;\n sawDigit = true;\n } else if ((ch === \"-\" || ch === \"+\") && !sawSign && !sawDigit && !sawDot) {\n count += 1;\n sawSign = true;\n } else if (this.#isDecimalMark(ch) && !sawDot) {\n count += 1;\n sawDot = true;\n }\n }\n return count;\n }\n\n /** Digits, signs, and the decimal mark anchor the caret; grouping does not. */\n #isSignificant(ch: string): boolean {\n if (ch >= \"0\" && ch <= \"9\") return true;\n if (ch === \"-\" || ch === \"+\") return true;\n return ch === this.#decimal || (ch === \".\" && this.#group !== \".\");\n }\n\n /** Writes the normalized value to the field, the SR span, and the empty hook. */\n #write(value: number | null): void {\n const isEmpty = value === null;\n if (this.hasFieldTarget) this.fieldTarget.value = isEmpty ? \"\" : String(value);\n if (this.hasSrValueTarget) {\n this.srValueTarget.textContent = isEmpty ? \"\" : this.#accessible.format(value);\n }\n this.element.toggleAttribute(`data-${this.identifier}-empty`, isEmpty);\n }\n\n /**\n * {@link #write}, then reports a moved value under the event `cause` selects:\n * `change` for the user's edit, `reconcile` for a move the page caused. The\n * display may hold an in-progress `-`, but a `null` value always rides with an\n * empty `formatted`, whichever event reports it, so consumers can treat the\n * pair as cleared.\n */\n #reflect(value: number | null, formatted: string, cause: Cause): void {\n this.#write(value);\n if (value === this.#lastValue) return;\n this.#lastValue = value;\n const detail = { value, formatted: value === null ? \"\" : formatted };\n if (cause === \"edit\") this.dispatch(\"change\", { detail });\n else this.dispatch(\"reconcile\", { detail });\n }\n\n /**\n * Scans arbitrary input text into its number-shaped parts and value. Keeps\n * digits, one leading sign, one decimal mark, and the fraction verbatim;\n * everything else (grouping, symbols, words) is dropped. An ASCII \".\" is only\n * a decimal mark where it is not the locale's grouping separator. Precision\n * plays no part here — rounding belongs to the blur-time format.\n */\n #scan(text: string): Scan {\n let sign: EntryParts[\"sign\"] = \"\";\n let int = \"\";\n let hasDot = false;\n let frac = \"\";\n for (const ch of this.#normalize(text)) {\n if (ch >= \"0\" && ch <= \"9\") {\n if (hasDot) frac += ch;\n else int += ch;\n } else if ((ch === \"-\" || ch === \"+\") && sign === \"\" && int === \"\" && !hasDot) {\n sign = ch;\n } else if (this.#isDecimalMark(ch) && !hasDot) {\n hasDot = true;\n }\n }\n const parts: EntryParts = { sign, int, hasDot, frac };\n // `Number` accepts \"12.\" and \".5\" alike, so one dotted form covers every\n // shape — and a digit-less entry (\"\", \"-\", \".\") reads as NaN, hence null.\n const value = Number(`${sign}${int}.${frac}`);\n return { parts, value: Number.isFinite(value) ? value : null };\n }\n\n /** Whether `ch` reads as this locale's decimal mark. */\n #isDecimalMark(ch: string): boolean {\n return ch === this.#decimal || (ch === \".\" && this.#group !== \".\");\n }\n\n /**\n * Re-syncs field / srValue / hook without dispatching: from the display, or —\n * while it is composing, when its text is not committed yet — from the value\n * last committed.\n */\n #resync(): void {\n if (!this.hasDisplayTarget) return;\n const value = this.#composition.isComposing()\n ? this.#lastValue\n : this.#scan(this.displayTarget.value).value;\n this.#write(value);\n }\n\n /**\n * Validates the declared Values, falling back to each Value's default when a\n * declaration cannot be interpreted (a malformed locale or currency tag, a\n * precision outside `Intl`'s 0–100 integer range), and rebuilds the cached\n * formatters from the validated set.\n */\n #revalidate(): void {\n const resolved = resolveLocale(this.element, this.localeValue);\n const usable = intlFormatter(Intl.NumberFormat, resolved, {});\n this.#locale = usable === null ? FALLBACK_LOCALE : resolved;\n\n this.#precision = this.#safePrecision;\n\n this.#currency = \"\";\n if (this.currencyValue !== \"\") {\n const declaredCurrency = intlFormatter(Intl.NumberFormat, this.#locale, {\n style: \"currency\",\n currency: this.currencyValue,\n });\n // An unknown code falls through to the plain-number accessible text.\n if (declaredCurrency !== null) this.#currency = this.currencyValue;\n }\n\n this.#grouping = intlFormatter(\n Intl.NumberFormat,\n this.#locale,\n { useGrouping: true, maximumFractionDigits: 0 },\n FALLBACK_LOCALE,\n );\n this.#fixed = intlFormatter(\n Intl.NumberFormat,\n this.#locale,\n {\n useGrouping: true,\n minimumFractionDigits: this.#precision,\n maximumFractionDigits: this.#precision,\n },\n FALLBACK_LOCALE,\n );\n this.#accessible = this.#currency\n ? intlFormatter(\n Intl.NumberFormat,\n this.#locale,\n { style: \"currency\", currency: this.#currency },\n FALLBACK_LOCALE,\n )\n : this.#fixed;\n\n const parts = intlFormatter(Intl.NumberFormat, this.#locale, {}, FALLBACK_LOCALE).formatToParts(\n 11111.1,\n );\n this.#group = parts.find((p) => p.type === \"group\")?.value ?? \",\";\n this.#decimal = parts.find((p) => p.type === \"decimal\")?.value ?? \".\";\n\n // Locales whose default numbering system is not Latin (ar-EG, fa-IR, …)\n // format with their own digits; mapping them back keeps the controller's\n // own output re-parseable to the same value.\n this.#digits.clear();\n const digitFormatter = intlFormatter(\n Intl.NumberFormat,\n this.#locale,\n { useGrouping: false },\n FALLBACK_LOCALE,\n );\n for (let i = 0; i <= 9; i++) {\n const digit = digitFormatter.format(i);\n if (digit !== String(i)) this.#digits.set(digit, String(i));\n }\n }\n\n /**\n * Maps the locale's own digits to ASCII, folds full-width forms (the digits,\n * signs, and marks an IME confirms as 0-9+-.,) through the shared\n * half-width mapping, and reads U+2212 MINUS SIGN as \"-\", which some locales'\n * formatted output uses for negatives.\n */\n #normalize(text: string): string {\n let out = \"\";\n for (const ch of text) {\n const mapped = this.#digits.get(ch);\n if (mapped !== undefined) {\n out += mapped;\n } else if (ch === \"−\") {\n out += \"-\";\n } else {\n out += halfWidthChar(ch);\n }\n }\n return out;\n }\n /** Current `precision` declaration resolved against its numeric contract. */\n get #safePrecision(): number {\n return this.#numbers.read(\n this,\n \"precision\",\n this.precisionValue,\n CurrencyInputController.values.precision.default,\n CurrencyInputController.valueConstraints.precision,\n );\n }\n}\n\n/** Rounds `value` to `precision` decimal places, avoiding `-0`; overflow keeps `value`. */\nfunction round(value: number, precision: number): number {\n const factor = 10 ** Math.max(0, precision);\n const rounded = Math.round(value * factor) / factor;\n if (!Number.isFinite(rounded)) return value;\n return rounded === 0 ? 0 : rounded;\n}\n"]}
@@ -51,6 +51,15 @@ import { Controller } from '@hotwired/stimulus';
51
51
  * on a replacement container, on row churn, and whenever `selection`, `name` or
52
52
  * `form` changes; a selection the page moved is reported by `reconcile` alone.
53
53
  *
54
+ * User `selectionchange` reports compare the resulting state with the last published
55
+ * state. A pending page write handled in the same script joins that confirmation;
56
+ * a browser-delivered listener may settle it first as `reconcile`. Confirming
57
+ * the last published state reports nothing.
58
+ *
59
+ * A synchronous subscriber that confirms another state replaces reports still
60
+ * pending for the outer confirmation. Reading state or confirming it unchanged
61
+ * does not replace them. An event already being dispatched cannot be recalled.
62
+ *
54
63
  * @remarks
55
64
  * Behavior only — the consumer performs the actual data sort/render in response to
56
65
  * the `sort` event and owns all styling. While connected a `MutationObserver`
@@ -130,6 +139,8 @@ declare class DataGridController extends Controller<HTMLElement> {
130
139
  formValueChanged(): void;
131
140
  /** Seeds a fields container inserted after connect from the current selection. */
132
141
  fieldsTargetConnected(): void;
142
+ /** Brings the fields container that stays to the current selection when an earlier one leaves. */
143
+ fieldsTargetDisconnected(): void;
133
144
  /** Re-establishes the baselines for a row added after connect. */
134
145
  rowTargetConnected(): void;
135
146
  /** Settles the selection again when a row leaves the grid or drops its target token. */
@@ -142,10 +153,10 @@ declare class DataGridController extends Controller<HTMLElement> {
142
153
  columnHeaderTargetConnected(): void;
143
154
  /** Re-establishes the tab stop when a header leaves the grid. */
144
155
  columnHeaderTargetDisconnected(): void;
145
- /** Cycles the activated column header's sort and emits `sort`. */
146
- sort(event: Event): void;
147
- /** Toggles selection of the row owning the event target. Bound optionally. */
148
- toggleSelect(event: Event): void;
156
+ /** Cycles an owned column header's sort from an event, the header, or its descendant. */
157
+ sort(source: Event | HTMLElement): void;
158
+ /** Toggles an owned row from an action event, the row, or its descendant. */
159
+ toggleSelect(source: Event | HTMLElement): void;
149
160
  /** Grid navigation + sort/select activation. Bound to cells and headers. */
150
161
  onKeydown(event: KeyboardEvent): void;
151
162
  }