stimeo-ui 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. package/CHANGELOG.md +209 -0
  2. package/README.md +128 -1
  3. package/dist/cable/index.d.ts +79 -23
  4. package/dist/cable/index.js +392 -417
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/controllers/accordion_controller.d.ts +34 -5
  7. package/dist/controllers/accordion_controller.js +228 -28
  8. package/dist/controllers/accordion_controller.js.map +1 -1
  9. package/dist/controllers/alert_dialog_controller.d.ts +20 -9
  10. package/dist/controllers/alert_dialog_controller.js +862 -221
  11. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  12. package/dist/controllers/announcer_controller.d.ts +38 -7
  13. package/dist/controllers/announcer_controller.js +135 -191
  14. package/dist/controllers/announcer_controller.js.map +1 -1
  15. package/dist/controllers/aspect_ratio_controller.js +0 -10
  16. package/dist/controllers/aspect_ratio_controller.js.map +1 -1
  17. package/dist/controllers/auto_submit_controller.d.ts +30 -6
  18. package/dist/controllers/auto_submit_controller.js +295 -110
  19. package/dist/controllers/auto_submit_controller.js.map +1 -1
  20. package/dist/controllers/avatar_controller.js +172 -106
  21. package/dist/controllers/avatar_controller.js.map +1 -1
  22. package/dist/controllers/breadcrumb_controller.d.ts +10 -7
  23. package/dist/controllers/breadcrumb_controller.js +0 -129
  24. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  25. package/dist/controllers/bulk_select_controller.d.ts +22 -4
  26. package/dist/controllers/bulk_select_controller.js +264 -53
  27. package/dist/controllers/bulk_select_controller.js.map +1 -1
  28. package/dist/controllers/calendar_controller.d.ts +109 -28
  29. package/dist/controllers/calendar_controller.js +346 -180
  30. package/dist/controllers/calendar_controller.js.map +1 -1
  31. package/dist/controllers/carousel_controller.d.ts +99 -27
  32. package/dist/controllers/carousel_controller.js +587 -300
  33. package/dist/controllers/carousel_controller.js.map +1 -1
  34. package/dist/controllers/character_counter_controller.d.ts +18 -2
  35. package/dist/controllers/character_counter_controller.js +271 -143
  36. package/dist/controllers/character_counter_controller.js.map +1 -1
  37. package/dist/controllers/checkbox_controller.d.ts +7 -2
  38. package/dist/controllers/checkbox_controller.js +77 -75
  39. package/dist/controllers/checkbox_controller.js.map +1 -1
  40. package/dist/controllers/clipboard_controller.d.ts +44 -7
  41. package/dist/controllers/clipboard_controller.js +187 -108
  42. package/dist/controllers/clipboard_controller.js.map +1 -1
  43. package/dist/controllers/collapsible_controller.d.ts +41 -5
  44. package/dist/controllers/collapsible_controller.js +374 -108
  45. package/dist/controllers/collapsible_controller.js.map +1 -1
  46. package/dist/controllers/color_picker_controller.d.ts +47 -14
  47. package/dist/controllers/color_picker_controller.js +183 -127
  48. package/dist/controllers/color_picker_controller.js.map +1 -1
  49. package/dist/controllers/combobox_controller.d.ts +33 -6
  50. package/dist/controllers/combobox_controller.js +426 -109
  51. package/dist/controllers/combobox_controller.js.map +1 -1
  52. package/dist/controllers/command_palette_controller.d.ts +45 -14
  53. package/dist/controllers/command_palette_controller.js +994 -350
  54. package/dist/controllers/command_palette_controller.js.map +1 -1
  55. package/dist/controllers/conditional_fields_controller.d.ts +15 -2
  56. package/dist/controllers/conditional_fields_controller.js +212 -125
  57. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  58. package/dist/controllers/confirm_controller.d.ts +49 -12
  59. package/dist/controllers/confirm_controller.js +939 -245
  60. package/dist/controllers/confirm_controller.js.map +1 -1
  61. package/dist/controllers/context_menu_controller.d.ts +36 -3
  62. package/dist/controllers/context_menu_controller.js +275 -127
  63. package/dist/controllers/context_menu_controller.js.map +1 -1
  64. package/dist/controllers/count_up_controller.d.ts +13 -1
  65. package/dist/controllers/count_up_controller.js +73 -21
  66. package/dist/controllers/count_up_controller.js.map +1 -1
  67. package/dist/controllers/countdown_controller.d.ts +75 -2
  68. package/dist/controllers/countdown_controller.js +235 -97
  69. package/dist/controllers/countdown_controller.js.map +1 -1
  70. package/dist/controllers/currency_input_controller.d.ts +93 -15
  71. package/dist/controllers/currency_input_controller.js +241 -118
  72. package/dist/controllers/currency_input_controller.js.map +1 -1
  73. package/dist/controllers/data_grid_controller.d.ts +78 -22
  74. package/dist/controllers/data_grid_controller.js +229 -135
  75. package/dist/controllers/data_grid_controller.js.map +1 -1
  76. package/dist/controllers/date_range_picker_controller.d.ts +64 -11
  77. package/dist/controllers/date_range_picker_controller.js +359 -165
  78. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  79. package/dist/controllers/dialog_controller.d.ts +22 -3
  80. package/dist/controllers/dialog_controller.js +887 -225
  81. package/dist/controllers/dialog_controller.js.map +1 -1
  82. package/dist/controllers/direct_upload_controller.d.ts +24 -7
  83. package/dist/controllers/direct_upload_controller.js +80 -142
  84. package/dist/controllers/direct_upload_controller.js.map +1 -1
  85. package/dist/controllers/dirty_form_controller.d.ts +2 -2
  86. package/dist/controllers/dirty_form_controller.js +26 -47
  87. package/dist/controllers/dirty_form_controller.js.map +1 -1
  88. package/dist/controllers/dismissible_controller.d.ts +19 -0
  89. package/dist/controllers/dismissible_controller.js +175 -20
  90. package/dist/controllers/dismissible_controller.js.map +1 -1
  91. package/dist/controllers/drawer_controller.d.ts +52 -16
  92. package/dist/controllers/drawer_controller.js +963 -336
  93. package/dist/controllers/drawer_controller.js.map +1 -1
  94. package/dist/controllers/dropdown_controller.d.ts +39 -3
  95. package/dist/controllers/dropdown_controller.js +342 -85
  96. package/dist/controllers/dropdown_controller.js.map +1 -1
  97. package/dist/controllers/editable_controller.d.ts +12 -1
  98. package/dist/controllers/editable_controller.js +182 -58
  99. package/dist/controllers/editable_controller.js.map +1 -1
  100. package/dist/controllers/empty_state_controller.js +67 -53
  101. package/dist/controllers/empty_state_controller.js.map +1 -1
  102. package/dist/controllers/file_dropzone_controller.d.ts +60 -18
  103. package/dist/controllers/file_dropzone_controller.js +426 -229
  104. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  105. package/dist/controllers/filter_controller.d.ts +10 -4
  106. package/dist/controllers/filter_controller.js +78 -36
  107. package/dist/controllers/filter_controller.js.map +1 -1
  108. package/dist/controllers/flash_controller.d.ts +57 -14
  109. package/dist/controllers/flash_controller.js +328 -211
  110. package/dist/controllers/flash_controller.js.map +1 -1
  111. package/dist/controllers/focus_controller.d.ts +12 -3
  112. package/dist/controllers/focus_controller.js +654 -239
  113. package/dist/controllers/focus_controller.js.map +1 -1
  114. package/dist/controllers/form_field_controller.js +153 -136
  115. package/dist/controllers/form_field_controller.js.map +1 -1
  116. package/dist/controllers/form_validation_controller.js +29 -96
  117. package/dist/controllers/form_validation_controller.js.map +1 -1
  118. package/dist/controllers/frame_loading_controller.d.ts +41 -9
  119. package/dist/controllers/frame_loading_controller.js +263 -198
  120. package/dist/controllers/frame_loading_controller.js.map +1 -1
  121. package/dist/controllers/highlight_controller.d.ts +22 -2
  122. package/dist/controllers/highlight_controller.js +119 -70
  123. package/dist/controllers/highlight_controller.js.map +1 -1
  124. package/dist/controllers/hover_card_controller.d.ts +65 -4
  125. package/dist/controllers/hover_card_controller.js +335 -118
  126. package/dist/controllers/hover_card_controller.js.map +1 -1
  127. package/dist/controllers/idle_controller.d.ts +58 -4
  128. package/dist/controllers/idle_controller.js +316 -65
  129. package/dist/controllers/idle_controller.js.map +1 -1
  130. package/dist/controllers/input_mask_controller.d.ts +5 -2
  131. package/dist/controllers/input_mask_controller.js +116 -61
  132. package/dist/controllers/input_mask_controller.js.map +1 -1
  133. package/dist/controllers/intersection_controller.d.ts +32 -13
  134. package/dist/controllers/intersection_controller.js +147 -103
  135. package/dist/controllers/intersection_controller.js.map +1 -1
  136. package/dist/controllers/lazy_frame_controller.d.ts +16 -0
  137. package/dist/controllers/lazy_frame_controller.js +9 -56
  138. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  139. package/dist/controllers/listbox_controller.d.ts +84 -10
  140. package/dist/controllers/listbox_controller.js +413 -153
  141. package/dist/controllers/listbox_controller.js.map +1 -1
  142. package/dist/controllers/local_time_controller.d.ts +1 -1
  143. package/dist/controllers/local_time_controller.js +54 -64
  144. package/dist/controllers/local_time_controller.js.map +1 -1
  145. package/dist/controllers/masonry_controller.d.ts +11 -3
  146. package/dist/controllers/masonry_controller.js +70 -95
  147. package/dist/controllers/masonry_controller.js.map +1 -1
  148. package/dist/controllers/menu_controller.d.ts +40 -9
  149. package/dist/controllers/menu_controller.js +254 -167
  150. package/dist/controllers/menu_controller.js.map +1 -1
  151. package/dist/controllers/menubar_controller.d.ts +15 -4
  152. package/dist/controllers/menubar_controller.js +206 -331
  153. package/dist/controllers/menubar_controller.js.map +1 -1
  154. package/dist/controllers/meter_controller.d.ts +20 -0
  155. package/dist/controllers/meter_controller.js +159 -71
  156. package/dist/controllers/meter_controller.js.map +1 -1
  157. package/dist/controllers/multi_select_controller.d.ts +50 -7
  158. package/dist/controllers/multi_select_controller.js +797 -388
  159. package/dist/controllers/multi_select_controller.js.map +1 -1
  160. package/dist/controllers/navigation_menu_controller.d.ts +19 -1
  161. package/dist/controllers/navigation_menu_controller.js +156 -231
  162. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  163. package/dist/controllers/nested_form_controller.d.ts +10 -0
  164. package/dist/controllers/nested_form_controller.js +373 -174
  165. package/dist/controllers/nested_form_controller.js.map +1 -1
  166. package/dist/controllers/network_status_controller.d.ts +23 -0
  167. package/dist/controllers/network_status_controller.js +241 -45
  168. package/dist/controllers/network_status_controller.js.map +1 -1
  169. package/dist/controllers/number_input_controller.d.ts +62 -10
  170. package/dist/controllers/number_input_controller.js +387 -227
  171. package/dist/controllers/number_input_controller.js.map +1 -1
  172. package/dist/controllers/optimistic_controller.js +28 -75
  173. package/dist/controllers/optimistic_controller.js.map +1 -1
  174. package/dist/controllers/otp_controller.d.ts +38 -7
  175. package/dist/controllers/otp_controller.js +344 -196
  176. package/dist/controllers/otp_controller.js.map +1 -1
  177. package/dist/controllers/overflow_indicator_controller.d.ts +13 -12
  178. package/dist/controllers/overflow_indicator_controller.js +167 -93
  179. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  180. package/dist/controllers/overflow_menu_controller.d.ts +66 -9
  181. package/dist/controllers/overflow_menu_controller.js +408 -277
  182. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  183. package/dist/controllers/pagination_controller.d.ts +52 -15
  184. package/dist/controllers/pagination_controller.js +342 -120
  185. package/dist/controllers/pagination_controller.js.map +1 -1
  186. package/dist/controllers/password_reveal_controller.d.ts +60 -9
  187. package/dist/controllers/password_reveal_controller.js +424 -99
  188. package/dist/controllers/password_reveal_controller.js.map +1 -1
  189. package/dist/controllers/password_strength_controller.d.ts +14 -5
  190. package/dist/controllers/password_strength_controller.js +99 -153
  191. package/dist/controllers/password_strength_controller.js.map +1 -1
  192. package/dist/controllers/persist_controller.d.ts +11 -4
  193. package/dist/controllers/persist_controller.js +252 -96
  194. package/dist/controllers/persist_controller.js.map +1 -1
  195. package/dist/controllers/pointer_drag_controller.d.ts +19 -7
  196. package/dist/controllers/pointer_drag_controller.js +263 -164
  197. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  198. package/dist/controllers/popover_controller.d.ts +46 -4
  199. package/dist/controllers/popover_controller.js +267 -94
  200. package/dist/controllers/popover_controller.js.map +1 -1
  201. package/dist/controllers/portal_controller.d.ts +44 -4
  202. package/dist/controllers/portal_controller.js +209 -72
  203. package/dist/controllers/portal_controller.js.map +1 -1
  204. package/dist/controllers/preview_guard_controller.d.ts +10 -4
  205. package/dist/controllers/preview_guard_controller.js +243 -112
  206. package/dist/controllers/preview_guard_controller.js.map +1 -1
  207. package/dist/controllers/progress_controller.d.ts +11 -0
  208. package/dist/controllers/progress_controller.js +132 -59
  209. package/dist/controllers/progress_controller.js.map +1 -1
  210. package/dist/controllers/radio_group_controller.d.ts +19 -8
  211. package/dist/controllers/radio_group_controller.js +138 -133
  212. package/dist/controllers/radio_group_controller.js.map +1 -1
  213. package/dist/controllers/range_slider_controller.d.ts +92 -4
  214. package/dist/controllers/range_slider_controller.js +245 -112
  215. package/dist/controllers/range_slider_controller.js.map +1 -1
  216. package/dist/controllers/rating_controller.d.ts +33 -6
  217. package/dist/controllers/rating_controller.js +429 -194
  218. package/dist/controllers/rating_controller.js.map +1 -1
  219. package/dist/controllers/read_more_controller.d.ts +26 -2
  220. package/dist/controllers/read_more_controller.js +185 -47
  221. package/dist/controllers/read_more_controller.js.map +1 -1
  222. package/dist/controllers/reading_progress_controller.d.ts +1 -1
  223. package/dist/controllers/reading_progress_controller.js +147 -135
  224. package/dist/controllers/reading_progress_controller.js.map +1 -1
  225. package/dist/controllers/relative_time_controller.d.ts +18 -4
  226. package/dist/controllers/relative_time_controller.js +145 -110
  227. package/dist/controllers/relative_time_controller.js.map +1 -1
  228. package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
  229. package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +97 -38
  230. package/dist/controllers/reset_on_restore_controller.js.map +1 -0
  231. package/dist/controllers/resizable_controller.d.ts +44 -4
  232. package/dist/controllers/resizable_controller.js +294 -118
  233. package/dist/controllers/resizable_controller.js.map +1 -1
  234. package/dist/controllers/roving_controller.js +39 -84
  235. package/dist/controllers/roving_controller.js.map +1 -1
  236. package/dist/controllers/scroll_area_controller.d.ts +7 -3
  237. package/dist/controllers/scroll_area_controller.js +428 -221
  238. package/dist/controllers/scroll_area_controller.js.map +1 -1
  239. package/dist/controllers/scroll_restore_controller.js +0 -53
  240. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  241. package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
  242. package/dist/controllers/scroll_visibility_controller.js +395 -146
  243. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  244. package/dist/controllers/scrollspy_controller.d.ts +9 -3
  245. package/dist/controllers/scrollspy_controller.js +181 -236
  246. package/dist/controllers/scrollspy_controller.js.map +1 -1
  247. package/dist/controllers/separator_controller.d.ts +59 -17
  248. package/dist/controllers/separator_controller.js +288 -132
  249. package/dist/controllers/separator_controller.js.map +1 -1
  250. package/dist/controllers/sidebar_controller.d.ts +81 -7
  251. package/dist/controllers/sidebar_controller.js +1071 -375
  252. package/dist/controllers/sidebar_controller.js.map +1 -1
  253. package/dist/controllers/skeleton_controller.d.ts +23 -0
  254. package/dist/controllers/skeleton_controller.js +248 -92
  255. package/dist/controllers/skeleton_controller.js.map +1 -1
  256. package/dist/controllers/slider_controller.d.ts +72 -8
  257. package/dist/controllers/slider_controller.js +211 -96
  258. package/dist/controllers/slider_controller.js.map +1 -1
  259. package/dist/controllers/smart_sticky_header_controller.d.ts +21 -3
  260. package/dist/controllers/smart_sticky_header_controller.js +163 -54
  261. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  262. package/dist/controllers/sortable_controller.js +13 -110
  263. package/dist/controllers/sortable_controller.js.map +1 -1
  264. package/dist/controllers/spinner_controller.d.ts +39 -4
  265. package/dist/controllers/spinner_controller.js +277 -161
  266. package/dist/controllers/spinner_controller.js.map +1 -1
  267. package/dist/controllers/step_indicator_controller.d.ts +24 -17
  268. package/dist/controllers/step_indicator_controller.js +107 -53
  269. package/dist/controllers/step_indicator_controller.js.map +1 -1
  270. package/dist/controllers/stepper_controller.d.ts +43 -9
  271. package/dist/controllers/stepper_controller.js +171 -48
  272. package/dist/controllers/stepper_controller.js.map +1 -1
  273. package/dist/controllers/stick_to_bottom_controller.d.ts +25 -0
  274. package/dist/controllers/stick_to_bottom_controller.js +310 -116
  275. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  276. package/dist/controllers/sticky_observer_controller.d.ts +11 -0
  277. package/dist/controllers/sticky_observer_controller.js +214 -49
  278. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  279. package/dist/controllers/submit_once_controller.d.ts +22 -6
  280. package/dist/controllers/submit_once_controller.js +294 -192
  281. package/dist/controllers/submit_once_controller.js.map +1 -1
  282. package/dist/controllers/switch_controller.d.ts +40 -7
  283. package/dist/controllers/switch_controller.js +107 -43
  284. package/dist/controllers/switch_controller.js.map +1 -1
  285. package/dist/controllers/tabs_controller.d.ts +13 -1
  286. package/dist/controllers/tabs_controller.js +50 -25
  287. package/dist/controllers/tabs_controller.js.map +1 -1
  288. package/dist/controllers/tags_input_controller.d.ts +27 -3
  289. package/dist/controllers/tags_input_controller.js +290 -149
  290. package/dist/controllers/tags_input_controller.js.map +1 -1
  291. package/dist/controllers/textarea_autosize_controller.d.ts +10 -0
  292. package/dist/controllers/textarea_autosize_controller.js +71 -58
  293. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  294. package/dist/controllers/theme_controller.d.ts +37 -8
  295. package/dist/controllers/theme_controller.js +148 -80
  296. package/dist/controllers/theme_controller.js.map +1 -1
  297. package/dist/controllers/time_picker_controller.d.ts +18 -1
  298. package/dist/controllers/time_picker_controller.js +162 -81
  299. package/dist/controllers/time_picker_controller.js.map +1 -1
  300. package/dist/controllers/toast_controller.d.ts +85 -23
  301. package/dist/controllers/toast_controller.js +365 -193
  302. package/dist/controllers/toast_controller.js.map +1 -1
  303. package/dist/controllers/toggle_group_controller.d.ts +60 -9
  304. package/dist/controllers/toggle_group_controller.js +194 -99
  305. package/dist/controllers/toggle_group_controller.js.map +1 -1
  306. package/dist/controllers/toolbar_controller.js +92 -90
  307. package/dist/controllers/toolbar_controller.js.map +1 -1
  308. package/dist/controllers/tooltip_controller.d.ts +52 -2
  309. package/dist/controllers/tooltip_controller.js +185 -125
  310. package/dist/controllers/tooltip_controller.js.map +1 -1
  311. package/dist/controllers/transition_controller.d.ts +22 -4
  312. package/dist/controllers/transition_controller.js +123 -115
  313. package/dist/controllers/transition_controller.js.map +1 -1
  314. package/dist/controllers/tree_view_controller.d.ts +59 -18
  315. package/dist/controllers/tree_view_controller.js +248 -290
  316. package/dist/controllers/tree_view_controller.js.map +1 -1
  317. package/dist/index.d.ts +33 -3
  318. package/dist/index.js +8649 -8572
  319. package/dist/index.js.map +1 -1
  320. package/dist/inspector/cli.d.ts +95 -9
  321. package/dist/inspector/cli.js +343 -77
  322. package/dist/inspector/cli.js.map +1 -1
  323. package/dist/inspector/cli_bin.js +390 -96
  324. package/dist/inspector/cli_bin.js.map +1 -1
  325. package/dist/inspector/examples.json +45 -45
  326. package/dist/inspector/manifest.json +1308 -155
  327. package/dist/positioning/index.d.ts +8 -0
  328. package/dist/positioning/index.js +148 -45
  329. package/dist/positioning/index.js.map +1 -1
  330. package/package.json +7 -7
  331. package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
  332. package/dist/controllers/reset_before_cache_controller.js.map +0 -1
@@ -1,55 +1,71 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
3
- // src/controllers/currency_input_controller.ts
4
-
5
- // src/utils/composition_tracker.ts
3
+ var COMPOSITION_INPUT_TYPES = /* @__PURE__ */ new Set([
4
+ "insertCompositionText",
5
+ "insertFromComposition",
6
+ "deleteCompositionText",
7
+ "deleteByComposition"
8
+ ]);
6
9
  var CompositionTracker = class {
7
10
  #observedTargets = /* @__PURE__ */ new Set();
8
11
  #activeTargets = /* @__PURE__ */ new Set();
9
12
  #onStart;
10
13
  #onEnd;
14
+ #confirmedTarget = null;
11
15
  constructor(options = {}) {
12
16
  this.#onStart = options.onStart;
13
17
  this.#onEnd = options.onEnd;
14
18
  }
15
- /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */
16
19
  observe(target) {
17
20
  if (this.#observedTargets.has(target)) return;
18
21
  target.addEventListener("compositionstart", this.#handleStart);
19
22
  target.addEventListener("compositionend", this.#handleEnd);
23
+ target.addEventListener("keydown", this.#handleKeydown);
20
24
  this.#observedTargets.add(target);
21
25
  }
22
- /** Stops tracking one target and clears any active composition it owned. */
23
26
  unobserve(target) {
24
27
  if (!this.#observedTargets.delete(target)) return;
25
28
  target.removeEventListener("compositionstart", this.#handleStart);
26
29
  target.removeEventListener("compositionend", this.#handleEnd);
30
+ target.removeEventListener("keydown", this.#handleKeydown);
27
31
  this.#activeTargets.delete(target);
32
+ if (this.#confirmedTarget === target) this.#confirmedTarget = null;
28
33
  }
29
- /** Releases every listener and clears state so reconnect starts cleanly. */
30
34
  disconnect() {
31
35
  for (const target of this.#observedTargets) {
32
36
  target.removeEventListener("compositionstart", this.#handleStart);
33
37
  target.removeEventListener("compositionend", this.#handleEnd);
38
+ target.removeEventListener("keydown", this.#handleKeydown);
34
39
  }
35
40
  this.#observedTargets.clear();
36
41
  this.#activeTargets.clear();
42
+ this.#confirmedTarget = null;
37
43
  }
38
- /** True when lifecycle tracking or the current event reports composition. */
39
44
  isComposing(event) {
40
45
  return this.#activeTargets.size > 0 || event?.isComposing === true;
41
46
  }
47
+ consumesConfirmedInput(event) {
48
+ const confirmed = this.#confirmedTarget;
49
+ this.#confirmedTarget = null;
50
+ if (confirmed === null || confirmed !== event.target) return false;
51
+ const inputType = event.inputType;
52
+ return !inputType || COMPOSITION_INPUT_TYPES.has(inputType);
53
+ }
42
54
  #handleStart = (event) => {
55
+ this.#confirmedTarget = null;
43
56
  if (event.currentTarget) this.#activeTargets.add(event.currentTarget);
44
57
  this.#onStart?.(event);
45
58
  };
46
59
  #handleEnd = (event) => {
47
60
  if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);
61
+ this.#confirmedTarget = event.target;
48
62
  this.#onEnd?.(event);
49
63
  };
64
+ #handleKeydown = () => {
65
+ this.#confirmedTarget = null;
66
+ };
50
67
  };
51
68
 
52
- // src/utils/half_width.ts
53
69
  var FULL_WIDTH_SHIFT = 65248;
54
70
  function halfWidthChar(char) {
55
71
  if (char >= "\uFF01" && char <= "\uFF5E") {
@@ -58,7 +74,6 @@ function halfWidthChar(char) {
58
74
  return char === "\u3000" ? " " : char;
59
75
  }
60
76
 
61
- // src/utils/intl_format.ts
62
77
  var formatters = /* @__PURE__ */ new WeakMap();
63
78
  function intlFormatter(factory, locale, options, fallbackLocale) {
64
79
  const cache = cacheFor(factory);
@@ -88,42 +103,154 @@ function construct(factory, locale, options, fallbackLocale) {
88
103
  }
89
104
  }
90
105
 
91
- // src/utils/locale.ts
92
106
  function resolveLocale(element, declared = "") {
93
107
  return declared || element.closest("[lang]")?.getAttribute("lang") || void 0;
94
108
  }
95
109
 
96
- // src/controllers/currency_input_controller.ts
110
+ var ListenerSet = class {
111
+ #abort = new AbortController();
112
+ add(target, type, handler, options) {
113
+ target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
114
+ }
115
+ dispose() {
116
+ this.#abort.abort();
117
+ this.#abort = new AbortController();
118
+ }
119
+ };
120
+
121
+ var MicrotaskCoalescer = class {
122
+ #run;
123
+ #queued = false;
124
+ #active = false;
125
+ #generation = 0;
126
+ constructor(run) {
127
+ this.#run = run;
128
+ }
129
+ activate() {
130
+ this.#active = true;
131
+ }
132
+ cancel() {
133
+ this.#active = false;
134
+ this.#queued = false;
135
+ this.#generation += 1;
136
+ }
137
+ schedule() {
138
+ if (!this.#active || this.#queued) return;
139
+ this.#queued = true;
140
+ const generation = this.#generation;
141
+ queueMicrotask(() => {
142
+ if (generation !== this.#generation || !this.#queued || !this.#active) return;
143
+ this.#queued = false;
144
+ this.#run();
145
+ });
146
+ }
147
+ };
148
+
149
+ var MorphRenderWatcher = class {
150
+ #listeners = new ListenerSet();
151
+ #pass;
152
+ #element = null;
153
+ #onMorph = () => this.#pass.schedule();
154
+ constructor(run) {
155
+ this.#pass = new MicrotaskCoalescer(run);
156
+ }
157
+ observe(element) {
158
+ if (this.#element === element) return;
159
+ this.disconnect();
160
+ this.#element = element;
161
+ this.#pass.activate();
162
+ this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
163
+ }
164
+ schedule() {
165
+ this.#pass.schedule();
166
+ }
167
+ disconnect() {
168
+ this.#listeners.dispose();
169
+ this.#pass.cancel();
170
+ this.#element = null;
171
+ }
172
+ };
173
+
174
+ function matchesNumberBounds(value, bounds) {
175
+ if (!Number.isFinite(value)) {
176
+ const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
177
+ if (direction === null) return false;
178
+ if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
179
+ }
180
+ if (bounds.min !== void 0 && value < bounds.min) return false;
181
+ if (bounds.max !== void 0 && value > bounds.max) return false;
182
+ if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
183
+ if (bounds.integer && !Number.isInteger(value)) return false;
184
+ if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
185
+ return true;
186
+ }
187
+
188
+ function readNumber(raw, fallback, bounds) {
189
+ return matchesNumberBounds(raw, bounds) ? raw : fallback;
190
+ }
191
+
192
+ var NumberValueReader = class {
193
+ #lastRejected = /* @__PURE__ */ new Map();
194
+ read(owner, name, raw, fallback, bounds) {
195
+ const resolved = readNumber(raw, fallback, bounds);
196
+ if (matchesNumberBounds(raw, bounds)) {
197
+ this.#lastRejected.delete(name);
198
+ return resolved;
199
+ }
200
+ const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
201
+ const literal = owner.element.getAttribute(attribute);
202
+ if (literal === null) {
203
+ this.#lastRejected.delete(name);
204
+ return resolved;
205
+ }
206
+ if (this.#lastRejected.get(name) !== literal) {
207
+ this.#lastRejected.set(name, literal);
208
+ console.warn(
209
+ `Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
210
+ );
211
+ }
212
+ return resolved;
213
+ }
214
+ };
215
+
97
216
  var FALLBACK_LOCALE = "en-US";
98
- var CurrencyInputController = class extends Controller {
217
+ var CurrencyInputController = class _CurrencyInputController extends Controller {
218
+ #numbers = new NumberValueReader();
99
219
  static targets = ["display", "field", "srValue"];
100
220
  static values = {
101
221
  locale: { type: String, default: "" },
102
222
  currency: { type: String, default: "" },
103
223
  precision: { type: Number, default: 2 }
104
224
  };
225
+ static valueConstraints = {
226
+ precision: { finite: true, integer: true, min: 0, max: 100 }
227
+ };
105
228
  static actions = ["format", "onInput"];
106
- static events = ["change"];
107
- /** Last committed numeric value, to suppress duplicate `change` dispatches. */
229
+ static events = ["change", "reconcile"];
108
230
  #lastValue = null;
109
231
  #started = false;
110
- /** Validated mirrors of the Values; the hot path never reads a raw Value. */
232
+ #changeHeld = false;
233
+ #composing = null;
234
+ #rendered = null;
111
235
  #locale;
112
236
  #currency = "";
113
237
  #precision = 2;
114
- /** Formatters rebuilt only when a Value changes, never per keystroke. */
115
238
  #grouping;
116
239
  #fixed;
117
240
  #accessible;
118
241
  #group = ",";
119
242
  #decimal = ".";
120
- /** The locale's non-Latin digits mapped back to ASCII (empty for Latin locales). */
121
243
  #digits = /* @__PURE__ */ new Map();
122
- /** Holds mid-composition input so the IME's uncommitted text is never rewritten. */
123
244
  #composition = new CompositionTracker({
124
- onEnd: () => this.#reformat(false)
245
+ onStart: (event) => {
246
+ this.#composing = event.currentTarget;
247
+ },
248
+ onEnd: () => {
249
+ this.#composing = null;
250
+ this.#reformat(false, "edit");
251
+ this.#applyHeldChange();
252
+ }
125
253
  });
126
- /** Re-validates on declaration changes and re-renders the committed display. */
127
254
  localeValueChanged() {
128
255
  this.#applyValueChange();
129
256
  }
@@ -133,92 +260,98 @@ var CurrencyInputController = class extends Controller {
133
260
  precisionValueChanged() {
134
261
  this.#applyValueChange();
135
262
  }
136
- /**
137
- * Scans the display under the *outgoing* configuration (its separators wrote
138
- * that text), then revalidates and re-renders under the new one — so a locale
139
- * switch re-interprets the value, never the old text with new separators.
140
- */
141
263
  #applyValueChange() {
142
- const scan = this.#started && this.hasDisplayTarget ? this.#scan(this.displayTarget.value) : null;
143
- this.#revalidate();
144
- if (!scan || !this.hasDisplayTarget) return;
264
+ if (this.#composition.isComposing()) {
265
+ this.#changeHeld = true;
266
+ return;
267
+ }
268
+ if (!this.#started || !this.hasDisplayTarget) return;
269
+ const scan = this.#readDisplay();
145
270
  if (document.activeElement === this.displayTarget) {
146
271
  const formatted = this.#render(scan.parts);
147
- this.displayTarget.value = formatted;
148
- this.#reflect(scan.value, formatted);
149
- } else if (scan.value === null) {
150
- this.displayTarget.value = "";
151
- this.#reflect(null, "");
272
+ this.#show(formatted);
273
+ this.#reflect(scan.value, formatted, "reconcile");
152
274
  } else {
153
- const rounded = round(scan.value, this.#precision);
154
- const formatted = this.#fixed.format(rounded);
155
- this.displayTarget.value = formatted;
156
- this.#reflect(rounded, formatted);
275
+ this.#renderFixed(scan.value, "reconcile");
157
276
  }
158
277
  }
159
- /** Normalizes any pre-filled display value to its fixed-precision form. */
278
+ #applyHeldChange() {
279
+ if (!this.#changeHeld) return;
280
+ this.#changeHeld = false;
281
+ this.#applyValueChange();
282
+ }
283
+ #readDisplay() {
284
+ const text = this.displayTarget.value;
285
+ const own = text === this.#rendered ? this.#scan(text) : null;
286
+ this.#takeInDeclarations();
287
+ return own ?? this.#scan(text);
288
+ }
289
+ #takeInDeclarations() {
290
+ this.#changeHeld = false;
291
+ this.#revalidate();
292
+ }
293
+ #morph = new MorphRenderWatcher(() => this.#applyValueChange());
160
294
  connect() {
295
+ this.#morph.observe(this.element);
161
296
  this.#started = true;
297
+ this.#takeInDeclarations();
162
298
  if (!this.hasDisplayTarget) return;
299
+ if (this.displayTarget.value === this.#rendered) {
300
+ this.#renderFixed(this.#lastValue, "reconcile");
301
+ return;
302
+ }
163
303
  const { value } = this.#scan(this.displayTarget.value);
164
304
  this.#lastValue = value === null ? null : round(value, this.#precision);
165
- if (value === null) {
166
- this.displayTarget.value = "";
167
- this.#reflect(null, "");
168
- } else {
169
- this.#reformat(true);
170
- }
305
+ this.#renderFixed(value, "reconcile");
171
306
  }
172
307
  disconnect() {
173
- this.#started = false;
308
+ this.#morph.disconnect();
309
+ this.#endUntrackedComposition();
174
310
  this.#composition.disconnect();
311
+ this.#started = false;
175
312
  }
176
- /** Tracks composition on an arriving (or swapped-in) display and normalizes it. */
177
313
  displayTargetConnected(target) {
178
314
  this.#composition.observe(target);
179
- if (this.#started) this.#reformat(true);
315
+ if (!this.#started || !this.hasDisplayTarget || this.displayTarget !== target) return;
316
+ this.#renderFixed(this.#readDisplay().value, "reconcile");
180
317
  }
181
318
  displayTargetDisconnected(target) {
182
319
  this.#composition.unobserve(target);
320
+ if (target === this.#composing) this.#endUntrackedComposition();
321
+ this.#applyValueChange();
322
+ }
323
+ #endUntrackedComposition() {
324
+ const display = this.#composing;
325
+ this.#composing = null;
326
+ if (this.hasDisplayTarget && this.displayTarget === display) {
327
+ this.#reformat(false, "reconcile");
328
+ }
183
329
  }
184
- /** Syncs a late-arriving hidden field without touching the display or events. */
185
330
  fieldTargetConnected() {
186
331
  if (this.#started) this.#resync();
187
332
  }
188
- /** Syncs a late-arriving screen-reader span the same way. */
333
+ fieldTargetDisconnected() {
334
+ if (this.#started) this.#resync();
335
+ }
189
336
  srValueTargetConnected() {
190
337
  if (this.#started) this.#resync();
191
338
  }
192
- /** Re-groups digits as the user types, preserving the caret position. */
339
+ srValueTargetDisconnected() {
340
+ if (this.#started) this.#resync();
341
+ }
193
342
  onInput(event) {
194
343
  if (this.#composition.isComposing(event)) return;
195
- this.#reformat(false);
344
+ this.#reformat(false, "edit");
196
345
  }
197
- /** Applies the fixed-precision rounding on blur. */
198
346
  format() {
199
- this.#reformat(true);
200
- }
201
- /**
202
- * Parses the display value, rewrites it grouped (optionally at fixed
203
- * precision), keeps the caret stable by significant characters, and syncs the
204
- * field, the screen-reader span, and the `change` event.
205
- *
206
- * @stimeoRenderRoot
207
- */
208
- #reformat(fixedPrecision) {
347
+ this.#reformat(true, "edit");
348
+ }
349
+ #reformat(fixedPrecision, cause) {
209
350
  if (!this.hasDisplayTarget) return;
210
351
  const raw = this.displayTarget.value;
211
352
  const { parts, value } = this.#scan(raw);
212
353
  if (fixedPrecision) {
213
- if (value === null) {
214
- this.displayTarget.value = "";
215
- this.#reflect(null, "");
216
- return;
217
- }
218
- const rounded = round(value, this.#precision);
219
- const formatted2 = this.#fixed.format(rounded);
220
- this.displayTarget.value = formatted2;
221
- this.#reflect(rounded, formatted2);
354
+ this.#renderFixed(value, cause);
222
355
  return;
223
356
  }
224
357
  const formatted = this.#render(parts);
@@ -228,19 +361,29 @@ var CurrencyInputController = class extends Controller {
228
361
  this.displayTarget.value = formatted;
229
362
  if (anchor !== null) this.#restoreCaret(formatted, anchor);
230
363
  }
231
- this.#reflect(value, value === null ? "" : formatted);
364
+ this.#rendered = formatted;
365
+ this.#reflect(value, formatted, cause);
366
+ }
367
+ #renderFixed(value, cause) {
368
+ if (value === null) {
369
+ this.#show("");
370
+ this.#reflect(null, "", cause);
371
+ return;
372
+ }
373
+ const rounded = round(value, this.#precision);
374
+ const formatted = this.#fixed.format(rounded);
375
+ this.#show(formatted);
376
+ this.#reflect(rounded, formatted, cause);
377
+ }
378
+ #show(text) {
379
+ if (this.displayTarget.value !== text) this.displayTarget.value = text;
380
+ this.#rendered = text;
232
381
  }
233
- /**
234
- * The in-progress rendering: grouped integer, sign and fraction as typed.
235
- *
236
- * @stimeoRenderRoot
237
- */
238
382
  #render(parts) {
239
383
  const int = parts.int === "" ? "" : this.#grouping.format(BigInt(parts.int));
240
384
  const frac = parts.hasDot ? this.#decimal + parts.frac : "";
241
385
  return parts.sign + int + frac;
242
386
  }
243
- /** Restores the caret to sit just after the n-th significant character. */
244
387
  #restoreCaret(formatted, significantBefore) {
245
388
  let seen = 0;
246
389
  let position = formatted.length;
@@ -256,11 +399,6 @@ var CurrencyInputController = class extends Controller {
256
399
  } catch {
257
400
  }
258
401
  }
259
- /**
260
- * Counts the characters before `caret` that survive into the rendering,
261
- * applying the same acceptance rules as {@link #scan} — a rejected keystroke
262
- * (a mid-string sign, a second decimal mark) must not shift the anchor.
263
- */
264
402
  #significantBefore(text, caret) {
265
403
  let count = 0;
266
404
  let sawSign = false;
@@ -280,36 +418,27 @@ var CurrencyInputController = class extends Controller {
280
418
  }
281
419
  return count;
282
420
  }
283
- /** Digits, signs, and the decimal mark anchor the caret; grouping does not. */
284
421
  #isSignificant(ch) {
285
422
  if (ch >= "0" && ch <= "9") return true;
286
423
  if (ch === "-" || ch === "+") return true;
287
424
  return ch === this.#decimal || ch === "." && this.#group !== ".";
288
425
  }
289
- /** Writes the normalized value to the field, the SR span, and the empty hook. */
290
426
  #write(value) {
291
427
  const isEmpty = value === null;
292
428
  if (this.hasFieldTarget) this.fieldTarget.value = isEmpty ? "" : String(value);
293
429
  if (this.hasSrValueTarget) {
294
430
  this.srValueTarget.textContent = isEmpty ? "" : this.#accessible.format(value);
295
431
  }
296
- this.element.toggleAttribute("data-stimeo--currency-input-empty", isEmpty);
432
+ this.element.toggleAttribute(`data-${this.identifier}-empty`, isEmpty);
297
433
  }
298
- /** {@link #write}, then reports a moved value as `change` (`""` rides with `null`). */
299
- #reflect(value, formatted) {
434
+ #reflect(value, formatted, cause) {
300
435
  this.#write(value);
301
- if (value !== this.#lastValue) {
302
- this.#lastValue = value;
303
- this.dispatch("change", { detail: { value, formatted } });
304
- }
436
+ if (value === this.#lastValue) return;
437
+ this.#lastValue = value;
438
+ const detail = { value, formatted: value === null ? "" : formatted };
439
+ if (cause === "edit") this.dispatch("change", { detail });
440
+ else this.dispatch("reconcile", { detail });
305
441
  }
306
- /**
307
- * Scans arbitrary input text into its number-shaped parts and value. Keeps
308
- * digits, one leading sign, one decimal mark, and the fraction verbatim;
309
- * everything else (grouping, symbols, words) is dropped. An ASCII "." is only
310
- * a decimal mark where it is not the locale's grouping separator. Precision
311
- * plays no part here — rounding belongs to the blur-time format.
312
- */
313
442
  #scan(text) {
314
443
  let sign = "";
315
444
  let int = "";
@@ -329,27 +458,19 @@ var CurrencyInputController = class extends Controller {
329
458
  const value = Number(`${sign}${int}.${frac}`);
330
459
  return { parts, value: Number.isFinite(value) ? value : null };
331
460
  }
332
- /** Whether `ch` reads as this locale's decimal mark. */
333
461
  #isDecimalMark(ch) {
334
462
  return ch === this.#decimal || ch === "." && this.#group !== ".";
335
463
  }
336
- /** Re-syncs field / srValue / hook from the current display without dispatching. */
337
464
  #resync() {
338
465
  if (!this.hasDisplayTarget) return;
339
- this.#write(this.#scan(this.displayTarget.value).value);
340
- }
341
- /**
342
- * Validates the declared Values, falling back to each Value's default when a
343
- * declaration cannot be interpreted (a malformed locale or currency tag, a
344
- * precision outside `Intl`'s 0–100 integer range), and rebuilds the cached
345
- * formatters from the validated set.
346
- */
466
+ const value = this.#composition.isComposing() ? this.#lastValue : this.#scan(this.displayTarget.value).value;
467
+ this.#write(value);
468
+ }
347
469
  #revalidate() {
348
470
  const resolved = resolveLocale(this.element, this.localeValue);
349
471
  const usable = intlFormatter(Intl.NumberFormat, resolved, {});
350
472
  this.#locale = usable === null ? FALLBACK_LOCALE : resolved;
351
- const precision = this.precisionValue;
352
- this.#precision = Number.isInteger(precision) && precision >= 0 && precision <= 100 ? precision : 2;
473
+ this.#precision = this.#safePrecision;
353
474
  this.#currency = "";
354
475
  if (this.currencyValue !== "") {
355
476
  const declaredCurrency = intlFormatter(Intl.NumberFormat, this.#locale, {
@@ -397,12 +518,6 @@ var CurrencyInputController = class extends Controller {
397
518
  if (digit !== String(i)) this.#digits.set(digit, String(i));
398
519
  }
399
520
  }
400
- /**
401
- * Maps the locale's own digits to ASCII, folds full-width forms (the digits,
402
- * signs, and marks an IME confirms as 0-9+-.,) through the shared
403
- * half-width mapping, and reads U+2212 MINUS SIGN as "-", which some locales'
404
- * formatted output uses for negatives.
405
- */
406
521
  #normalize(text) {
407
522
  let out = "";
408
523
  for (const ch of text) {
@@ -417,6 +532,15 @@ var CurrencyInputController = class extends Controller {
417
532
  }
418
533
  return out;
419
534
  }
535
+ get #safePrecision() {
536
+ return this.#numbers.read(
537
+ this,
538
+ "precision",
539
+ this.precisionValue,
540
+ _CurrencyInputController.values.precision.default,
541
+ _CurrencyInputController.valueConstraints.precision
542
+ );
543
+ }
420
544
  };
421
545
  function round(value, precision) {
422
546
  const factor = 10 ** Math.max(0, precision);
@@ -426,5 +550,4 @@ function round(value, precision) {
426
550
  }
427
551
 
428
552
  export { CurrencyInputController };
429
- //# sourceMappingURL=currency_input_controller.js.map
430
553
  //# sourceMappingURL=currency_input_controller.js.map