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 +1 @@
1
- {"version":3,"sources":["../../src/utils/logical_scroll.ts","../../src/utils/arrow_step.ts","../../src/utils/microtask_coalescer.ts","../../src/controllers/time_picker_controller.ts"],"names":[],"mappings":"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","file":"time_picker_controller.js","sourcesContent":["/** Normalized scroll position and maximum distance on one logical axis. */\nexport interface LogicalScrollMetrics {\n position: number;\n max: number;\n}\n\n/**\n * Whether horizontal scrolling on `element` follows right-to-left inline flow.\n *\n * Resolved from the **computed** `direction`, so the authoring contract is the\n * usual `dir=\"rtl\"` (or a stylesheet) on the element or any ancestor.\n *\n * Scope: horizontal writing modes. A vertical writing mode (`writing-mode:\n * vertical-rl`) also inverts the horizontal axis, which this check does not\n * model — vertical writing modes are out of scope for the scroll utilities\n * (their consumers describe axes as horizontal/vertical, not inline/block).\n */\nexport function isRtl(element: Element): boolean {\n return window.getComputedStyle(element).direction === \"rtl\";\n}\n\n/**\n * Returns scroll distance from the logical start edge.\n *\n * CSSOM View exposes standards-mode RTL horizontal offsets as `0` at the inline\n * start (right) and increasingly negative values toward the inline end (left).\n * The normalized position is always clamped to `[0, max]`, which also absorbs\n * Safari's elastic overscroll values.\n */\nexport function logicalScrollMetrics(\n element: HTMLElement,\n horizontal: boolean,\n): LogicalScrollMetrics {\n const max = Math.max(\n 0,\n horizontal\n ? element.scrollWidth - element.clientWidth\n : element.scrollHeight - element.clientHeight,\n );\n const raw = horizontal ? element.scrollLeft : element.scrollTop;\n const position = horizontal && isRtl(element) ? -raw : raw;\n return { position: Math.min(max, Math.max(0, position)), max };\n}\n\n/**\n * Converts a logical start/end delta to the physical value accepted by\n * `Element.scrollBy`.\n */\nexport function physicalScrollDelta(\n element: HTMLElement,\n horizontal: boolean,\n logicalDelta: number,\n): number {\n return horizontal && isRtl(element) ? -logicalDelta : logicalDelta;\n}\n","import { isRtl } from \"./logical_scroll\";\n\n/**\n * Turns an arrow key into a **logical** step: `+1` for \"next\", `-1` for\n * \"previous\", `0` when the key names neither.\n *\n * APG defines the horizontal pair as *next / previous* and says a vertical\n * arrangement swaps in Down/Up for the same meaning — so the pair is one axis's\n * spelling of an order, and the order reverses with the writing direction. Only\n * the horizontal pair reverses. Down/Up name an axis the writing direction does\n * not mirror, and returning them unchanged is the point: many controllers fold\n * both pairs into one branch, where swapping the branches under RTL would flip\n * the vertical axis too — a bug that reads as \"the arrows work\" until someone\n * presses Down.\n *\n * **Direction is read from the element the caller passes, which should be the\n * container that lays the items out** — not the focused child. A child may carry\n * its own `dir` (an LTR input inside an RTL form is ordinary authoring), and\n * probing per handler makes two handlers disagree at the boundary between them.\n *\n * This decides direction only. Whether the axis is even active (an\n * `orientation=\"horizontal\"` widget ignoring Down/Up), how far the step lands,\n * and what wrapping does all stay with the caller.\n *\n * **It encodes the list-order convention: `ArrowDown` is *next*.** Widgets that\n * pair the arrows by *value* instead — `ArrowUp` meaning \"more\", as a rating or a\n * slider does — must not use this, or their vertical axis inverts. Reverse the\n * horizontal pair on its own there.\n *\n * @example\n * ```ts\n * const step = logicalArrowStep(event.key, this.element);\n * if (step === 0) return;\n * this.#roving.setActive(rovingMove(current, length, step, \"wrap\"), { focus: true });\n * ```\n */\nexport function logicalArrowStep(key: string, element: Element): 1 | -1 | 0 {\n if (key === \"ArrowDown\") return 1;\n if (key === \"ArrowUp\") return -1;\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return 0;\n const forward = isRtl(element) ? \"ArrowLeft\" : \"ArrowRight\";\n return key === forward ? 1 : -1;\n}\n\n/**\n * Rewrites `key` so an existing LTR-shaped branch keeps working under RTL:\n * `ArrowRight` and `ArrowLeft` trade places, everything else passes through.\n *\n * The alternative — negating a delta — silently breaks handlers whose two\n * horizontal branches are **not mirror images**. A grid that clamps one edge but\n * not the other, or a segmented field guarding `index > 0` on one side and\n * `index < length - 1` on the other, ends up applying the wrong guard to the\n * wrong direction. Swapping the key leaves each branch, guards and all, exactly\n * where its author put it.\n *\n * Same rule as {@link logicalArrowStep} about which element to read: pass the\n * container that lays the items out, not the focused child.\n *\n * @example\n * ```ts\n * switch (logicalArrowKey(event.key, this.element)) {\n * case \"ArrowLeft\": // \"previous\" — whatever direction that is on screen\n * ```\n */\nexport function logicalArrowKey(key: string, element: Element): string {\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return key;\n if (!isRtl(element)) return key;\n return key === \"ArrowRight\" ? \"ArrowLeft\" : \"ArrowRight\";\n}\n\n/** Modifiers a widget may claim on an arrow key, named for the `allow` list. */\nexport type ArrowModifier = \"alt\" | \"ctrl\" | \"meta\" | \"shift\";\n\n/**\n * True when an arrow key arrived carrying a modifier the widget must leave to\n * the browser: return without calling `preventDefault()` and without moving any\n * state.\n *\n * A bare arrow belongs to the widget; a chorded one usually does not.\n * `Alt`/`Meta` plus a horizontal arrow is history back/forward on every desktop\n * browser, and a widget that swallows it makes the shortcut work or not\n * depending on where focus happens to sit — a coin-flip the user cannot see.\n *\n * `allow` is for the combinations APG assigns to a pattern **and the widget\n * actually implements** — today only Combobox's optional `Alt+Down`/`Alt+Up`.\n * Listing one the widget does not implement defeats the point: the chord then\n * runs the plain-arrow branch, which is exactly what this guard exists to stop.\n * Non-arrow keys return `false`, so chorded letters and\n * `Control+Home`/`Control+End` are untouched.\n *\n * @example\n * ```ts\n * if (isReservedArrowChord(event)) return;\n * ```\n */\nexport function isReservedArrowChord(\n event: KeyboardEvent,\n allow: readonly ArrowModifier[] = [],\n): boolean {\n if (!event.key.startsWith(\"Arrow\")) return false;\n return (\n (event.altKey && !allow.includes(\"alt\")) ||\n (event.ctrlKey && !allow.includes(\"ctrl\")) ||\n (event.metaKey && !allow.includes(\"meta\")) ||\n (event.shiftKey && !allow.includes(\"shift\"))\n );\n}\n\n/**\n * True when a press arrived carrying any modifier, for the keys the browser and\n * the OS own outright: return without calling `preventDefault()` and without\n * moving any state.\n *\n * `Control+Home` and `Control+End` jump the document to its ends, and a widget\n * that swallows them makes the shortcut work or not depending on where focus\n * happens to sit. {@link isReservedArrowChord} answers the same question for the\n * arrows, but returns `false` for every other key so that this one can decide.\n *\n * There is no `allow` list here on purpose. APG assigns no modifier chord to\n * `Home`/`End`, so a widget that wanted one would be claiming a combination the\n * pattern never gave it.\n *\n * @example\n * ```ts\n * case \"Home\":\n * case \"End\":\n * if (hasModifierChord(event)) return;\n * ```\n */\nexport function hasModifierChord(event: KeyboardEvent): boolean {\n return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\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 * This file's own doc block is dropped from `dist`, but every member comment is\n * inlined into each consumer entry (`tsup` builds with `splitting: false`), so\n * rationale belongs here and only the contract belongs on the members.\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 { Controller } from \"@hotwired/stimulus\";\nimport { isReservedArrowChord, logicalArrowKey } from \"../utils/arrow_step\";\nimport { MicrotaskCoalescer } from \"../utils/microtask_coalescer\";\n\n/** A time segment kind, as declared by `data-segment` on each spinbutton. */\ntype SegmentKind = \"hour\" | \"minute\" | \"second\" | \"meridiem\";\n\n/** Canonical controller state. Hours are always stored on the 24-hour clock. */\ninterface TimeState {\n hour: number;\n minute: number;\n second: number;\n}\n\n/** Meridiem encoding exposed through the meridiem spinbutton. */\nconst AM = 0;\nconst PM = 1;\nconst SECONDS_PER_MINUTE = 60;\nconst SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;\nconst SECONDS_PER_DAY = 24 * SECONDS_PER_HOUR;\n\n/** Modifier keys that reserve document/browser shortcuts outside the widget. */\nconst hasModifier = (event: KeyboardEvent): boolean =>\n event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\n\n/**\n * Headless, accessible **time picker** behavior. Each segment (hour, minute,\n * optional second, optional AM/PM) is an APG **Spinbutton**; the controller\n * composes them into an `HH:MM[:SS]` value mirrored to an optional hidden field.\n *\n * Markup contract (identifier: `stimeo--time-picker`):\n * <div data-controller=\"stimeo--time-picker\"\n * data-stimeo--time-picker-hour-cycle-value=\"24\"\n * role=\"group\" aria-label=\"Time\">\n * <span role=\"spinbutton\" aria-label=\"Hours\" tabindex=\"0\"\n * aria-valuenow=\"9\" aria-valuemin=\"0\" aria-valuemax=\"23\" aria-valuetext=\"09\"\n * data-segment=\"hour\" data-stimeo--time-picker-target=\"segment\"\n * data-action=\"keydown->stimeo--time-picker#onKeydown\">09</span>\n * <span aria-hidden=\"true\">:</span>\n * <span role=\"spinbutton\" aria-label=\"Minutes\" tabindex=\"0\"\n * data-segment=\"minute\" data-stimeo--time-picker-target=\"segment\"\n * data-action=\"keydown->stimeo--time-picker#onKeydown\">30</span>\n * <input type=\"hidden\" data-stimeo--time-picker-target=\"field\" />\n * </div>\n *\n * `reconcile` dispatches `{ value: string }`.\n *\n * @remarks\n * `segment` targets declare the spinbuttons; the optional `field` target receives\n * the composed form value. `hourCycle` selects 12- or 24-hour presentation\n * (default 24), `step` is the positive integer minute step (default 1), `seconds`\n * includes seconds in the composed value (default false), and `wrap` controls\n * whether stepping crosses segment bounds (default true). The author decides\n * which optional segment targets are present; `seconds` does not create or hide\n * markup.\n *\n * Every segment is its own Tab stop (multi-tabstop, *not* roving), while\n * `ArrowLeft`/`ArrowRight` provide auxiliary movement. `ArrowUp`/`ArrowDown`\n * step the focused spinbutton; wrapping seconds or minutes carries into the next\n * unit, and 12-hour stepping crosses AM/PM at noon and midnight. Typing digits\n * enters a value directly and advances after completion. The digit buffer is\n * discarded on another action, target replacement, or focus departure.\n *\n * A user action that changes the composed value dispatches exactly one bubbling\n * native `change` from the field, when present, and one\n * `stimeo--time-picker:change` with `{ value: string }`. Retained\n * `aria-valuenow`/`data-segment` changes, runtime targets, and\n * `hourCycle`/`seconds` Value changes are reconciled for Turbo morph\n * compatibility; when such a pass moves the composed value — dropping a `second`\n * segment, say — it reports `stimeo--time-picker:reconcile` with the same detail\n * instead, so a consumer can tell its own edit from this controller's repair.\n * Initial connection reports neither.\n */\nexport class TimePickerController extends Controller<HTMLElement> {\n static override targets = [\"segment\", \"field\"];\n static override values = {\n hourCycle: { type: Number, default: 24 },\n step: { type: Number, default: 1 },\n seconds: { type: Boolean, default: false },\n wrap: { type: Boolean, default: true },\n };\n static actions = [\"onKeydown\"] as const;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly segmentTargets: HTMLElement[];\n declare readonly fieldTarget: HTMLInputElement;\n declare readonly hasFieldTarget: boolean;\n declare hourCycleValue: number;\n declare stepValue: number;\n declare secondsValue: boolean;\n declare wrapValue: boolean;\n\n /** Collapses target, Value, and retained-attribute morphs into one silent render. */\n readonly #reconcile = new MicrotaskCoalescer(() => this.#reconcileDom());\n /** Canonical state; the displayed hour and meridiem are derived from this value. */\n #state: TimeState = { hour: 0, minute: 0, second: 0 };\n /** Direct-entry digit buffer and the segment it belongs to. */\n #typeBuffer = \"\";\n #typeSegment: SegmentKind | null = null;\n /** Last composed value, used to suppress duplicate user notifications. */\n #lastValue = \"\";\n #observer: MutationObserver | null = null;\n #connected = false;\n #domDirty = false;\n\n /** Seeds state from the DOM, renders canonical ARIA, and starts morph observation. */\n override connect(): void {\n this.#connected = true;\n this.#reconcile.activate();\n this.element.addEventListener(\"focusout\", this.#onFocusOut);\n this.#domDirty = false;\n this.#adoptDomState();\n this.#render();\n this.#observeMutations();\n }\n\n /** Releases the observer, listener, queued reconciliation, and transient input state. */\n override disconnect(): void {\n this.#connected = false;\n this.#reconcile.cancel();\n this.element.removeEventListener(\"focusout\", this.#onFocusOut);\n this.#observer?.disconnect();\n this.#observer = null;\n this.#domDirty = false;\n this.#clearTypeBuffer();\n this.#lastValue = \"\";\n }\n\n /** Re-renders the canonical instant when 12/24-hour presentation changes at runtime. */\n hourCycleValueChanged(): void {\n this.#reconcile.schedule();\n }\n\n /** Recomposes the optional seconds portion after a runtime Value change. */\n secondsValueChanged(): void {\n this.#reconcile.schedule();\n }\n\n /** Adopts a segment inserted or replaced by a Turbo morph. */\n segmentTargetConnected(): void {\n this.#domDirty = true;\n this.#clearTypeBuffer();\n this.#reconcile.schedule();\n }\n\n /** Rebuilds state after a segment leaves the retained controller element. */\n segmentTargetDisconnected(): void {\n this.#domDirty = true;\n this.#clearTypeBuffer();\n this.#reconcile.schedule();\n }\n\n /** Reflects the current composed value into a field added or replaced at runtime. */\n fieldTargetConnected(): void {\n this.#reconcile.schedule();\n }\n\n /** Reconciles silently when the optional field leaves at runtime. */\n fieldTargetDisconnected(): void {\n this.#reconcile.schedule();\n }\n\n /** Handles APG stepping, inter-segment focus moves, jumps, and direct entry. */\n onKeydown(event: KeyboardEvent): void {\n if (isReservedArrowChord(event)) return;\n const segment = (event.target as HTMLElement | null)?.closest<HTMLElement>(\n \"[data-stimeo--time-picker-target~='segment']\",\n );\n if (!segment || !this.segmentTargets.includes(segment)) return;\n const kind = this.#kindOf(segment);\n if (!kind) return;\n\n const key = logicalArrowKey(event.key, this.element);\n if ((key === \"Home\" || key === \"End\") && hasModifier(event)) return;\n\n switch (key) {\n case \"ArrowUp\":\n event.preventDefault();\n this.#step(kind, this.#delta(kind));\n break;\n case \"ArrowDown\":\n event.preventDefault();\n this.#step(kind, -this.#delta(kind));\n break;\n case \"ArrowLeft\":\n event.preventDefault();\n this.#focusSibling(segment, -1);\n break;\n case \"ArrowRight\":\n event.preventDefault();\n this.#focusSibling(segment, 1);\n break;\n case \"Home\":\n event.preventDefault();\n this.#setDisplayed(kind, this.#bounds(kind).min);\n this.#commitRender();\n break;\n case \"End\":\n event.preventDefault();\n this.#setDisplayed(kind, this.#bounds(kind).max);\n this.#commitRender();\n break;\n default:\n if (kind !== \"meridiem\" && /^[0-9]$/.test(event.key) && !hasModifier(event)) {\n event.preventDefault();\n this.#typeDigit(segment, kind, event.key);\n return;\n }\n return;\n }\n this.#clearTypeBuffer();\n }\n\n /** Clears direct-entry state when Tab, Shift+Tab, or pointer focus leaves a segment. */\n readonly #onFocusOut = (event: FocusEvent): void => {\n const segment = (event.target as HTMLElement | null)?.closest<HTMLElement>(\n \"[data-stimeo--time-picker-target~='segment']\",\n );\n if (!segment || !this.segmentTargets.includes(segment)) return;\n this.#clearTypeBuffer();\n };\n\n /** Uses the normalized positive-integer minute step; other segments step by one. */\n #delta(kind: SegmentKind): number {\n if (kind !== \"minute\") return 1;\n const step = Math.trunc(this.stepValue);\n return Number.isFinite(step) && step > 0 ? step : 1;\n }\n\n /** Mutates one complete action and then renders/notifies its final value once. */\n #step(kind: SegmentKind, delta: number): void {\n if (kind === \"meridiem\" && this.wrapValue) {\n this.#state.hour = modulo(this.#state.hour + 12, 24);\n } else if (this.wrapValue) {\n const scale = kind === \"hour\" ? SECONDS_PER_HOUR : kind === \"minute\" ? SECONDS_PER_MINUTE : 1;\n this.#setFromSeconds(this.#secondsOfDay + delta * scale);\n } else if (kind === \"hour\") {\n // The displayed hour is a projection of the canonical one, so stepping it\n // moves the instant: 11 → 12 crosses noon or midnight even here, where the\n // step never leaves the segment's own bounds. Clamping on the canonical\n // clock is what \"no wrapping\" means — the day is not crossed.\n this.#state.hour = Math.min(23, Math.max(0, this.#state.hour + delta));\n } else {\n const { min, max } = this.#bounds(kind);\n const displayed = this.#displayValue(kind);\n this.#setDisplayed(kind, Math.min(max, Math.max(min, displayed + delta)));\n }\n this.#commitRender();\n }\n\n /** Accumulates a typed digit, rendering once and advancing after completion. */\n #typeDigit(segment: HTMLElement, kind: Exclude<SegmentKind, \"meridiem\">, digit: string): void {\n if (this.#typeSegment !== kind) this.#typeBuffer = \"\";\n this.#typeSegment = kind;\n\n const { max } = this.#bounds(kind);\n const candidate = Number(`${this.#typeBuffer}${digit}`);\n this.#typeBuffer = candidate <= max ? `${this.#typeBuffer}${digit}` : digit;\n\n this.#setDisplayed(kind, Number(this.#typeBuffer));\n this.#commitRender();\n\n if (this.#typeBuffer.length >= 2 || Number(this.#typeBuffer) * 10 > max) {\n this.#clearTypeBuffer();\n this.#focusSibling(segment, 1);\n }\n }\n\n /** Moves focus to the previous/next valid segment, if one exists. */\n #focusSibling(segment: HTMLElement, direction: 1 | -1): void {\n const segments = this.segmentTargets.filter((candidate) => this.#kindOf(candidate) !== null);\n const index = segments.indexOf(segment);\n segments[index + direction]?.focus();\n }\n\n /** Clears the direct-entry buffer and its owning segment together. */\n #clearTypeBuffer(): void {\n this.#typeBuffer = \"\";\n this.#typeSegment = null;\n }\n\n /** Reconciles one coalesced target, Value, or retained-attribute mutation batch. */\n #reconcileDom(): void {\n if (this.#domDirty) {\n this.#domDirty = false;\n this.#clearTypeBuffer();\n this.#adoptDomState();\n }\n this.#render();\n }\n\n /** Rebuilds canonical state from the targets; an absent hour represents midnight. */\n #adoptDomState(): void {\n let displayedHour = 0;\n let meridiem = AM;\n let minute = 0;\n let second = 0;\n\n for (const segment of this.segmentTargets) {\n const kind = this.#kindOf(segment);\n if (!kind) continue;\n const value = this.#authoredValue(segment, kind);\n if (kind === \"hour\") displayedHour = value;\n else if (kind === \"minute\") minute = value;\n else if (kind === \"second\") second = value;\n else meridiem = value;\n }\n\n this.#state = {\n hour:\n this.hourCycleValue === 12\n ? (displayedHour % 12) + (meridiem === PM ? 12 : 0)\n : displayedHour,\n minute,\n second,\n };\n }\n\n /** Reads and integer-clamps one authored `aria-valuenow`. */\n #authoredValue(segment: HTMLElement, kind: SegmentKind): number {\n const raw = Number(segment.getAttribute(\"aria-valuenow\"));\n const { min, max } = this.#bounds(kind);\n if (!Number.isFinite(raw)) return min;\n return Math.min(max, Math.max(min, Math.trunc(raw)));\n }\n\n /** Writes a displayed segment value back into canonical state without rendering. */\n #setDisplayed(kind: SegmentKind, raw: number): void {\n const { min, max } = this.#bounds(kind);\n const value = Math.min(max, Math.max(min, Math.trunc(raw)));\n if (kind === \"hour\") {\n this.#state.hour =\n this.hourCycleValue === 12 ? (value % 12) + (this.#state.hour >= 12 ? 12 : 0) : value;\n } else if (kind === \"minute\" || kind === \"second\") {\n this.#state[kind] = value;\n } else {\n this.#state.hour = (this.#state.hour % 12) + (value === PM ? 12 : 0);\n }\n }\n\n /** Converts seconds with day wrapping into the canonical three-unit state. */\n #setFromSeconds(raw: number): void {\n const seconds = modulo(raw, SECONDS_PER_DAY);\n this.#state.hour = Math.floor(seconds / SECONDS_PER_HOUR);\n this.#state.minute = Math.floor((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);\n this.#state.second = seconds % SECONDS_PER_MINUTE;\n }\n\n /** Reflects canonical state to every segment without dispatching user events. */\n #renderSegments(): void {\n this.#withoutObservation(() => {\n for (const segment of this.segmentTargets) this.#renderSegment(segment);\n });\n }\n\n /**\n * Reflects canonical state during connection or DOM reconciliation.\n *\n * No user edit reaches here, so `change` never fires from this path. A pass\n * that moves the committed value reports `reconcile` instead.\n *\n * @stimeoRenderRoot\n */\n #render(): void {\n this.#renderSegments();\n const value = this.#composedValue;\n const previous = this.#lastValue;\n this.#writeField(value);\n this.#lastValue = value;\n // A reconciliation can move the committed value — dropping a `second`\n // segment recomposes without it, and a `seconds` Value change adds or\n // removes the unit. That is this controller's decision rather than the\n // user's, so it is reported apart from `change`. The empty baseline is the\n // initial connection, which reports nothing.\n if (previous !== \"\" && value !== previous) {\n this.dispatch(\"reconcile\", { detail: { value } });\n }\n }\n\n /** Reflects one completed user action and dispatches its final change exactly once. */\n #commitRender(): void {\n this.#renderSegments();\n const value = this.#composedValue;\n const fieldChanged = this.#writeField(value);\n if (fieldChanged) this.fieldTarget.dispatchEvent(new Event(\"change\", { bubbles: true }));\n if (value !== this.#lastValue) this.dispatch(\"change\", { detail: { value } });\n this.#lastValue = value;\n }\n\n /** Reflects one segment's value and controller-owned ARIA bounds/text. */\n #renderSegment(segment: HTMLElement): void {\n const kind = this.#kindOf(segment);\n if (!kind) return;\n const value = this.#displayValue(kind);\n const text = kind === \"meridiem\" ? (value === PM ? \"PM\" : \"AM\") : pad(value);\n const { min, max } = this.#bounds(kind);\n\n segment.setAttribute(\"aria-valuenow\", String(value));\n segment.setAttribute(\"aria-valuetext\", text);\n segment.setAttribute(\"aria-valuemin\", String(min));\n segment.setAttribute(\"aria-valuemax\", String(max));\n segment.textContent = text;\n }\n\n /** Writes a composed value to the optional form field and reports whether it changed. */\n #writeField(value: string): boolean {\n if (!this.hasFieldTarget || this.fieldTarget.value === value) return false;\n this.fieldTarget.value = value;\n return true;\n }\n\n /** The canonical form value composed as `HH:MM[:SS]`. */\n get #composedValue(): string {\n const parts = [pad(this.#state.hour), pad(this.#state.minute)];\n if (this.secondsValue) parts.push(pad(this.#state.second));\n return parts.join(\":\");\n }\n\n /** Returns a canonical unit in the presentation form exposed by its segment. */\n #displayValue(kind: SegmentKind): number {\n if (kind === \"hour\") {\n return this.hourCycleValue === 12 ? this.#state.hour % 12 || 12 : this.#state.hour;\n }\n if (kind === \"meridiem\") return this.#state.hour >= 12 ? PM : AM;\n return this.#state[kind];\n }\n\n /** The inclusive controller-owned bounds for a segment kind. */\n #bounds(kind: SegmentKind): { min: number; max: number } {\n switch (kind) {\n case \"hour\":\n return this.hourCycleValue === 12 ? { min: 1, max: 12 } : { min: 0, max: 23 };\n case \"minute\":\n case \"second\":\n return { min: 0, max: 59 };\n case \"meridiem\":\n return { min: AM, max: PM };\n }\n }\n\n /** Watches retained segment state while excluding this controller's own reflections. */\n #observeMutations(): void {\n const observer = new MutationObserver((records) => {\n const changed = records.some(\n ({ target }) => target instanceof HTMLElement && this.segmentTargets.includes(target),\n );\n if (!changed) return;\n this.#domDirty = true;\n this.#clearTypeBuffer();\n this.#reconcile.schedule();\n });\n this.#observer = observer;\n this.#observeWith(observer);\n }\n\n /** Registers retained attribute observation on the controller subtree. */\n #observeWith(observer: MutationObserver): void {\n observer.observe(this.element, {\n subtree: true,\n attributes: true,\n attributeFilter: [\"aria-valuenow\", \"data-segment\"],\n });\n }\n\n /** Temporarily pauses observation so derived ARIA writes cannot become DOM input. */\n #withoutObservation(run: () => void): void {\n const observer = this.#observer;\n observer?.disconnect();\n try {\n run();\n } finally {\n if (observer && this.#connected) this.#observeWith(observer);\n }\n }\n\n /** Reads a segment's declared kind, or null when absent/invalid. */\n #kindOf(segment: HTMLElement): SegmentKind | null {\n const kind = segment.getAttribute(\"data-segment\");\n if (kind === \"hour\" || kind === \"minute\" || kind === \"second\" || kind === \"meridiem\") {\n return kind;\n }\n return null;\n }\n\n /** Canonical state as seconds since the start of its nominal day. */\n get #secondsOfDay(): number {\n return (\n this.#state.hour * SECONDS_PER_HOUR +\n this.#state.minute * SECONDS_PER_MINUTE +\n this.#state.second\n );\n }\n}\n\n/** Positive modulo for wrapping values in both keyboard directions. */\nfunction modulo(value: number, modulus: number): number {\n return ((value % modulus) + modulus) % modulus;\n}\n\n/** Zero-pads a number to two digits. */\nfunction pad(value: number): string {\n return String(value).padStart(2, \"0\");\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/logical_scroll.ts","../../src/utils/arrow_step.ts","../../src/utils/field_mirror.ts","../../src/utils/listener_set.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/morph_render_watcher.ts","../../src/utils/move_counter.ts","../../src/utils/number_bounds.ts","../../src/utils/coerce.ts","../../src/utils/number_value.ts","../../src/utils/target_selector.ts","../../src/controllers/time_picker_controller.ts"],"names":[],"mappings":"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","file":"time_picker_controller.js","sourcesContent":["/** Normalized scroll position and maximum distance on one logical axis. */\nexport interface LogicalScrollMetrics {\n position: number;\n max: number;\n}\n\n/**\n * Whether horizontal scrolling on `element` follows right-to-left inline flow.\n *\n * Resolved from the **computed** `direction`, so the authoring contract is the\n * usual `dir=\"rtl\"` (or a stylesheet) on the element or any ancestor.\n *\n * Scope: horizontal writing modes. A vertical writing mode (`writing-mode:\n * vertical-rl`) also inverts the horizontal axis, which this check does not\n * model — vertical writing modes are out of scope for the scroll utilities\n * (their consumers describe axes as horizontal/vertical, not inline/block).\n */\nexport function isRtl(element: Element): boolean {\n return window.getComputedStyle(element).direction === \"rtl\";\n}\n\n/**\n * Returns scroll distance from the logical start edge.\n *\n * CSSOM View exposes standards-mode RTL horizontal offsets as `0` at the inline\n * start (right) and increasingly negative values toward the inline end (left).\n * The normalized position is always clamped to `[0, max]`, which also absorbs\n * Safari's elastic overscroll values.\n */\nexport function logicalScrollMetrics(\n element: HTMLElement,\n horizontal: boolean,\n): LogicalScrollMetrics {\n const max = Math.max(\n 0,\n horizontal\n ? element.scrollWidth - element.clientWidth\n : element.scrollHeight - element.clientHeight,\n );\n const raw = horizontal ? element.scrollLeft : element.scrollTop;\n const position = horizontal && isRtl(element) ? -raw : raw;\n return { position: Math.min(max, Math.max(0, position)), max };\n}\n\n/**\n * Converts a logical start/end delta to the physical value accepted by\n * `Element.scrollBy`.\n */\nexport function physicalScrollDelta(\n element: HTMLElement,\n horizontal: boolean,\n logicalDelta: number,\n): number {\n return horizontal && isRtl(element) ? -logicalDelta : logicalDelta;\n}\n","import { isRtl } from \"./logical_scroll\";\n\n/**\n * Turns an arrow key into a **logical** step: `+1` for \"next\", `-1` for\n * \"previous\", `0` when the key names neither.\n *\n * APG defines the horizontal pair as *next / previous* and says a vertical\n * arrangement swaps in Down/Up for the same meaning — so the pair is one axis's\n * spelling of an order, and the order reverses with the writing direction. Only\n * the horizontal pair reverses. Down/Up name an axis the writing direction does\n * not mirror, and returning them unchanged is the point: many controllers fold\n * both pairs into one branch, where swapping the branches under RTL would flip\n * the vertical axis too — a bug that reads as \"the arrows work\" until someone\n * presses Down.\n *\n * **Direction is read from the element the caller passes, which should be the\n * container that lays the items out** — not the focused child. A child may carry\n * its own `dir` (an LTR input inside an RTL form is ordinary authoring), and\n * probing per handler makes two handlers disagree at the boundary between them.\n *\n * This decides direction only. Whether the axis is even active (an\n * `orientation=\"horizontal\"` widget ignoring Down/Up), how far the step lands,\n * and what wrapping does all stay with the caller.\n *\n * **It encodes the list-order convention: `ArrowDown` is *next*.** Widgets that\n * pair the arrows by *value* instead — `ArrowUp` meaning \"more\", as a rating or a\n * slider does — must not use this, or their vertical axis inverts. Reverse the\n * horizontal pair on its own there.\n *\n * @example\n * ```ts\n * const step = logicalArrowStep(event.key, this.element);\n * if (step === 0) return;\n * this.#roving.setActive(rovingMove(current, length, step, \"wrap\"), { focus: true });\n * ```\n */\nexport function logicalArrowStep(key: string, element: Element): 1 | -1 | 0 {\n if (key === \"ArrowDown\") return 1;\n if (key === \"ArrowUp\") return -1;\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return 0;\n const forward = isRtl(element) ? \"ArrowLeft\" : \"ArrowRight\";\n return key === forward ? 1 : -1;\n}\n\n/**\n * Rewrites `key` so an existing LTR-shaped branch keeps working under RTL:\n * `ArrowRight` and `ArrowLeft` trade places, everything else passes through.\n *\n * The alternative — negating a delta — silently breaks handlers whose two\n * horizontal branches are **not mirror images**. A grid that clamps one edge but\n * not the other, or a segmented field guarding `index > 0` on one side and\n * `index < length - 1` on the other, ends up applying the wrong guard to the\n * wrong direction. Swapping the key leaves each branch, guards and all, exactly\n * where its author put it.\n *\n * Same rule as {@link logicalArrowStep} about which element to read: pass the\n * container that lays the items out, not the focused child.\n *\n * @example\n * ```ts\n * switch (logicalArrowKey(event.key, this.element)) {\n * case \"ArrowLeft\": // \"previous\" — whatever direction that is on screen\n * ```\n */\nexport function logicalArrowKey(key: string, element: Element): string {\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return key;\n if (!isRtl(element)) return key;\n return key === \"ArrowRight\" ? \"ArrowLeft\" : \"ArrowRight\";\n}\n\n/** Modifiers a widget may claim on an arrow key, named for the `allow` list. */\nexport type ArrowModifier = \"alt\" | \"ctrl\" | \"meta\" | \"shift\";\n\n/**\n * True when an arrow key arrived carrying a modifier the widget must leave to\n * the browser: return without calling `preventDefault()` and without moving any\n * state.\n *\n * A bare arrow belongs to the widget; a chorded one usually does not.\n * `Alt`/`Meta` plus a horizontal arrow is history back/forward on every desktop\n * browser, and a widget that swallows it makes the shortcut work or not\n * depending on where focus happens to sit — a coin-flip the user cannot see.\n *\n * `allow` is for the combinations APG assigns to a pattern **and the widget\n * actually implements** — today only Combobox's optional `Alt+Down`/`Alt+Up`.\n * Listing one the widget does not implement defeats the point: the chord then\n * runs the plain-arrow branch, which is exactly what this guard exists to stop.\n * Non-arrow keys return `false`, so chorded letters and\n * `Control+Home`/`Control+End` are untouched.\n *\n * @example\n * ```ts\n * if (isReservedArrowChord(event)) return;\n * ```\n */\nexport function isReservedArrowChord(\n event: KeyboardEvent,\n allow: readonly ArrowModifier[] = [],\n): boolean {\n if (!event.key.startsWith(\"Arrow\")) return false;\n return (\n (event.altKey && !allow.includes(\"alt\")) ||\n (event.ctrlKey && !allow.includes(\"ctrl\")) ||\n (event.metaKey && !allow.includes(\"meta\")) ||\n (event.shiftKey && !allow.includes(\"shift\"))\n );\n}\n\n/**\n * True when a press arrived carrying any modifier, for the keys the browser and\n * the OS own outright: return without calling `preventDefault()` and without\n * moving any state.\n *\n * `Control+Home` and `Control+End` jump the document to its ends, and a widget\n * that swallows them makes the shortcut work or not depending on where focus\n * happens to sit. {@link isReservedArrowChord} answers the same question for the\n * arrows, but returns `false` for every other key so that this one can decide.\n *\n * There is no `allow` list here on purpose. APG assigns no modifier chord to\n * `Home`/`End`, so a widget that wanted one would be claiming a combination the\n * pattern never gave it.\n *\n * @example\n * ```ts\n * case \"Home\":\n * case \"End\":\n * if (hasModifierChord(event)) return;\n * ```\n */\nexport function hasModifierChord(event: KeyboardEvent): boolean {\n return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\n}\n","/**\n * The hidden form fields a widget keeps in step with the state it owns.\n *\n * A widget whose value lives in ARIA attributes submits nothing on its own, so\n * it mirrors that value into `<input type=\"hidden\">` — one field for a single\n * value, a container of generated fields for a set. The mirror is one-way: the\n * widget's own state stays the source of truth and the field is what the form\n * reads.\n *\n * The write and the report are separate calls because they answer to different\n * rules. A mirror is refreshed on connect, after a morph, and whenever the\n * widget repairs itself — none of which a form should treat as an edit. Only\n * the user's own commit reports one, which is why {@link commitField} is never\n * folded into the writes.\n */\n\n/** How a widget's generated fields identify themselves to the form. */\nexport interface GeneratedFieldOptions {\n /** The `name` every generated input submits under. */\n readonly name: string;\n /** The `form` id, for a widget that sits outside the form it submits to. */\n readonly form?: string;\n}\n\n/**\n * Mirrors one value into a hidden field.\n *\n * @returns Whether the field's value moved.\n *\n * @example\n * ```ts\n * if (writeField(this.fieldTarget, String(value)) && userDriven) {\n * commitField(this.fieldTarget);\n * }\n * ```\n */\nexport function writeField(field: HTMLInputElement, value: string): boolean {\n if (field.value === value) return false;\n field.value = value;\n return true;\n}\n\n/**\n * Mirrors a set of values into `container` as generated hidden fields, in the\n * order given.\n *\n * A container that already submits exactly this set is left untouched, children\n * and all — the mirror is refreshed far more often than it moves (every connect,\n * morph and repair), and a rebuild that changes nothing is still a DOM mutation\n * a consumer's observer and a `:empty` rule can see.\n *\n * @returns Whether the submitted set moved — its values, their order, the\n * `name`, or the `form`.\n */\nexport function writeFields(\n container: HTMLElement,\n values: readonly string[],\n { name, form = \"\" }: GeneratedFieldOptions,\n): boolean {\n const current = [...container.children];\n const submits =\n current.length === values.length &&\n current.every(\n (child, index) =>\n child instanceof HTMLInputElement &&\n child.type === \"hidden\" &&\n child.value === values[index] &&\n child.name === name &&\n (child.getAttribute(\"form\") ?? \"\") === form,\n );\n if (submits) return false;\n\n container.replaceChildren(\n ...values.map((value) => {\n const input = document.createElement(\"input\");\n input.type = \"hidden\";\n input.name = name;\n input.value = value;\n if (form !== \"\") input.setAttribute(\"form\", form);\n return input;\n }),\n );\n return true;\n}\n\n/**\n * Reports a committed value from `target` the way a native form control does:\n * one bubbling, non-cancelable `change`.\n *\n * Call it only for a move the user made. Form-level behaviors listen for this —\n * validation re-checks, auto-submit — and a mirror refreshed by a morph or a\n * repair is not something the user submitted.\n *\n * `target` is the element that carries the value: the hidden field for a single\n * mirrored value, the container for a generated set (whose own inputs are\n * replaced on every write), or a widget's own native control where that is what\n * the form reads.\n */\nexport function commitField(target: HTMLElement): void {\n target.dispatchEvent(new Event(\"change\", { bubbles: true }));\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","/**\n * Identifies the latest reported state transition of one owner.\n *\n * Record a transition after its state is written and before invoking external\n * code. Check the returned token before each later report: a synchronous\n * transition made by a listener supersedes reports that have not been sent.\n * Reading state or committing an unchanged state must not advance the counter.\n * Reports stay in the caller so their ordering remains explicit.\n */\nexport class MoveCounter {\n #sequence = 0;\n\n /** Records a state transition and returns its report token. */\n record(): number {\n this.#sequence += 1;\n return this.#sequence;\n }\n\n /** Whether no later state transition has superseded this report token. */\n isLatest(token: number): boolean {\n return token === this.#sequence;\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","/**\n * The attribute selector for one declared target, in a controller's own namespace.\n *\n * Stimulus reads `data-<identifier>-target` as a **space-separated token list**, so a\n * single element can carry several target names at once. Matching the attribute value\n * whole would reach only the elements that declare exactly one name, which is why the\n * name is paired with `~=`.\n *\n * `identifier` is the name the controller is registered under, so the selector reaches\n * the markup that registration renders rather than one fixed spelling.\n */\nexport function targetSelector(identifier: string, name: string): string {\n return `[data-${identifier}-target~=\"${name}\"]`;\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { isReservedArrowChord, logicalArrowKey } from \"../utils/arrow_step\";\nimport { commitField, writeField } from \"../utils/field_mirror\";\nimport { MorphRenderWatcher } from \"../utils/morph_render_watcher\";\nimport { MoveCounter } from \"../utils/move_counter\";\nimport { NUMBER_BOUNDS, type NumberValueConstraints } from \"../utils/number_bounds\";\nimport { NumberValueReader } from \"../utils/number_value\";\nimport { targetSelector } from \"../utils/target_selector\";\n\n/** A time segment kind, as declared by `data-segment` on each spinbutton. */\ntype SegmentKind = \"hour\" | \"minute\" | \"second\" | \"meridiem\";\n\n/** Canonical controller state. Hours are always stored on the 24-hour clock. */\ninterface TimeState {\n hour: number;\n minute: number;\n second: number;\n}\n\n/** Meridiem encoding exposed through the meridiem spinbutton. */\nconst AM = 0;\nconst PM = 1;\nconst SECONDS_PER_MINUTE = 60;\nconst SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;\nconst SECONDS_PER_DAY = 24 * SECONDS_PER_HOUR;\n\n/** Modifier keys that reserve document/browser shortcuts outside the widget. */\nconst hasModifier = (event: KeyboardEvent): boolean =>\n event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\n\n/**\n * Headless, accessible **time picker** behavior. Each segment (hour, minute,\n * optional second, optional AM/PM) is an APG **Spinbutton**; the controller\n * composes them into an `HH:MM[:SS]` value mirrored to an optional hidden field.\n *\n * Markup contract (identifier: `stimeo--time-picker`):\n * <div data-controller=\"stimeo--time-picker\"\n * data-stimeo--time-picker-hour-cycle-value=\"24\"\n * role=\"group\" aria-label=\"Time\">\n * <span role=\"spinbutton\" aria-label=\"Hours\" tabindex=\"0\"\n * aria-valuenow=\"9\" aria-valuemin=\"0\" aria-valuemax=\"23\" aria-valuetext=\"09\"\n * data-segment=\"hour\" data-stimeo--time-picker-target=\"segment\"\n * data-action=\"keydown->stimeo--time-picker#onKeydown\">09</span>\n * <span aria-hidden=\"true\">:</span>\n * <span role=\"spinbutton\" aria-label=\"Minutes\" tabindex=\"0\"\n * data-segment=\"minute\" data-stimeo--time-picker-target=\"segment\"\n * data-action=\"keydown->stimeo--time-picker#onKeydown\">30</span>\n * <input type=\"hidden\" data-stimeo--time-picker-target=\"field\" />\n * </div>\n *\n * `reconcile` dispatches `{ value: string }`.\n *\n * All published state is settled before its reports. A synchronous listener\n * that confirms another value leaves that newer confirmation to report itself;\n * reports still pending for the replaced value are not sent. A read-only listener\n * or a confirmation that moves no published value leaves pending reports intact.\n * An event already being dispatched still reaches its remaining listeners.\n *\n * @remarks\n * `segment` targets declare the spinbuttons; the optional `field` target receives\n * the composed form value. `hourCycle` selects 12- or 24-hour presentation\n * (default 24), `step` is the positive integer minute step (default 1), `seconds`\n * includes seconds in the composed value (default false), and `wrap` controls\n * whether stepping crosses segment bounds (default true). The author decides\n * which optional segment targets are present; `seconds` does not create or hide\n * markup.\n *\n * Every segment is its own Tab stop (multi-tabstop, *not* roving), while\n * `ArrowLeft`/`ArrowRight` provide auxiliary movement. `ArrowUp`/`ArrowDown`\n * step the focused spinbutton; wrapping seconds or minutes carries into the next\n * unit, and 12-hour stepping crosses AM/PM at noon and midnight. Typing digits\n * enters a value directly and advances after completion. The digit buffer is\n * discarded on another action, a segment target change, a page write taken in\n * from a segment, or focus departure.\n *\n * A user action that changes the composed value dispatches exactly one bubbling\n * native `change` from the field, when present, and one\n * `stimeo--time-picker:change` with `{ value: string }`. Retained\n * `aria-valuenow`/`data-segment` changes, runtime targets, and\n * `hourCycle`/`seconds` Value changes are reconciled for Turbo morph\n * compatibility; when such a pass moves the composed value — dropping a `second`\n * segment, say — it reports `stimeo--time-picker:reconcile` with the same detail\n * instead, so a consumer can tell its own edit from this controller's repair.\n * Initial connection reports neither.\n */\nexport class TimePickerController extends Controller<HTMLElement> {\n /** Numeric read boundaries share one reader for this controller instance. */\n readonly #numbers = new NumberValueReader();\n\n readonly #moves = new MoveCounter();\n #move = 0;\n\n static override targets = [\"segment\", \"field\"];\n static override values = {\n hourCycle: { type: Number, default: 24 },\n step: { type: Number, default: 1 },\n seconds: { type: Boolean, default: false },\n wrap: { type: Boolean, default: true },\n };\n\n static valueConstraints = {\n hourCycle: { finite: true, allowedValues: [12, 24] },\n step: NUMBER_BOUNDS.positive,\n } satisfies NumberValueConstraints<typeof TimePickerController.values>;\n static actions = [\"onKeydown\"] as const;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly segmentTargets: HTMLElement[];\n declare readonly fieldTarget: HTMLInputElement;\n declare readonly hasFieldTarget: boolean;\n declare hourCycleValue: number;\n declare stepValue: number;\n declare secondsValue: boolean;\n declare wrapValue: boolean;\n\n /**\n * Collapses target, Value, and retained-attribute morphs into one render that\n * dispatches no `change`.\n */\n readonly #reconcile = new MorphRenderWatcher(() => this.#reconcileDom());\n /** Canonical state; the displayed hour and meridiem are derived from this value. */\n #state: TimeState = { hour: 0, minute: 0, second: 0 };\n /** Direct-entry digit buffer and the segment it belongs to. */\n #typeBuffer = \"\";\n #typeSegment: SegmentKind | null = null;\n /** Last composed value, used to suppress duplicate user notifications. */\n #lastValue = \"\";\n #observer: MutationObserver | null = null;\n #connected = false;\n /**\n * Whether the segments changed since state was last adopted from them. The next\n * adoption also discards the direct-entry buffer, and runs before any key reads it.\n */\n #domDirty = false;\n\n /** Seeds state from the DOM, renders canonical ARIA, and starts morph observation. */\n override connect(): void {\n this.#connected = true;\n this.#reconcile.observe(this.element);\n this.element.addEventListener(\"focusout\", this.#onFocusOut);\n this.#domDirty = false;\n this.#adoptDomState();\n this.#render();\n this.#observeMutations();\n }\n\n /** Releases the observer, listener, queued reconciliation, and transient input state. */\n override disconnect(): void {\n this.#connected = false;\n this.#reconcile.disconnect();\n this.element.removeEventListener(\"focusout\", this.#onFocusOut);\n this.#observer?.disconnect();\n this.#observer = null;\n this.#domDirty = false;\n this.#clearTypeBuffer();\n this.#lastValue = \"\";\n }\n\n /** Re-renders the canonical instant when 12/24-hour presentation changes at runtime. */\n hourCycleValueChanged(): void {\n this.#reconcile.schedule();\n }\n\n /** Recomposes the optional seconds portion after a runtime Value change. */\n secondsValueChanged(): void {\n this.#reconcile.schedule();\n }\n\n /** Adopts a segment inserted or replaced by a Turbo morph. */\n segmentTargetConnected(): void {\n this.#domDirty = true;\n this.#reconcile.schedule();\n }\n\n /** Rebuilds state after a segment leaves the retained controller element. */\n segmentTargetDisconnected(): void {\n this.#domDirty = true;\n this.#reconcile.schedule();\n }\n\n /** Reflects the current composed value into a field added or replaced at runtime. */\n fieldTargetConnected(): void {\n this.#reconcile.schedule();\n }\n\n /** Reconciles silently when the optional field leaves at runtime. */\n fieldTargetDisconnected(): void {\n this.#reconcile.schedule();\n }\n\n /** Handles APG stepping, inter-segment focus moves, jumps, and direct entry. */\n onKeydown(event: KeyboardEvent): void {\n if (isReservedArrowChord(event)) return;\n const segment = (event.target as HTMLElement | null)?.closest<HTMLElement>(\n targetSelector(this.identifier, \"segment\"),\n );\n if (!segment || !this.segmentTargets.includes(segment)) return;\n const kind = this.#kindOf(segment);\n if (!kind) return;\n\n const key = logicalArrowKey(event.key, this.element);\n if ((key === \"Home\" || key === \"End\") && hasModifier(event)) return;\n\n // Taking in the page's writes consumes the records the observer would have\n // answered, so the pass it would have queued is queued here. A key that renders\n // leaves that pass nothing to report.\n if (this.#adoptPendingDom()) this.#reconcile.schedule();\n switch (key) {\n case \"ArrowUp\":\n event.preventDefault();\n this.#step(kind, this.#delta(kind));\n break;\n case \"ArrowDown\":\n event.preventDefault();\n this.#step(kind, -this.#delta(kind));\n break;\n case \"ArrowLeft\":\n event.preventDefault();\n this.#focusSibling(segment, -1);\n break;\n case \"ArrowRight\":\n event.preventDefault();\n this.#focusSibling(segment, 1);\n break;\n case \"Home\":\n event.preventDefault();\n this.#setDisplayed(kind, this.#bounds(kind).min);\n this.#commitRender();\n break;\n case \"End\":\n event.preventDefault();\n this.#setDisplayed(kind, this.#bounds(kind).max);\n this.#commitRender();\n break;\n default:\n if (kind !== \"meridiem\" && /^[0-9]$/.test(event.key) && !hasModifier(event)) {\n event.preventDefault();\n this.#typeDigit(segment, kind, event.key);\n return;\n }\n return;\n }\n this.#clearTypeBuffer();\n }\n\n /** Clears direct-entry state when Tab, Shift+Tab, or pointer focus leaves a segment. */\n readonly #onFocusOut = (event: FocusEvent): void => {\n const segment = (event.target as HTMLElement | null)?.closest<HTMLElement>(\n targetSelector(this.identifier, \"segment\"),\n );\n if (!segment || !this.segmentTargets.includes(segment)) return;\n this.#clearTypeBuffer();\n };\n\n /** Uses the normalized positive-integer minute step; other segments step by one. */\n #delta(kind: SegmentKind): number {\n if (kind !== \"minute\") return 1;\n const step = Math.trunc(this.#safeStep);\n return step > 0 ? step : 1;\n }\n\n /** Mutates one complete action and then renders/notifies its final value once. */\n #step(kind: SegmentKind, delta: number): void {\n if (kind === \"meridiem\" && this.wrapValue) {\n this.#state.hour = modulo(this.#state.hour + 12, 24);\n } else if (this.wrapValue) {\n const scale = kind === \"hour\" ? SECONDS_PER_HOUR : kind === \"minute\" ? SECONDS_PER_MINUTE : 1;\n this.#setFromSeconds(this.#secondsOfDay + delta * scale);\n } else if (kind === \"hour\") {\n // The displayed hour is a projection of the canonical one, so stepping it\n // moves the instant: 11 → 12 crosses noon or midnight even here, where the\n // step never leaves the segment's own bounds. Clamping on the canonical\n // clock is what \"no wrapping\" means — the day is not crossed.\n this.#state.hour = Math.min(23, Math.max(0, this.#state.hour + delta));\n } else {\n const { min, max } = this.#bounds(kind);\n const displayed = this.#displayValue(kind);\n this.#setDisplayed(kind, Math.min(max, Math.max(min, displayed + delta)));\n }\n this.#commitRender();\n }\n\n /** Accumulates a typed digit, rendering once and advancing after completion. */\n #typeDigit(segment: HTMLElement, kind: Exclude<SegmentKind, \"meridiem\">, digit: string): void {\n if (this.#typeSegment !== kind) this.#typeBuffer = \"\";\n this.#typeSegment = kind;\n\n const { max } = this.#bounds(kind);\n const candidate = Number(`${this.#typeBuffer}${digit}`);\n this.#typeBuffer = candidate <= max ? `${this.#typeBuffer}${digit}` : digit;\n\n this.#setDisplayed(kind, Number(this.#typeBuffer));\n this.#commitRender();\n\n if (this.#typeBuffer.length >= 2 || Number(this.#typeBuffer) * 10 > max) {\n this.#clearTypeBuffer();\n this.#focusSibling(segment, 1);\n }\n }\n\n /** Moves focus to the previous/next valid segment, if one exists. */\n #focusSibling(segment: HTMLElement, direction: 1 | -1): void {\n const segments = this.segmentTargets.filter((candidate) => this.#kindOf(candidate) !== null);\n const index = segments.indexOf(segment);\n segments[index + direction]?.focus();\n }\n\n /** Clears the direct-entry buffer and its owning segment together. */\n #clearTypeBuffer(): void {\n this.#typeBuffer = \"\";\n this.#typeSegment = null;\n }\n\n /**\n * Adopts authored segment state before a synchronous user operation consumes it,\n * and reports whether it did.\n */\n #adoptPendingDom(): boolean {\n const pending = this.#observer?.takeRecords() ?? [];\n if (pending.some(({ target }) => this.segmentTargets.includes(target as HTMLElement))) {\n this.#domDirty = true;\n }\n if (!this.#domDirty) return false;\n this.#domDirty = false;\n this.#clearTypeBuffer();\n this.#adoptDomState();\n return true;\n }\n\n /** Reconciles one coalesced target, Value, or retained-attribute mutation batch. */\n #reconcileDom(): void {\n this.#adoptPendingDom();\n this.#render();\n }\n\n /** Rebuilds canonical state from the targets; an absent hour represents midnight. */\n #adoptDomState(): void {\n let displayedHour = 0;\n let meridiem = AM;\n let minute = 0;\n let second = 0;\n\n for (const segment of this.segmentTargets) {\n const kind = this.#kindOf(segment);\n if (!kind) continue;\n const value = this.#authoredValue(segment, kind);\n if (kind === \"hour\") displayedHour = value;\n else if (kind === \"minute\") minute = value;\n else if (kind === \"second\") second = value;\n else meridiem = value;\n }\n\n this.#state = {\n hour:\n this.#safeHourCycle === 12\n ? (displayedHour % 12) + (meridiem === PM ? 12 : 0)\n : displayedHour,\n minute,\n second,\n };\n }\n\n /** Reads and integer-clamps one authored `aria-valuenow`. */\n #authoredValue(segment: HTMLElement, kind: SegmentKind): number {\n const raw = Number(segment.getAttribute(\"aria-valuenow\"));\n const { min, max } = this.#bounds(kind);\n if (!Number.isFinite(raw)) return min;\n return Math.min(max, Math.max(min, Math.trunc(raw)));\n }\n\n /** Writes a displayed segment value back into canonical state without rendering. */\n #setDisplayed(kind: SegmentKind, raw: number): void {\n const { min, max } = this.#bounds(kind);\n const value = Math.min(max, Math.max(min, Math.trunc(raw)));\n if (kind === \"hour\") {\n this.#state.hour =\n this.#safeHourCycle === 12 ? (value % 12) + (this.#state.hour >= 12 ? 12 : 0) : value;\n } else if (kind === \"minute\" || kind === \"second\") {\n this.#state[kind] = value;\n } else {\n this.#state.hour = (this.#state.hour % 12) + (value === PM ? 12 : 0);\n }\n }\n\n /** Converts seconds with day wrapping into the canonical three-unit state. */\n #setFromSeconds(raw: number): void {\n const seconds = modulo(raw, SECONDS_PER_DAY);\n this.#state.hour = Math.floor(seconds / SECONDS_PER_HOUR);\n this.#state.minute = Math.floor((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);\n this.#state.second = seconds % SECONDS_PER_MINUTE;\n }\n\n /** Reflects canonical state to every segment without dispatching user events. */\n #renderSegments(): void {\n this.#withoutObservation(() => {\n for (const segment of this.segmentTargets) this.#renderSegment(segment);\n });\n }\n\n /**\n * Reflects canonical state during connection or DOM reconciliation.\n *\n * No user edit reaches here, so `change` never fires from this path. A pass\n * that moves the committed value reports `reconcile` instead.\n *\n * @stimeoRenderRoot\n */\n #render(): void {\n this.#renderSegments();\n const value = this.#composedValue;\n const previous = this.#lastValue;\n this.#writeField(value);\n this.#lastValue = value;\n // A reconciliation can move the committed value — dropping a `second`\n // segment recomposes without it, and a `seconds` Value change adds or\n // removes the unit. That is this controller's decision rather than the\n // user's, so it is reported apart from `change`. The empty baseline is the\n // initial connection, which reports nothing.\n if (previous !== \"\" && value !== previous) {\n this.#move = this.#moves.record();\n this.dispatch(\"reconcile\", { detail: { value } });\n }\n }\n\n /** Reflects one completed user action and dispatches its final change exactly once. */\n #commitRender(): void {\n this.#renderSegments();\n const value = this.#composedValue;\n const changed = value !== this.#lastValue;\n this.#lastValue = value;\n if (changed) this.#move = this.#moves.record();\n const move = this.#move;\n if (this.#writeField(value)) commitField(this.fieldTarget);\n if (!this.#moves.isLatest(move)) return;\n if (changed) this.dispatch(\"change\", { detail: { value } });\n }\n\n /** Reflects one segment's value and controller-owned ARIA bounds/text. */\n #renderSegment(segment: HTMLElement): void {\n const kind = this.#kindOf(segment);\n if (!kind) return;\n const value = this.#displayValue(kind);\n const text = kind === \"meridiem\" ? (value === PM ? \"PM\" : \"AM\") : pad(value);\n const { min, max } = this.#bounds(kind);\n\n segment.setAttribute(\"aria-valuenow\", String(value));\n segment.setAttribute(\"aria-valuetext\", text);\n segment.setAttribute(\"aria-valuemin\", String(min));\n segment.setAttribute(\"aria-valuemax\", String(max));\n segment.textContent = text;\n }\n\n /** Writes a composed value to the optional form field and reports whether it changed. */\n #writeField(value: string): boolean {\n return this.hasFieldTarget && writeField(this.fieldTarget, value);\n }\n\n /** The canonical form value composed as `HH:MM[:SS]`. */\n get #composedValue(): string {\n const parts = [pad(this.#state.hour), pad(this.#state.minute)];\n if (this.secondsValue) parts.push(pad(this.#state.second));\n return parts.join(\":\");\n }\n\n /** Returns a canonical unit in the presentation form exposed by its segment. */\n #displayValue(kind: SegmentKind): number {\n if (kind === \"hour\") {\n return this.#safeHourCycle === 12 ? this.#state.hour % 12 || 12 : this.#state.hour;\n }\n if (kind === \"meridiem\") return this.#state.hour >= 12 ? PM : AM;\n return this.#state[kind];\n }\n\n /** The inclusive controller-owned bounds for a segment kind. */\n #bounds(kind: SegmentKind): { min: number; max: number } {\n switch (kind) {\n case \"hour\":\n return this.#safeHourCycle === 12 ? { min: 1, max: 12 } : { min: 0, max: 23 };\n case \"minute\":\n case \"second\":\n return { min: 0, max: 59 };\n case \"meridiem\":\n return { min: AM, max: PM };\n }\n }\n\n /** Watches retained segment state while excluding this controller's own reflections. */\n #observeMutations(): void {\n const observer = new MutationObserver((records) => {\n const changed = records.some(\n ({ target }) => target instanceof HTMLElement && this.segmentTargets.includes(target),\n );\n if (!changed) return;\n this.#domDirty = true;\n this.#reconcile.schedule();\n });\n this.#observer = observer;\n this.#observeWith(observer);\n }\n\n /** Registers retained attribute observation on the controller subtree. */\n #observeWith(observer: MutationObserver): void {\n observer.observe(this.element, {\n subtree: true,\n attributes: true,\n attributeFilter: [\"aria-valuenow\", \"data-segment\"],\n });\n }\n\n /** Temporarily pauses observation so derived ARIA writes cannot become DOM input. */\n #withoutObservation(run: () => void): void {\n const observer = this.#observer;\n observer?.disconnect();\n try {\n run();\n } finally {\n if (observer && this.#connected) this.#observeWith(observer);\n }\n }\n\n /** Reads a segment's declared kind, or null when absent/invalid. */\n #kindOf(segment: HTMLElement): SegmentKind | null {\n const kind = segment.getAttribute(\"data-segment\");\n if (kind === \"hour\" || kind === \"minute\" || kind === \"second\" || kind === \"meridiem\") {\n return kind;\n }\n return null;\n }\n\n /** Canonical state as seconds since the start of its nominal day. */\n get #secondsOfDay(): number {\n return (\n this.#state.hour * SECONDS_PER_HOUR +\n this.#state.minute * SECONDS_PER_MINUTE +\n this.#state.second\n );\n }\n /** Current `hourCycle` declaration resolved against its numeric contract. */\n get #safeHourCycle(): number {\n return this.#numbers.read(\n this,\n \"hourCycle\",\n this.hourCycleValue,\n TimePickerController.values.hourCycle.default,\n TimePickerController.valueConstraints.hourCycle,\n );\n }\n\n /** Current `step` declaration resolved against its numeric contract. */\n get #safeStep(): number {\n return this.#numbers.read(\n this,\n \"step\",\n this.stepValue,\n TimePickerController.values.step.default,\n TimePickerController.valueConstraints.step,\n );\n }\n}\n\n/** Positive modulo for wrapping values in both keyboard directions. */\nfunction modulo(value: number, modulus: number): number {\n return ((value % modulus) + modulus) % modulus;\n}\n\n/** Zero-pads a number to two digits. */\nfunction pad(value: number): string {\n return String(value).padStart(2, \"0\");\n}\n"]}
@@ -3,13 +3,16 @@ import { Controller } from '@hotwired/stimulus';
3
3
  /**
4
4
  * Headless, highly accessible toast notification behavior.
5
5
  *
6
+ * Capacity evicts by arrival order, independent of DOM order. The same controller
7
+ * instance preserves that order across reconnects; a new instance uses DOM order.
8
+ *
6
9
  * Markup contract (identifier: `stimeo--toast`):
7
10
  * <div data-controller="stimeo--toast"
8
11
  * data-stimeo--toast-duration-value="5000"
9
12
  * data-stimeo--toast-max-value="3">
10
13
  * <!-- Attribute-only trigger: no hand-written JS required. -->
11
14
  * <button data-action="click->stimeo--toast#show"
12
- * data-stimeo--toast-body-param="Saved"
15
+ * data-stimeo--toast-message-param="Saved"
13
16
  * data-stimeo--toast-type-param="status">Show</button>
14
17
  * <!-- The live region is a descendant; the controller element only needs
15
18
  * to enclose both the trigger(s) and the list/template targets. -->
@@ -17,7 +20,7 @@ import { Controller } from '@hotwired/stimulus';
17
20
  * <ol data-stimeo--toast-target="list"></ol>
18
21
  * <template data-stimeo--toast-target="template">
19
22
  * <li data-stimeo--toast-target="item" tabindex="0">
20
- * <span role="status" data-toast-slot="body"></span>
23
+ * <span role="status" data-toast-slot="message"></span>
21
24
  * <button type="button" data-toast-dismiss>Dismiss</button>
22
25
  * </li>
23
26
  * </template>
@@ -30,7 +33,21 @@ import { Controller } from '@hotwired/stimulus';
30
33
  * once the last of hover and focus is released, so the pointer's target and the
31
34
  * focused control stay where they are.
32
35
  *
33
- * `dismiss` dispatches `{ item: HTMLElement, reason: "timeout" | "user" }`.
36
+ * `duration` is read as each toast is taken on. While the controller stays connected
37
+ * a toast already shown keeps the deadline it was given — a change neither shortens,
38
+ * stretches nor restarts it, and the time a hover or focus hold banked stays banked —
39
+ * and the next toast takes the new value. A change on its own arms, dismisses and
40
+ * reports nothing. A connection that finds toasts already in the list arms each of
41
+ * them from the current `duration`.
42
+ *
43
+ * The `max` limit (`0` or less, or not a finite number, means none) keeps them there too.
44
+ * Past it the oldest toasts go with reason `limit`, passing over every toast the pointer
45
+ * is over or focus is inside — whether or not a timer runs — the toast just taken on, and
46
+ * the one the pointer or focus is moving into. While nothing else can go the list stays
47
+ * over the limit, and the limit is applied again once hover and focus have both left a
48
+ * toast, or a toast they held leaves the list.
49
+ *
50
+ * `dismiss` dispatches `{ item: HTMLElement, reason: StateReason }`.
34
51
  *
35
52
  * `show` dispatches `{ item: HTMLElement }`.
36
53
  *
@@ -51,6 +68,16 @@ declare class ToastController extends Controller<HTMLElement> {
51
68
  default: number;
52
69
  };
53
70
  };
71
+ static valueConstraints: {
72
+ duration: {
73
+ readonly finite: true;
74
+ readonly min: 0;
75
+ readonly max: 2147483647;
76
+ };
77
+ max: {
78
+ readonly finite: true;
79
+ };
80
+ };
54
81
  static actions: readonly ["dismiss", "onKeydown", "pause", "resume", "show"];
55
82
  static events: readonly ["dismiss", "show"];
56
83
  readonly listTarget: HTMLElement;
@@ -60,21 +87,43 @@ declare class ToastController extends Controller<HTMLElement> {
60
87
  readonly hasTemplateTarget: boolean;
61
88
  durationValue: number;
62
89
  maxValue: number;
90
+ /**
91
+ * Stimulus reports every toast the list already holds before this runs, and each is
92
+ * taken on then with its holds, meeting no limit. The limit is applied here once, over
93
+ * all of them, unless the list was already held to the current `max`.
94
+ */
63
95
  connect(): void;
64
96
  disconnect(): void;
65
- /** Rebinds delegated interaction when Turbo replaces the list target in place. */
66
- listTargetConnected(element: HTMLElement): void;
67
- /** Releases delegation only when the removed target is its current owner. */
97
+ /** Keeps delegated interaction on the first list when a list arrives. */
98
+ listTargetConnected(): void;
99
+ /**
100
+ * Moves delegation to the list that stays and takes in the toasts it held while an earlier
101
+ * list was first. A toast that arrives with the list in the same task is left to
102
+ * `itemTargetConnected`, which applies the limit.
103
+ */
68
104
  listTargetDisconnected(element: HTMLElement): void;
69
- durationValueChanged(): void;
105
+ /**
106
+ * Holds the list to a changed `max`. Stimulus can also call this ahead of `connect()` —
107
+ * for an attribute that changed while the controller was away, and on every connect
108
+ * for an undeclared `max`, with its default; `connect()` decides then.
109
+ */
70
110
  maxValueChanged(): void;
71
111
  /**
72
112
  * Stimulus lifecycle callback triggered automatically when a new item target
73
- * enters the DOM, from a client-side injection or a Turbo Stream append alike. An
74
- * item already leaving, or parented outside `list`, is skipped.
113
+ * enters the DOM, from a client-side injection or a Turbo Stream append alike, and for
114
+ * every toast the list already holds ahead of `connect()`. An item already leaving,
115
+ * parented outside `list`, or already taken on (a move within the list) is skipped; any
116
+ * other is taken on with the holds it already has. On a connected controller the `max`
117
+ * limit is then applied, never to the arrival itself; the toasts reported ahead of
118
+ * `connect()` are left to it.
75
119
  */
76
120
  itemTargetConnected(element: HTMLElement): void;
77
- /** Clears any active timer when a toast is removed from the DOM. */
121
+ /**
122
+ * Lets go of a toast that left the list or stopped being an item: its timer, holds,
123
+ * `data-paused` and pending frame. After a move within the list the node is already
124
+ * back, still an item, when Stimulus reports it, so it keeps all of those, and only the
125
+ * holds the move may have ended are read again.
126
+ */
78
127
  itemTargetDisconnected(element: HTMLElement): void;
79
128
  /**
80
129
  * Shows a new toast. Accepts its content from either a Stimulus action param
@@ -82,16 +131,19 @@ declare class ToastController extends Controller<HTMLElement> {
82
131
  * (remote / Turbo trigger); the action param wins when both are present.
83
132
  *
84
133
  * <button data-action="click->stimeo--toast#show"
85
- * data-stimeo--toast-body-param="Saved"
134
+ * data-stimeo--toast-message-param="Saved"
86
135
  * data-stimeo--toast-type-param="status">Show</button>
87
136
  *
88
- * element.dispatchEvent(new CustomEvent("show", { detail: { body, type } }))
137
+ * element.dispatchEvent(new CustomEvent("show", { detail: { message, type } }))
89
138
  *
90
- * Clones the template slot, interpolates the body text, and appends to the list.
139
+ * Clones the template slot, interpolates the message, and appends to the list.
140
+ * `message` is the wording key the rest of the library dispatches under, so a
141
+ * part that already carries its own wording — `stimeo--clipboard:copy`,
142
+ * `stimeo--auto-submit:done` — wires straight into this action.
91
143
  */
92
144
  show(event: Event): void;
93
- /** Dismisses the toast that contained the trigger. */
94
- dismiss(event: Event): void;
145
+ /** Dismisses an owned item or descendant, or the item a DOM action operated. */
146
+ dismiss(input: Event | HTMLElement): void;
95
147
  /** Dismisses the focused toast when Escape is pressed. */
96
148
  onKeydown(event: KeyboardEvent): void;
97
149
  /**
@@ -100,18 +152,28 @@ declare class ToastController extends Controller<HTMLElement> {
100
152
  * Hover and focus are tracked as independent reasons: the timer is only
101
153
  * snapshotted on the first active reason, and only resumed once *every*
102
154
  * reason has been released (see {@link resume}). This keeps a toast paused
103
- * while it is still hovered *or* focused, per WCAG 2.2.1.
155
+ * while it is still hovered *or* focused, per WCAG 2.2.1. The hold is recorded
156
+ * whether or not a timer runs, so the `max` limit passes over the toast either
157
+ * way; `data-paused` marks a timer that stopped, and only that. An explicit
158
+ * item or descendant holds the hover reason, shared with pointer entry.
159
+ */
160
+ pause(input: Event | HTMLElement): void;
161
+ /**
162
+ * Resumes the auto-dismiss timer once both hover and focus have been released,
163
+ * and then applies the `max` limit again, sparing the toast the pointer or focus is
164
+ * moving into: its own hold only arrives after this event. An explicit item
165
+ * or descendant releases the hover reason without releasing a focus hold.
104
166
  */
105
- pause(event: Event): void;
106
- /** Resumes the auto-dismiss timer once both hover and focus have been released. */
107
- resume(event: Event): void;
167
+ resume(input: Event | HTMLElement): void;
108
168
  /**
109
- * Removes the oldest toasts when the list exceeds `maxValue`.
169
+ * Removes the oldest toasts while the list shows more than `maxValue`, passing
170
+ * over every toast hover or focus holds.
110
171
  *
111
172
  * Public (not `#private`) as a deterministic seam: enforcement normally runs
112
- * from `itemTargetConnected`, a Stimulus callback delivered through a
113
- * MutationObserver, which a DOM-only environment does not reliably fire — so
114
- * it can also be invoked directly. It is not a user-wired action.
173
+ * as each toast is taken on in `itemTargetConnected`, a Stimulus callback delivered
174
+ * through a MutationObserver, which a DOM-only environment does not reliably fire —
175
+ * so it can also be invoked directly. It counts only the toasts taken on. It is not a
176
+ * user-wired action.
115
177
  */
116
178
  enforceMaxLimit(): void;
117
179
  }