stimeo-ui 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +8 -1
  3. package/dist/cable/index.d.ts +79 -23
  4. package/dist/cable/index.js +363 -436
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/controllers/accordion_controller.d.ts +4 -2
  7. package/dist/controllers/accordion_controller.js +166 -55
  8. package/dist/controllers/accordion_controller.js.map +1 -1
  9. package/dist/controllers/alert_dialog_controller.d.ts +12 -2
  10. package/dist/controllers/alert_dialog_controller.js +862 -221
  11. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  12. package/dist/controllers/announcer_controller.d.ts +35 -5
  13. package/dist/controllers/announcer_controller.js +135 -198
  14. package/dist/controllers/announcer_controller.js.map +1 -1
  15. package/dist/controllers/aspect_ratio_controller.js +0 -10
  16. package/dist/controllers/aspect_ratio_controller.js.map +1 -1
  17. package/dist/controllers/auto_submit_controller.d.ts +30 -6
  18. package/dist/controllers/auto_submit_controller.js +271 -127
  19. package/dist/controllers/auto_submit_controller.js.map +1 -1
  20. package/dist/controllers/avatar_controller.js +171 -105
  21. package/dist/controllers/avatar_controller.js.map +1 -1
  22. package/dist/controllers/breadcrumb_controller.js +0 -130
  23. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  24. package/dist/controllers/bulk_select_controller.d.ts +18 -0
  25. package/dist/controllers/bulk_select_controller.js +262 -52
  26. package/dist/controllers/bulk_select_controller.js.map +1 -1
  27. package/dist/controllers/calendar_controller.d.ts +24 -5
  28. package/dist/controllers/calendar_controller.js +175 -209
  29. package/dist/controllers/calendar_controller.js.map +1 -1
  30. package/dist/controllers/carousel_controller.d.ts +34 -7
  31. package/dist/controllers/carousel_controller.js +461 -399
  32. package/dist/controllers/carousel_controller.js.map +1 -1
  33. package/dist/controllers/character_counter_controller.d.ts +17 -1
  34. package/dist/controllers/character_counter_controller.js +246 -156
  35. package/dist/controllers/character_counter_controller.js.map +1 -1
  36. package/dist/controllers/checkbox_controller.d.ts +7 -2
  37. package/dist/controllers/checkbox_controller.js +32 -74
  38. package/dist/controllers/checkbox_controller.js.map +1 -1
  39. package/dist/controllers/clipboard_controller.d.ts +16 -5
  40. package/dist/controllers/clipboard_controller.js +168 -147
  41. package/dist/controllers/clipboard_controller.js.map +1 -1
  42. package/dist/controllers/collapsible_controller.d.ts +16 -4
  43. package/dist/controllers/collapsible_controller.js +301 -120
  44. package/dist/controllers/collapsible_controller.js.map +1 -1
  45. package/dist/controllers/color_picker_controller.d.ts +18 -6
  46. package/dist/controllers/color_picker_controller.js +149 -139
  47. package/dist/controllers/color_picker_controller.js.map +1 -1
  48. package/dist/controllers/combobox_controller.d.ts +23 -5
  49. package/dist/controllers/combobox_controller.js +360 -133
  50. package/dist/controllers/combobox_controller.js.map +1 -1
  51. package/dist/controllers/command_palette_controller.d.ts +45 -14
  52. package/dist/controllers/command_palette_controller.js +970 -358
  53. package/dist/controllers/command_palette_controller.js.map +1 -1
  54. package/dist/controllers/conditional_fields_controller.d.ts +15 -2
  55. package/dist/controllers/conditional_fields_controller.js +166 -124
  56. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  57. package/dist/controllers/confirm_controller.d.ts +49 -12
  58. package/dist/controllers/confirm_controller.js +939 -248
  59. package/dist/controllers/confirm_controller.js.map +1 -1
  60. package/dist/controllers/context_menu_controller.d.ts +31 -4
  61. package/dist/controllers/context_menu_controller.js +256 -128
  62. package/dist/controllers/context_menu_controller.js.map +1 -1
  63. package/dist/controllers/count_up_controller.d.ts +13 -1
  64. package/dist/controllers/count_up_controller.js +73 -21
  65. package/dist/controllers/count_up_controller.js.map +1 -1
  66. package/dist/controllers/countdown_controller.d.ts +45 -1
  67. package/dist/controllers/countdown_controller.js +183 -148
  68. package/dist/controllers/countdown_controller.js.map +1 -1
  69. package/dist/controllers/currency_input_controller.d.ts +21 -2
  70. package/dist/controllers/currency_input_controller.js +134 -158
  71. package/dist/controllers/currency_input_controller.js.map +1 -1
  72. package/dist/controllers/data_grid_controller.d.ts +15 -4
  73. package/dist/controllers/data_grid_controller.js +114 -186
  74. package/dist/controllers/data_grid_controller.js.map +1 -1
  75. package/dist/controllers/date_range_picker_controller.d.ts +30 -5
  76. package/dist/controllers/date_range_picker_controller.js +288 -206
  77. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  78. package/dist/controllers/dialog_controller.d.ts +13 -1
  79. package/dist/controllers/dialog_controller.js +858 -223
  80. package/dist/controllers/dialog_controller.js.map +1 -1
  81. package/dist/controllers/direct_upload_controller.d.ts +24 -7
  82. package/dist/controllers/direct_upload_controller.js +73 -153
  83. package/dist/controllers/direct_upload_controller.js.map +1 -1
  84. package/dist/controllers/dirty_form_controller.js +14 -48
  85. package/dist/controllers/dirty_form_controller.js.map +1 -1
  86. package/dist/controllers/dismissible_controller.d.ts +19 -0
  87. package/dist/controllers/dismissible_controller.js +175 -21
  88. package/dist/controllers/dismissible_controller.js.map +1 -1
  89. package/dist/controllers/drawer_controller.d.ts +39 -11
  90. package/dist/controllers/drawer_controller.js +933 -341
  91. package/dist/controllers/drawer_controller.js.map +1 -1
  92. package/dist/controllers/dropdown_controller.d.ts +31 -1
  93. package/dist/controllers/dropdown_controller.js +312 -82
  94. package/dist/controllers/dropdown_controller.js.map +1 -1
  95. package/dist/controllers/editable_controller.d.ts +12 -1
  96. package/dist/controllers/editable_controller.js +158 -68
  97. package/dist/controllers/editable_controller.js.map +1 -1
  98. package/dist/controllers/empty_state_controller.js +67 -53
  99. package/dist/controllers/empty_state_controller.js.map +1 -1
  100. package/dist/controllers/file_dropzone_controller.d.ts +60 -18
  101. package/dist/controllers/file_dropzone_controller.js +311 -207
  102. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  103. package/dist/controllers/filter_controller.js +67 -39
  104. package/dist/controllers/filter_controller.js.map +1 -1
  105. package/dist/controllers/flash_controller.d.ts +31 -8
  106. package/dist/controllers/flash_controller.js +172 -314
  107. package/dist/controllers/flash_controller.js.map +1 -1
  108. package/dist/controllers/focus_controller.d.ts +12 -3
  109. package/dist/controllers/focus_controller.js +654 -240
  110. package/dist/controllers/focus_controller.js.map +1 -1
  111. package/dist/controllers/form_field_controller.js +147 -132
  112. package/dist/controllers/form_field_controller.js.map +1 -1
  113. package/dist/controllers/form_validation_controller.js +13 -86
  114. package/dist/controllers/form_validation_controller.js.map +1 -1
  115. package/dist/controllers/frame_loading_controller.d.ts +41 -9
  116. package/dist/controllers/frame_loading_controller.js +264 -213
  117. package/dist/controllers/frame_loading_controller.js.map +1 -1
  118. package/dist/controllers/highlight_controller.d.ts +22 -2
  119. package/dist/controllers/highlight_controller.js +107 -75
  120. package/dist/controllers/highlight_controller.js.map +1 -1
  121. package/dist/controllers/hover_card_controller.d.ts +56 -3
  122. package/dist/controllers/hover_card_controller.js +309 -118
  123. package/dist/controllers/hover_card_controller.js.map +1 -1
  124. package/dist/controllers/idle_controller.d.ts +42 -1
  125. package/dist/controllers/idle_controller.js +267 -101
  126. package/dist/controllers/idle_controller.js.map +1 -1
  127. package/dist/controllers/input_mask_controller.js +71 -72
  128. package/dist/controllers/input_mask_controller.js.map +1 -1
  129. package/dist/controllers/intersection_controller.d.ts +32 -13
  130. package/dist/controllers/intersection_controller.js +147 -106
  131. package/dist/controllers/intersection_controller.js.map +1 -1
  132. package/dist/controllers/lazy_frame_controller.d.ts +16 -0
  133. package/dist/controllers/lazy_frame_controller.js +9 -65
  134. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  135. package/dist/controllers/listbox_controller.d.ts +34 -2
  136. package/dist/controllers/listbox_controller.js +306 -204
  137. package/dist/controllers/listbox_controller.js.map +1 -1
  138. package/dist/controllers/local_time_controller.d.ts +1 -1
  139. package/dist/controllers/local_time_controller.js +54 -64
  140. package/dist/controllers/local_time_controller.js.map +1 -1
  141. package/dist/controllers/masonry_controller.d.ts +11 -3
  142. package/dist/controllers/masonry_controller.js +70 -93
  143. package/dist/controllers/masonry_controller.js.map +1 -1
  144. package/dist/controllers/menu_controller.d.ts +32 -7
  145. package/dist/controllers/menu_controller.js +214 -156
  146. package/dist/controllers/menu_controller.js.map +1 -1
  147. package/dist/controllers/menubar_controller.d.ts +4 -4
  148. package/dist/controllers/menubar_controller.js +170 -329
  149. package/dist/controllers/menubar_controller.js.map +1 -1
  150. package/dist/controllers/meter_controller.d.ts +20 -0
  151. package/dist/controllers/meter_controller.js +151 -67
  152. package/dist/controllers/meter_controller.js.map +1 -1
  153. package/dist/controllers/multi_select_controller.d.ts +32 -4
  154. package/dist/controllers/multi_select_controller.js +593 -358
  155. package/dist/controllers/multi_select_controller.js.map +1 -1
  156. package/dist/controllers/navigation_menu_controller.d.ts +8 -1
  157. package/dist/controllers/navigation_menu_controller.js +124 -232
  158. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  159. package/dist/controllers/nested_form_controller.d.ts +10 -0
  160. package/dist/controllers/nested_form_controller.js +352 -182
  161. package/dist/controllers/nested_form_controller.js.map +1 -1
  162. package/dist/controllers/network_status_controller.d.ts +23 -0
  163. package/dist/controllers/network_status_controller.js +242 -54
  164. package/dist/controllers/network_status_controller.js.map +1 -1
  165. package/dist/controllers/number_input_controller.d.ts +26 -2
  166. package/dist/controllers/number_input_controller.js +320 -263
  167. package/dist/controllers/number_input_controller.js.map +1 -1
  168. package/dist/controllers/optimistic_controller.js +16 -76
  169. package/dist/controllers/optimistic_controller.js.map +1 -1
  170. package/dist/controllers/otp_controller.d.ts +20 -4
  171. package/dist/controllers/otp_controller.js +198 -193
  172. package/dist/controllers/otp_controller.js.map +1 -1
  173. package/dist/controllers/overflow_indicator_controller.d.ts +5 -0
  174. package/dist/controllers/overflow_indicator_controller.js +116 -113
  175. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  176. package/dist/controllers/overflow_menu_controller.d.ts +48 -11
  177. package/dist/controllers/overflow_menu_controller.js +343 -283
  178. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  179. package/dist/controllers/pagination_controller.d.ts +35 -6
  180. package/dist/controllers/pagination_controller.js +295 -119
  181. package/dist/controllers/pagination_controller.js.map +1 -1
  182. package/dist/controllers/password_reveal_controller.d.ts +45 -8
  183. package/dist/controllers/password_reveal_controller.js +389 -121
  184. package/dist/controllers/password_reveal_controller.js.map +1 -1
  185. package/dist/controllers/password_strength_controller.d.ts +14 -5
  186. package/dist/controllers/password_strength_controller.js +99 -153
  187. package/dist/controllers/password_strength_controller.js.map +1 -1
  188. package/dist/controllers/persist_controller.d.ts +11 -4
  189. package/dist/controllers/persist_controller.js +237 -103
  190. package/dist/controllers/persist_controller.js.map +1 -1
  191. package/dist/controllers/pointer_drag_controller.d.ts +19 -7
  192. package/dist/controllers/pointer_drag_controller.js +185 -165
  193. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  194. package/dist/controllers/popover_controller.d.ts +38 -2
  195. package/dist/controllers/popover_controller.js +236 -97
  196. package/dist/controllers/popover_controller.js.map +1 -1
  197. package/dist/controllers/portal_controller.d.ts +44 -4
  198. package/dist/controllers/portal_controller.js +209 -76
  199. package/dist/controllers/portal_controller.js.map +1 -1
  200. package/dist/controllers/preview_guard_controller.d.ts +10 -4
  201. package/dist/controllers/preview_guard_controller.js +232 -116
  202. package/dist/controllers/preview_guard_controller.js.map +1 -1
  203. package/dist/controllers/progress_controller.d.ts +11 -0
  204. package/dist/controllers/progress_controller.js +125 -56
  205. package/dist/controllers/progress_controller.js.map +1 -1
  206. package/dist/controllers/radio_group_controller.d.ts +14 -5
  207. package/dist/controllers/radio_group_controller.js +117 -137
  208. package/dist/controllers/radio_group_controller.js.map +1 -1
  209. package/dist/controllers/range_slider_controller.d.ts +43 -3
  210. package/dist/controllers/range_slider_controller.js +192 -105
  211. package/dist/controllers/range_slider_controller.js.map +1 -1
  212. package/dist/controllers/rating_controller.d.ts +20 -4
  213. package/dist/controllers/rating_controller.js +418 -207
  214. package/dist/controllers/rating_controller.js.map +1 -1
  215. package/dist/controllers/read_more_controller.d.ts +2 -0
  216. package/dist/controllers/read_more_controller.js +134 -63
  217. package/dist/controllers/read_more_controller.js.map +1 -1
  218. package/dist/controllers/reading_progress_controller.d.ts +1 -1
  219. package/dist/controllers/reading_progress_controller.js +147 -135
  220. package/dist/controllers/reading_progress_controller.js.map +1 -1
  221. package/dist/controllers/relative_time_controller.d.ts +18 -4
  222. package/dist/controllers/relative_time_controller.js +145 -110
  223. package/dist/controllers/relative_time_controller.js.map +1 -1
  224. package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
  225. package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +97 -38
  226. package/dist/controllers/reset_on_restore_controller.js.map +1 -0
  227. package/dist/controllers/resizable_controller.d.ts +28 -2
  228. package/dist/controllers/resizable_controller.js +255 -139
  229. package/dist/controllers/resizable_controller.js.map +1 -1
  230. package/dist/controllers/roving_controller.js +39 -84
  231. package/dist/controllers/roving_controller.js.map +1 -1
  232. package/dist/controllers/scroll_area_controller.d.ts +7 -3
  233. package/dist/controllers/scroll_area_controller.js +428 -225
  234. package/dist/controllers/scroll_area_controller.js.map +1 -1
  235. package/dist/controllers/scroll_restore_controller.js +0 -53
  236. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  237. package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
  238. package/dist/controllers/scroll_visibility_controller.js +395 -145
  239. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  240. package/dist/controllers/scrollspy_controller.d.ts +6 -1
  241. package/dist/controllers/scrollspy_controller.js +181 -242
  242. package/dist/controllers/scrollspy_controller.js.map +1 -1
  243. package/dist/controllers/separator_controller.d.ts +19 -4
  244. package/dist/controllers/separator_controller.js +267 -140
  245. package/dist/controllers/separator_controller.js.map +1 -1
  246. package/dist/controllers/sidebar_controller.d.ts +64 -7
  247. package/dist/controllers/sidebar_controller.js +1023 -386
  248. package/dist/controllers/sidebar_controller.js.map +1 -1
  249. package/dist/controllers/skeleton_controller.d.ts +23 -0
  250. package/dist/controllers/skeleton_controller.js +248 -97
  251. package/dist/controllers/skeleton_controller.js.map +1 -1
  252. package/dist/controllers/slider_controller.d.ts +27 -1
  253. package/dist/controllers/slider_controller.js +159 -79
  254. package/dist/controllers/slider_controller.js.map +1 -1
  255. package/dist/controllers/smart_sticky_header_controller.d.ts +21 -3
  256. package/dist/controllers/smart_sticky_header_controller.js +162 -63
  257. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  258. package/dist/controllers/sortable_controller.js +0 -112
  259. package/dist/controllers/sortable_controller.js.map +1 -1
  260. package/dist/controllers/spinner_controller.d.ts +39 -4
  261. package/dist/controllers/spinner_controller.js +277 -169
  262. package/dist/controllers/spinner_controller.js.map +1 -1
  263. package/dist/controllers/step_indicator_controller.d.ts +5 -0
  264. package/dist/controllers/step_indicator_controller.js +99 -46
  265. package/dist/controllers/step_indicator_controller.js.map +1 -1
  266. package/dist/controllers/stepper_controller.d.ts +12 -3
  267. package/dist/controllers/stepper_controller.js +114 -73
  268. package/dist/controllers/stepper_controller.js.map +1 -1
  269. package/dist/controllers/stick_to_bottom_controller.d.ts +6 -0
  270. package/dist/controllers/stick_to_bottom_controller.js +262 -138
  271. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  272. package/dist/controllers/sticky_observer_controller.d.ts +11 -0
  273. package/dist/controllers/sticky_observer_controller.js +214 -49
  274. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  275. package/dist/controllers/submit_once_controller.d.ts +23 -8
  276. package/dist/controllers/submit_once_controller.js +294 -205
  277. package/dist/controllers/submit_once_controller.js.map +1 -1
  278. package/dist/controllers/switch_controller.d.ts +12 -1
  279. package/dist/controllers/switch_controller.js +33 -60
  280. package/dist/controllers/switch_controller.js.map +1 -1
  281. package/dist/controllers/tabs_controller.d.ts +2 -2
  282. package/dist/controllers/tabs_controller.js +35 -29
  283. package/dist/controllers/tabs_controller.js.map +1 -1
  284. package/dist/controllers/tags_input_controller.d.ts +12 -0
  285. package/dist/controllers/tags_input_controller.js +136 -145
  286. package/dist/controllers/tags_input_controller.js.map +1 -1
  287. package/dist/controllers/textarea_autosize_controller.d.ts +10 -0
  288. package/dist/controllers/textarea_autosize_controller.js +71 -58
  289. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  290. package/dist/controllers/theme_controller.d.ts +21 -9
  291. package/dist/controllers/theme_controller.js +130 -112
  292. package/dist/controllers/theme_controller.js.map +1 -1
  293. package/dist/controllers/time_picker_controller.d.ts +18 -1
  294. package/dist/controllers/time_picker_controller.js +146 -80
  295. package/dist/controllers/time_picker_controller.js.map +1 -1
  296. package/dist/controllers/toast_controller.d.ts +36 -11
  297. package/dist/controllers/toast_controller.js +186 -297
  298. package/dist/controllers/toast_controller.js.map +1 -1
  299. package/dist/controllers/toggle_group_controller.d.ts +12 -3
  300. package/dist/controllers/toggle_group_controller.js +95 -136
  301. package/dist/controllers/toggle_group_controller.js.map +1 -1
  302. package/dist/controllers/toolbar_controller.js +68 -98
  303. package/dist/controllers/toolbar_controller.js.map +1 -1
  304. package/dist/controllers/tooltip_controller.d.ts +45 -3
  305. package/dist/controllers/tooltip_controller.js +158 -124
  306. package/dist/controllers/tooltip_controller.js.map +1 -1
  307. package/dist/controllers/transition_controller.d.ts +22 -4
  308. package/dist/controllers/transition_controller.js +123 -119
  309. package/dist/controllers/transition_controller.js.map +1 -1
  310. package/dist/controllers/tree_view_controller.d.ts +21 -11
  311. package/dist/controllers/tree_view_controller.js +150 -345
  312. package/dist/controllers/tree_view_controller.js.map +1 -1
  313. package/dist/index.d.ts +8 -5
  314. package/dist/index.js +6370 -9346
  315. package/dist/index.js.map +1 -1
  316. package/dist/inspector/cli.d.ts +23 -3
  317. package/dist/inspector/cli.js +92 -37
  318. package/dist/inspector/cli.js.map +1 -1
  319. package/dist/inspector/cli_bin.js +92 -56
  320. package/dist/inspector/cli_bin.js.map +1 -1
  321. package/dist/inspector/examples.json +8 -8
  322. package/dist/inspector/manifest.json +787 -100
  323. package/dist/positioning/index.d.ts +8 -0
  324. package/dist/positioning/index.js +148 -47
  325. package/dist/positioning/index.js.map +1 -1
  326. package/package.json +6 -6
  327. package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
  328. package/dist/controllers/reset_before_cache_controller.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/arrow_step.ts","../../src/utils/event_owner.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/before_cache_reset.ts","../../src/utils/tabindex_loan.ts","../../src/utils/transient_hooks.ts","../../src/controllers/resizable_controller.ts"],"names":[],"mappings":"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","file":"resizable_controller.js","sourcesContent":["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 * Resolves which of a controller's elements owns a node.\n *\n * A delegated listener hears events from a whole subtree, so the handler's first\n * job is almost always the same question: which item, handle, or control does\n * this `event.target` belong to? The same question comes up for a\n * `MutationRecord.target`, for `document.activeElement`, and for a\n * `relatedTarget` on the way out of a hover region.\n *\n * The answer is `Node.contains()`, which is **inclusive** — an element contains\n * itself — so testing the candidate for identity as well would be redundant.\n *\n * **The guard is what makes this safe to call with a raw event target.**\n * `event.target` is typed `EventTarget | null`, and `contains()` takes a `Node?`:\n * browsers throw `TypeError` for anything else, and `window` — the everyday\n * `EventTarget` that is not a `Node` — is what an event dispatched at it carries.\n * Narrowing here means a caller never has to cast, and the rule cannot drift\n * between the places that ask the question.\n *\n * Scope stays with the caller. These helpers say *which candidate owns the node*,\n * not *whether the node belongs to this controller at all* — a component with\n * nested instances of itself decides that first (by comparing the closest\n * annotated ancestor) and passes the candidates it owns.\n */\n\n/**\n * Index in `candidates` of the first one that is, or contains, `node`.\n *\n * `-1` when none does, when `node` is absent, and when it is an `EventTarget`\n * that is not a `Node`. Candidates are tested in array order, so a nested pair\n * resolves to whichever the caller listed first.\n */\nexport function ownerIndex<T extends Element>(\n candidates: readonly T[],\n node: EventTarget | null | undefined,\n): number {\n if (!(node instanceof Node)) return -1;\n return candidates.findIndex((candidate) => candidate.contains(node));\n}\n\n/**\n * The first candidate that is, or contains, `node`; `null` when none does.\n *\n * A miss indexes the array at `-1`, which reads as `undefined` and lands on the\n * same `null` the absent cases produce.\n */\nexport function ownerOf<T extends Element>(\n candidates: readonly T[],\n node: EventTarget | null | undefined,\n): T | null {\n return candidates[ownerIndex(candidates, node)] ?? null;\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","/**\n * Runs a controller's \"return to the initial state\" pass just before Turbo\n * caches the page.\n *\n * **`disconnect()` cannot do this job, for two independent reasons.** Turbo\n * queues the clone from this event rather than taking it here, and the body swap\n * that runs the controller's `disconnect()` is queued separately — so which of\n * the two lands first is not something a controller can rely on, and a rewind\n * written in `disconnect()` may reach only the DOM being thrown away. In the\n * other direction, `disconnect()` also fires on an in-page move (Stimulus tears\n * down and reconnects the same element), where rewinding would wipe a\n * legitimately in-progress interaction — a spinner mid-load would vanish. One\n * timing is unreliable, the other is too eager; `turbo:before-cache` is the only\n * point that is exactly \"the page is about to be frozen\".\n *\n * Scope is the subscription only: registering on `activate()`, unregistering on\n * `deactivate()`, and one shared document listener no matter how many instances\n * are live. *What* to return to its initial state — which `data-state`, which\n * `hidden`, which `aria-busy` — stays in the controller, because no two\n * consumers answer it the same way.\n *\n * **Rewind state, not appearance.** The pass writes attributes the controller\n * itself owns; the visual result of those attributes is the consumer's CSS, and\n * a library that reached for style or class names would be guessing at markup\n * it does not own.\n *\n * Both entry points are idempotent, so the lifecycle hooks can call them\n * unconditionally: a second `activate()` does not double-subscribe and does not\n * make the callback run twice, and `deactivate()` on an instance that never\n * subscribed is a no-op.\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 #beforeCache = new BeforeCacheReset(() => this.#rewind());\n *\n * connect() { this.#beforeCache.activate(); }\n * disconnect() { this.#beforeCache.deactivate(); }\n * ```\n */\nexport class BeforeCacheReset {\n /** Every subscribed instance, iterated by the one shared document listener. */\n static readonly #subscribers = new Set<BeforeCacheReset>();\n\n /** The shared listener; installed while at least one instance is subscribed. */\n static readonly #onBeforeCache = (): void => {\n for (const subscriber of BeforeCacheReset.#subscribers) subscriber.#rewind();\n };\n\n readonly #rewind: () => void;\n\n /** @param rewind - the pass that returns this controller's state to its initial form. */\n constructor(rewind: () => void) {\n this.#rewind = rewind;\n }\n\n /** Subscribes to `turbo:before-cache`; call from `connect()`. Idempotent. */\n activate(): void {\n const first = BeforeCacheReset.#subscribers.size === 0;\n BeforeCacheReset.#subscribers.add(this);\n if (first) {\n document.addEventListener(\"turbo:before-cache\", BeforeCacheReset.#onBeforeCache);\n }\n }\n\n /** Unsubscribes; call from `disconnect()`. Safe when never subscribed. */\n deactivate(): void {\n BeforeCacheReset.#subscribers.delete(this);\n if (BeforeCacheReset.#subscribers.size > 0) return;\n document.removeEventListener(\"turbo:before-cache\", BeforeCacheReset.#onBeforeCache);\n }\n}\n","import { BeforeCacheReset } from \"./before_cache_reset\";\n\n/**\n * Shared bookkeeping for a `tabindex` a controller lends an element temporarily.\n *\n * A controller that must move focus somewhere the author never made focusable\n * (a landmark root, a scroll destination) reaches for the same trick: add a\n * `tabindex` just-in-time and hand it back once it is no longer needed. The\n * borrow is the easy half; the return is what the two conditions below are for.\n *\n * **Returning needs two conditions, not one.** Owning the borrow is not enough:\n * the attribute must also still hold the value this instance wrote. A consumer\n * that changed it afterwards — `tabindex=\"0\"` to make the root its own Tab stop\n * — owns it now, and removing it there silently discards authored markup. The\n * bookkeeping is dropped either way, since the loan is over regardless of who\n * ends up owning the value.\n *\n * **Never borrow over an existing value.** An element that already carries a\n * `tabindex` is the author's to control, so there is nothing to lend and nothing\n * to return.\n *\n * Every live loan also owns a shared `turbo:before-cache` subscription. The loan\n * is returned before Turbo can copy it into a snapshot, so consumers get cache\n * safety without duplicating a lifecycle hook; `returnAll()` removes the\n * subscription again as soon as no loan remains.\n *\n * The registry is keyed by element, so a controller borrowing on a single\n * element (`this.element`) and one borrowing across a changing set of targets\n * use the same API — the single-element case is a set of one. It holds no\n * opinion about *when* to borrow or where focus goes next; that stays in the\n * controller.\n *\n * **The API is deliberately two methods.** This file's own doc block is dropped\n * from `dist`, but every member comment is inlined into **each** consumer entry\n * (`tsup` builds with `splitting: false`), so rationale belongs here, only the\n * contract belongs on the members, and every method no consumer calls is still\n * paid for once per consumer entry.\n *\n * @example\n * ```ts\n * readonly #tabindex = new TabindexLoan();\n *\n * #rescueFocus() {\n * this.#tabindex.lend(this.element);\n * this.element.focus();\n * }\n *\n * disconnect() {\n * this.#tabindex.returnAll();\n * }\n * ```\n */\nexport class TabindexLoan<T extends HTMLElement = HTMLElement> {\n readonly #value: string;\n readonly #lent = new Set<T>();\n /** Returns live loans before Turbo can copy them into its page snapshot. */\n readonly #beforeCache = new BeforeCacheReset(() => this.returnAll());\n\n /**\n * @param value - the `tabindex` to lend. `\"-1\"` (the default) is\n * programmatically focusable but not a Tab stop; `\"0\"` is a real Tab stop,\n * which a scroll region with no focusable content of its own needs.\n */\n constructor(value: string = \"-1\") {\n this.#value = value;\n }\n\n /** Lends `element` the value; no-ops when it already carries a `tabindex`. */\n lend(element: T): void {\n if (element.hasAttribute(\"tabindex\")) return;\n element.setAttribute(\"tabindex\", this.#value);\n this.#lent.add(element);\n // Subscribe only while a real loan exists. Keeping this guarantee here means\n // every consumer is Turbo-safe without another lifecycle hook to remember.\n this.#beforeCache.activate();\n }\n\n /** Takes back every loan whose value is still the one that was lent. */\n returnAll(): void {\n for (const element of this.#lent) {\n if (element.getAttribute(\"tabindex\") === this.#value) element.removeAttribute(\"tabindex\");\n }\n this.#lent.clear();\n this.#beforeCache.deactivate();\n }\n}\n","/**\n * Drops the transient state hooks a connection inherited, so the cycle it opens\n * starts from a DOM that claims nothing.\n *\n * A transient hook is an attribute a controller writes to say \"this is happening\n * right now\" — a drag in progress, a form with unsaved edits, a refused\n * subscription. Its lifetime belongs to the interaction, not to the element, and\n * the two come apart whenever the element outlives the instance that wrote it: a\n * Turbo cache snapshot taken mid-interaction restores the hook with the markup,\n * and an element re-inserted elsewhere in the page carries it along. Nothing\n * takes such a hook off, because the instance that owned it is gone; consumer\n * CSS then keeps claiming a state no one is in.\n *\n * **`turbo:before-cache` cannot do this job**, which is why the pass belongs in\n * `connect()`: that event fires for a navigation only, so an in-page move — the\n * other half of the population — never reaches it, and a hook that arrived with\n * a moved element would survive. `connect()` covers both, because both end in a\n * connection.\n *\n * Scope is the **drop** only. What the fresh cycle should say instead is the\n * consumer's: a value re-read from the live DOM, a roster refilled by the\n * stream, a measurement retaken from the current scroll position, a slot emptied\n * of the last result. Those answers differ per consumer and none of them is a\n * hook removal, so the pass stops where every consumer agrees.\n *\n * A declaration names one group of hooks and carries no per-instance state, so\n * it belongs at module scope, shared by every instance the page connects. A\n * consumer writes as many as it has groups — hooks it drops under different\n * conditions cannot share one. The exception is a hook whose name is only known\n * at runtime, such as one built from the registered identifier: that\n * declaration is a field, because the name is.\n *\n * **A drop is not always right.** The population splits on one question: can the\n * state a hook describes outlive the instance that wrote it? Where it cannot — a\n * drag ends with the pointer, a subscription dies with its socket — dropping on\n * every connection is correct. Where it can — a submission in flight is not\n * interrupted by an in-page move — only a connection that follows a real restore\n * may drop, and the consumer answers \"did a session survive?\" with the signal it\n * already holds for its own teardown (a live-session field, a `DetachGate`\n * probe). The drop then sits behind that answer, as the second example shows.\n *\n * @example Unconditional — the state cannot outlive the instance.\n * ```ts\n * const TRANSIENT = new TransientHooks({ attributes: [\"data-sortable-dragging\"] });\n *\n * connect(): void {\n * TRANSIENT.reset(this.element);\n * }\n * ```\n *\n * @example Gated — an in-page move must not drop a live state.\n * ```ts\n * const TRANSIENT = new TransientHooks({ attributes: [\"data-optimistic\"] });\n *\n * connect(): void {\n * const restored = !this.#connected && !this.#gate.pending;\n * this.#gate.cancel();\n * this.#connected = true;\n * if (restored) TRANSIENT.reset(this.element);\n * }\n * ```\n */\n\n/** What a consumer declares once about the hooks its interaction owns. */\nexport interface TransientHooksOptions {\n /**\n * The attribute names a connection may find written by an earlier one. Hooks\n * a consumer drops under different conditions belong to different\n * declarations, so each one can be reset on its own.\n */\n readonly attributes: readonly string[];\n}\n\n/**\n * One consumer's declaration of the hooks its interaction owns, dropped from an\n * element by {@link TransientHooks.reset}.\n *\n * Every member comment inside this class body is inlined into each consumer\n * bundle (`tsup` builds with `splitting: false`), so rationale belongs in this\n * file's own block, which `dist` drops, and only the contract belongs inside.\n */\nexport class TransientHooks {\n readonly #attributes: readonly string[];\n\n constructor(options: TransientHooksOptions) {\n this.#attributes = options.attributes;\n }\n\n /** Drops the declared hooks from `element`; what it carries besides stays. */\n reset(element: Element): void {\n for (const attribute of this.#attributes) element.removeAttribute(attribute);\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { isReservedArrowChord } from \"../utils/arrow_step\";\nimport { ownerIndex } from \"../utils/event_owner\";\nimport { MicrotaskCoalescer } from \"../utils/microtask_coalescer\";\nimport { TabindexLoan } from \"../utils/tabindex_loan\";\nimport { TransientHooks } from \"../utils/transient_hooks\";\n\n/** The hook a connection may find written by an earlier, now-gone one. */\nconst TRANSIENT = new TransientHooks({ attributes: [\"data-dragging\"] });\n\n/** Value defaults, reused when a declaration cannot be read as a percentage. */\nconst DEFAULT_MIN = 0;\nconst DEFAULT_MAX = 100;\nconst DEFAULT_VALUE = 50;\nconst DEFAULT_STEP = 1;\n\n/**\n * Headless, highly accessible Window Splitter / Resizable panes logic.\n *\n * Markup contract (identifier: `stimeo--resizable`):\n * <div data-controller=\"stimeo--resizable\"\n * data-stimeo--resizable-min-value=\"20\"\n * data-stimeo--resizable-max-value=\"80\"\n * data-stimeo--resizable-step-value=\"1\"\n * data-stimeo--resizable-value-value=\"50\">\n * <div data-stimeo--resizable-target=\"primary\" id=\"pane-1\">Pane A</div>\n * <div role=\"separator\" tabindex=\"0\" aria-orientation=\"vertical\"\n * aria-controls=\"pane-1\" aria-valuemin=\"20\" aria-valuemax=\"80\"\n * aria-valuenow=\"50\" aria-label=\"Resize splitter\"\n * data-stimeo--resizable-target=\"separator\"\n * data-action=\"pointerdown->stimeo--resizable#onPointerDown\n * keydown->stimeo--resizable#onKeydown\"></div>\n * <div data-stimeo--resizable-target=\"secondary\">Pane B</div>\n * </div>\n *\n * Implements the WAI-ARIA APG **Window Splitter** pattern:\n * - Robust dragging track using W3C `setPointerCapture` to ensure uninterrupted dragging\n * even when pointers quickly stray outside the separator area.\n * - Arrow keys move the divider by `step` percent, along the axis\n * `aria-orientation` names; `Home` / `End` jump to the ends of the range.\n * - `Enter` collapses the primary pane to the minimum and puts it back where it\n * was, which is what the pattern means by restoring a previous position.\n * - Root-level CSS custom property `--stimeo--resizable-fraction` (0..1) driving\n * presentation styles.\n * - `F6` cycles focus through the panes, which the pattern lists as optional.\n *\n * `change` and `reconcile` dispatch `{ value: number, fraction: number }`.\n *\n * @remarks\n * Behavior only. The controller adjusts the CSS custom property on the root element,\n * updates ARIA values on the separator, and emits `stimeo--resizable:change` events.\n *\n * Both the range and the position are percentages. A bound that is not a finite\n * number falls back to its Value default, a maximum below the minimum collapses\n * onto that minimum, and a step that is not a positive finite number falls back\n * to `1` — so an unreadable declaration narrows what the widget can do without\n * ever publishing `NaN` to CSS or to assistive tech.\n *\n * The Values are inputs. A declared `value` outside the range stays in its\n * attribute as the page wrote it; the separator's ARIA, the fraction and both\n * events carry the clamped position instead, and only a move the user makes\n * writes `value`. `change` reports a key press, drag or toggle that moved the\n * position from the one last confirmed — a drag once, when it ends — and\n * nothing for one that leaves it there: a key at an edge, a press released\n * without moving, a drag released where it started. When a Value the page\n * changes at runtime — a Turbo morph or application code — moves the position,\n * `reconcile` reports it once per batch with the same detail, so a consumer can\n * tell its user's move from the page's. Connecting reports neither. The\n * position last confirmed is the one connecting published, moved by each\n * `change` and `reconcile`; the positions a drag paints on the way do not move\n * it.\n *\n * `aria-orientation` is the author's, and its absence means `horizontal` — the\n * value ARIA gives a separator that does not say. Reading any other default here\n * would make the announced axis and the answering arrow keys disagree.\n */\nexport class ResizableController extends Controller<HTMLElement> {\n static override targets = [\"primary\", \"secondary\", \"separator\"];\n static override values = {\n min: { type: Number, default: DEFAULT_MIN },\n max: { type: Number, default: DEFAULT_MAX },\n step: { type: Number, default: DEFAULT_STEP },\n value: { type: Number, default: DEFAULT_VALUE },\n };\n static actions = [\"onKeydown\", \"onPointerDown\", \"toggle\"] as const;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly primaryTarget: HTMLElement;\n declare readonly secondaryTarget: HTMLElement;\n declare readonly separatorTarget: HTMLElement;\n declare readonly hasPrimaryTarget: boolean;\n declare readonly hasSecondaryTarget: boolean;\n declare readonly hasSeparatorTarget: boolean;\n\n declare minValue: number;\n declare maxValue: number;\n declare stepValue: number;\n declare valueValue: number;\n\n /** Where the divider sat before the current collapse; `null` when unknown. */\n #valueBeforeCollapse: number | null = null;\n\n /**\n * The position last painted: moved by each move the user makes — every step of\n * a drag included — and by each repaint that finds a page-driven move.\n */\n #painted = DEFAULT_VALUE;\n\n /**\n * The position last confirmed: the one connecting published, then moved by\n * each `change` and `reconcile`. A drag moves the painted position step by\n * step and this one only when it ends.\n */\n #confirmed = DEFAULT_VALUE;\n\n /** Aborts in-progress pointer-drag listeners when the drag ends or on teardown. */\n #dragAbort: AbortController | null = null;\n\n /** `tabindex` lent to a pane so `F6` can put focus on it; panes carry none. */\n readonly #paneTabindex = new TabindexLoan();\n\n /** Releases the pane cycle listener bound in {@link connect}. */\n #cycleAbort: AbortController | null = null;\n\n /** Folds the range and position inputs of one morph batch into a single paint. */\n readonly #repaint = new MicrotaskCoalescer(() => this.#render());\n\n override connect(): void {\n // A drag cannot outlive a navigation, so a hook captured mid-drag is stale on\n // arrival. Clearing is unconditional here because disconnect() aborts the\n // drag, leaving no session that an in-page move could carry over.\n TRANSIENT.reset(this.element);\n this.#repaint.activate();\n // Stimulus fires the value callbacks before connect, where the coalescer\n // ignores them, so the first paint has to be asked for directly. The\n // position it publishes is taken as reported first, so connecting reports\n // nothing.\n this.#confirmed = this.#position;\n this.#render();\n // Bound on the root rather than the panes so the cycle continues once focus\n // has left the separator — the panes hold consumer markup and the next F6\n // arrives from inside one of them.\n this.#cycleAbort = new AbortController();\n this.element.addEventListener(\"keydown\", this.#onCycleKeydown, {\n signal: this.#cycleAbort.signal,\n });\n }\n\n /** Cancels any active pointer drag so listeners never leak past disconnect. */\n override disconnect(): void {\n this.#dragAbort?.abort();\n this.#dragAbort = null;\n this.#cycleAbort?.abort();\n this.#cycleAbort = null;\n this.#repaint.cancel();\n this.#paneTabindex.returnAll();\n this.element.removeAttribute(\"data-dragging\");\n }\n\n /** Moves focus to the next pane on `F6`, wrapping; entering at the first one. */\n readonly #onCycleKeydown = (event: KeyboardEvent): void => {\n if (event.key !== \"F6\") return;\n // Japanese input methods bind F6 to a conversion, so a press that belongs to\n // a composition steers that conversion and must not move focus away from it.\n if (event.isComposing) return;\n // A descendant widget that already claimed the key must not ALSO cycle the\n // panes; this listener sees consumer markup, so composition depends on it.\n if (event.defaultPrevented) return;\n // The pattern binds a bare F6 only. A chorded one is the browser's or the\n // OS's (Ctrl+F6 cycles frames in several browsers).\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n\n const panes: HTMLElement[] = [];\n if (this.hasPrimaryTarget) panes.push(this.primaryTarget);\n if (this.hasSecondaryTarget) panes.push(this.secondaryTarget);\n\n const current = ownerIndex(panes, event.target);\n // With no panes the modulo is NaN and the read is undefined, which is the\n // same \"nowhere to go\" this guard answers for a cycle that has ends.\n const next = panes[(current + 1) % panes.length];\n if (!next) return;\n\n event.preventDefault();\n this.#paneTabindex.lend(next);\n next.focus();\n };\n\n /** Re-renders when application code (or a Turbo morph) changes `value` at runtime. */\n valueValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Re-renders when application code (or a Turbo morph) changes `min` at runtime. */\n minValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Re-renders when application code (or a Turbo morph) changes `max` at runtime. */\n maxValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Re-publishes range and position onto a separator swapped in after connect. */\n separatorTargetConnected(): void {\n this.#repaint.schedule();\n }\n\n /** Starts active pointer drag tracking and locks capture. */\n onPointerDown(event: PointerEvent): void {\n if (!this.hasSeparatorTarget || event.button !== 0) return;\n\n event.preventDefault();\n\n const separator = this.separatorTarget;\n separator.setPointerCapture(event.pointerId);\n // preventDefault() above suppresses the implicit focus, so move focus\n // explicitly — otherwise keyboard (arrow) adjustments never reach the\n // separator after a pointer interaction (WCAG 2.1.1).\n separator.focus();\n\n this.element.setAttribute(\"data-dragging\", \"true\");\n\n this.#dragAbort?.abort();\n const abort = new AbortController();\n this.#dragAbort = abort;\n separator.addEventListener(\"pointermove\", this.#onPointerMove, { signal: abort.signal });\n separator.addEventListener(\"pointerup\", this.#onPointerUp, { signal: abort.signal });\n separator.addEventListener(\"pointercancel\", this.#onPointerUp, { signal: abort.signal });\n }\n\n /** Keydown adjustments for ArrowUp/Down/Left/Right and Home/End. */\n onKeydown(event: KeyboardEvent): void {\n if (isReservedArrowChord(event)) return;\n if (!this.hasSeparatorTarget) return;\n\n const { min, max } = this.#range;\n const isVertical = this.#isVertical;\n\n let handled = true;\n let nextValue = this.#position;\n\n switch (event.key) {\n case \"ArrowLeft\":\n if (isVertical) {\n nextValue -= this.#step;\n } else {\n handled = false;\n }\n break;\n case \"ArrowRight\":\n if (isVertical) {\n nextValue += this.#step;\n } else {\n handled = false;\n }\n break;\n case \"ArrowUp\":\n if (!isVertical) {\n nextValue -= this.#step;\n } else {\n handled = false;\n }\n break;\n case \"ArrowDown\":\n if (!isVertical) {\n nextValue += this.#step;\n } else {\n handled = false;\n }\n break;\n case \"Home\":\n nextValue = min;\n break;\n case \"End\":\n nextValue = max;\n break;\n case \"Enter\":\n event.preventDefault();\n this.toggle();\n return;\n default:\n handled = false;\n break;\n }\n\n if (handled) {\n event.preventDefault();\n this.#commit(nextValue);\n }\n }\n\n /** Collapses the primary pane to its minimum, or returns it to the last position. */\n toggle(): void {\n const { min, max } = this.#range;\n if (this.#position > min) {\n this.#valueBeforeCollapse = this.#position;\n this.#commit(min);\n } else {\n // With nothing remembered — a controller that connected to an already\n // collapsed pane — there is no previous position, so open the pane fully.\n const restored = this.#valueBeforeCollapse ?? max;\n this.#valueBeforeCollapse = null;\n this.#commit(restored);\n }\n }\n\n readonly #onPointerMove = (event: PointerEvent): void => {\n if (!this.hasSeparatorTarget) return;\n\n const rect = this.element.getBoundingClientRect();\n const raw = this.#isVertical\n ? (event.clientX - rect.left) / rect.width\n : (event.clientY - rect.top) / rect.height;\n\n // A container with no extent divides by zero; treat that as the near end\n // rather than letting it reach the published fraction.\n const fraction = Number.isFinite(raw) ? Math.max(0, Math.min(raw, 1)) : 0;\n this.#move(Math.round(fraction * 100));\n };\n\n readonly #onPointerUp = (event: PointerEvent): void => {\n // Ending the drag must not depend on the separator still being there: a\n // target removed mid-drag would otherwise strand the hook and the listeners.\n this.element.removeAttribute(\"data-dragging\");\n this.#dragAbort?.abort();\n this.#dragAbort = null;\n\n if (this.hasSeparatorTarget) {\n this.separatorTarget.releasePointerCapture(event.pointerId);\n }\n\n this.#confirm();\n };\n\n /** Moves to a position the user chose and reports it if it moved. */\n #commit(raw: number): void {\n this.#move(raw);\n this.#confirm();\n }\n\n /**\n * Stores the clamped position the user moved to and paints it. The painted\n * position moves with it before anything is reported, so the repaint the Value\n * write schedules — and any move a subscriber makes while `change` is\n * dispatched — is measured from this position.\n */\n #move(raw: number): void {\n const { min, max } = this.#range;\n const position = Math.max(min, Math.min(raw, max));\n this.valueValue = position;\n this.#painted = position;\n this.#paint();\n }\n\n /**\n * Publishes the position the Values declare without writing it back. A\n * position the user did not paint is the page's move, reported once as\n * `reconcile` unless it lands on the position last confirmed — a drag the page\n * puts back where it started has nothing new to report.\n *\n * @stimeoRenderRoot\n */\n #render(): void {\n this.#paint();\n const position = this.#position;\n if (position === this.#painted) return;\n this.#painted = position;\n if (position === this.#confirmed) return;\n this.#confirmed = position;\n this.dispatch(\"reconcile\", { detail: this.#detail(position) });\n }\n\n /**\n * Publishes the position: the fraction consumer CSS multiplies a pane by, and\n * the range assistive tech reads off the separator.\n */\n #paint(): void {\n const { min, max } = this.#range;\n const position = this.#position;\n\n this.element.style.setProperty(\"--stimeo--resizable-fraction\", String(position / 100));\n\n if (this.hasSeparatorTarget) {\n this.separatorTarget.setAttribute(\"aria-valuenow\", String(position));\n this.separatorTarget.setAttribute(\"aria-valuemin\", String(min));\n this.separatorTarget.setAttribute(\"aria-valuemax\", String(max));\n }\n }\n\n /**\n * Reports the published position as `change` when the user's operation moved\n * it from the position last confirmed. A key at an edge, a press released\n * without moving and a drag released where it started report nothing.\n */\n #confirm(): void {\n const position = this.#position;\n if (position === this.#confirmed) return;\n this.#confirmed = position;\n this.dispatch(\"change\", { detail: this.#detail(position) });\n }\n\n /** The detail both events carry for `position`. */\n #detail(position: number): { value: number; fraction: number } {\n return { value: position, fraction: position / 100 };\n }\n\n /** The declared range after validation; an unreadable bound uses its default. */\n get #range(): { readonly min: number; readonly max: number } {\n const min = Number.isFinite(this.minValue) ? this.minValue : DEFAULT_MIN;\n const max = Number.isFinite(this.maxValue) ? this.maxValue : DEFAULT_MAX;\n // A maximum below the minimum describes no range at all; collapsing it onto\n // the minimum keeps the position inside something that can be announced.\n return { min, max: Math.max(min, max) };\n }\n\n /** The declared position, clamped into the validated range. */\n get #position(): number {\n const { min, max } = this.#range;\n const value = Number.isFinite(this.valueValue) ? this.valueValue : DEFAULT_VALUE;\n return Math.max(min, Math.min(value, max));\n }\n\n /** The keyboard increment; a non-positive or unreadable one uses the default. */\n get #step(): number {\n return Number.isFinite(this.stepValue) && this.stepValue > 0 ? this.stepValue : DEFAULT_STEP;\n }\n\n /** Whether the divider runs vertically; a separator that does not say is horizontal. */\n get #isVertical(): boolean {\n return (\n this.hasSeparatorTarget &&\n this.separatorTarget.getAttribute(\"aria-orientation\") === \"vertical\"\n );\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/arrow_step.ts","../../src/utils/event_owner.ts","../../src/utils/listener_set.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/morph_render_watcher.ts","../../src/utils/number_bounds.ts","../../src/utils/coerce.ts","../../src/utils/number_value.ts","../../src/utils/query_open_descendants.ts","../../src/utils/shared_registry.ts","../../src/utils/tabindex_loan.ts","../../src/controllers/resizable_controller.ts"],"names":["above"],"mappings":"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","file":"resizable_controller.js","sourcesContent":["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 * Resolves which of a controller's elements owns a node.\n *\n * A delegated listener hears events from a whole subtree, so the handler's first\n * job is almost always the same question: which item, handle, or control does\n * this `event.target` belong to? The same question comes up for a\n * `MutationRecord.target`, for `document.activeElement`, and for a\n * `relatedTarget` on the way out of a hover region.\n *\n * The answer is `Node.contains()`, which is **inclusive** — an element contains\n * itself — so testing the candidate for identity as well would be redundant.\n *\n * **The guard is what makes this safe to call with a raw event target.**\n * `event.target` is typed `EventTarget | null`, and `contains()` takes a `Node?`:\n * browsers throw `TypeError` for anything else, and `window` — the everyday\n * `EventTarget` that is not a `Node` — is what an event dispatched at it carries.\n * Narrowing here means a caller never has to cast, and the rule cannot drift\n * between the places that ask the question.\n *\n * Scope stays with the caller. These helpers say *which candidate owns the node*,\n * not *whether the node belongs to this controller at all* — a component with\n * nested instances of itself decides that first (by comparing the closest\n * annotated ancestor) and passes the candidates it owns.\n */\n\n/**\n * Index in `candidates` of the first one that is, or contains, `node`.\n *\n * `-1` when none does, when `node` is absent, and when it is an `EventTarget`\n * that is not a `Node`. Candidates are tested in array order, so a nested pair\n * resolves to whichever the caller listed first.\n */\nexport function ownerIndex<T extends Element>(\n candidates: readonly T[],\n node: EventTarget | null | undefined,\n): number {\n if (!(node instanceof Node)) return -1;\n return candidates.findIndex((candidate) => candidate.contains(node));\n}\n\n/**\n * The first candidate that is, or contains, `node`; `null` when none does.\n *\n * A miss indexes the array at `-1`, which reads as `undefined` and lands on the\n * same `null` the absent cases produce.\n */\nexport function ownerOf<T extends Element>(\n candidates: readonly T[],\n node: EventTarget | null | undefined,\n): T | null {\n return candidates[ownerIndex(candidates, node)] ?? null;\n}\n","/**\n * Owns every listener a controller attaches for one connected lifetime and\n * releases them together, so an event name is spelled once and the release\n * cannot drift from the registration.\n *\n * Detaching by hand repeats three things at the release site — the type, the\n * handler reference and the capture flag — and any one of them drifting leaves\n * a listener alive on an element the controller no longer drives. Aborting the\n * signal a registration was created with releases it whatever it was made of,\n * so the release site names nothing.\n *\n * One set per lifetime, held as a field and never rebuilt. {@link\n * ListenerSet.dispose} is the only thing that closes a generation, and it opens\n * the next one in the same step, so the lifecycle hooks can call `add` and\n * `dispose` in any order any number of times, and no `add` ever meets an\n * already aborted signal — a DOM that registers a listener on such a signal\n * would keep it forever. Rebuilding the set instead would leak:\n * `addEventListener` matches an existing registration on target, type, callback\n * and capture alone, so re-adding the same handler while the first registration\n * is live is discarded, and that live registration keeps the signal it was\n * attached with — a set built by a second `connect()` can never release what it\n * appears to own.\n *\n * Scope is the registration only. Timers, observers, leases and the order they\n * are unwound in stay with the controller, which places `dispose()` in its\n * cleanup sequence. A receiver that changes at runtime (a\n * swapped target) is rebound by calling `dispose()` and then `add()` again from\n * the rebind, not by a second set.\n *\n * The set must own every registration of a tuple it holds: a listener the same\n * target already carries for the same type, callback and capture flag keeps the\n * right to remove it, and this set's `add` for that tuple is discarded. A\n * subscription shared between instances behind a participant count, or one that\n * lives for less than the connection, keeps its own pair of calls.\n *\n * @example\n * ```ts\n * readonly #listeners = new ListenerSet();\n *\n * connect(): void {\n * this.#listeners.add(this.element, \"submit\", this.#onNativeSubmit, { capture: true });\n * this.#listeners.add(this.element, \"turbo:submit-start\", this.#onSubmitStart);\n * this.#listeners.add(this.element, \"turbo:submit-end\", this.#onSubmitEnd);\n * }\n *\n * disconnect(): void {\n * this.#listeners.dispose();\n * }\n * ```\n */\nexport class ListenerSet {\n /** The generation every `add` joins until the next `dispose()`. */\n #abort = new AbortController();\n\n /**\n * Attaches `handler` to the open generation, exactly as the caller spelled it.\n *\n * The set supplies the signal, so `options` carries everything else the DOM\n * accepts — `capture` included, which has to match at release time and no\n * longer has a second place to drift from.\n */\n add(\n target: EventTarget,\n type: string,\n handler: EventListener,\n options?: Omit<AddEventListenerOptions, \"signal\">,\n ): void {\n target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });\n }\n\n /**\n * Releases every listener of the open generation, synchronously, and opens the\n * next one. Idempotent, and safe before anything has been added.\n */\n dispose(): void {\n this.#abort.abort();\n this.#abort = new AbortController();\n }\n}\n","/**\n * Collapses many Stimulus lifecycle callbacks from one DOM mutation into a\n * single pass.\n *\n * Stimulus fires `<name>TargetConnected` / `Disconnected` once per element and\n * `<name>ValueChanged` once per changed attribute. Replacing a list of N options\n * or morphing several render Values therefore delivers N callbacks — but the\n * useful unit of work is \"reconcile against the resulting declarative input\",\n * once, after the batch has settled. Every controller with reconcilable targets\n * or render Values needs the same shape: a `queued` flag plus `queueMicrotask`.\n *\n * **A microtask is the right horizon, and the reason is specific.** Stimulus\n * drives these callbacks from a `MutationObserver`, whose own callback already\n * runs as a microtask with the whole batch in hand; scheduling one more lands\n * after the last sibling callback of that batch and still before paint or any\n * event handler. A timer would be later than it needs to be, and reconciling\n * synchronously would run once per element against a half-applied DOM.\n *\n * **The two guards are not the same guard.** Scheduling is refused before the\n * controller connects, and running is refused after it disconnects:\n *\n * - **Before `connect()`** — Stimulus delivers initial target and Value callbacks\n * ahead of `connect()`. Reconciling there would compute output against a\n * controller whose own state has not been initialised, and `connect()` is\n * about to do a full pass anyway.\n * - **After `disconnect()`** — Stimulus fires a callback for **every** target\n * during teardown, and a microtask queued just before it would otherwise run\n * against a detached tree. {@link MicrotaskCoalescer.cancel} exists for the\n * teardown path to drop the pending pass outright.\n *\n * Both guards are part of one contract here rather than something each consumer\n * has to remember separately.\n *\n * Scope is the scheduling only. *What* to reconcile — keep the surviving active\n * option, fall back to the next / previous / first visible one, rebuild derived\n * chips or hidden fields — stays in the controller, because no two consumers\n * answer it the same way.\n *\n * @example\n * ```ts\n * readonly #reconcile = new MicrotaskCoalescer(() => this.#reconcileOptions());\n *\n * connect() { this.#reconcile.activate(); }\n * disconnect() { this.#reconcile.cancel(); }\n *\n * optionTargetConnected() { this.#reconcile.schedule(); }\n * optionTargetDisconnected() { this.#reconcile.schedule(); }\n * ```\n */\nexport class MicrotaskCoalescer {\n readonly #run: () => void;\n #queued = false;\n #active = false;\n #generation = 0;\n\n /** @param run - the single reconciliation pass, invoked at most once per batch. */\n constructor(run: () => void) {\n this.#run = run;\n }\n\n /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */\n activate(): void {\n this.#active = true;\n }\n\n /** Closes the window and drops any pending pass; call from `disconnect()`. */\n cancel(): void {\n this.#active = false;\n this.#queued = false;\n this.#generation += 1;\n }\n\n /** Requests one pass after the batch settles. Idempotent; inert outside the window. */\n schedule(): void {\n if (!this.#active || this.#queued) return;\n this.#queued = true;\n const generation = this.#generation;\n queueMicrotask(() => {\n // A cancelled callback must not consume a pass queued after reconnect.\n if (generation !== this.#generation || !this.#queued || !this.#active) return;\n this.#queued = false;\n this.#run();\n });\n }\n}\n","import { ListenerSet } from \"./listener_set\";\nimport { MicrotaskCoalescer } from \"./microtask_coalescer\";\n\n/**\n * Coalesces retained-element morphs and explicit lifecycle requests into one pass.\n *\n * Observe the controller's element after its initial state is settled. Morphs on\n * that element and bubbling morphs on its descendants share the same microtask\n * as {@link schedule}. The callback repairs derived output; the controller owns\n * any logical transition reporting. {@link disconnect} releases the listener and\n * cancels pending work, including work from an earlier connected lifetime.\n */\nexport class MorphRenderWatcher {\n readonly #listeners = new ListenerSet();\n readonly #pass: MicrotaskCoalescer;\n #element: Element | null = null;\n readonly #onMorph = (): void => this.#pass.schedule();\n\n /** @param run - the single pass that repairs the settled controller's output. */\n constructor(run: () => void) {\n this.#pass = new MicrotaskCoalescer(run);\n }\n\n /** Opens observation; observing the same element again preserves queued work. */\n observe(element: Element): void {\n if (this.#element === element) return;\n this.disconnect();\n this.#element = element;\n this.#pass.activate();\n this.#listeners.add(element, \"turbo:morph-element\", this.#onMorph);\n }\n\n /** Requests one pass; requests outside an observed lifetime are ignored. */\n schedule(): void {\n this.#pass.schedule();\n }\n\n /** Releases observation and pending work synchronously; safe to repeat. */\n disconnect(): void {\n this.#listeners.dispose();\n this.#pass.cancel();\n this.#element = null;\n }\n}\n","import { MAX_TIMER_DELAY_MS } from \"./timer_bounds\";\n\n/** Semantic constraints on an already decoded number, independent of the DOM. */\nexport interface NumberBounds {\n /** Finite numbers are required, including when this field is omitted. */\n readonly finite?: true;\n /** Inclusive lower endpoint. */\n readonly min?: number;\n /** Inclusive upper endpoint. */\n readonly max?: number;\n /** Exclusive lower endpoint. */\n readonly exclusiveMin?: number;\n /** Require a number without a fractional part. */\n readonly integer?: boolean;\n /** Exact decoded numbers accepted by a discrete contract. */\n readonly allowedValues?: readonly number[];\n /** JSON-safe exceptions to finite-number checking for unbounded endpoints. */\n readonly allowInfinity?: \"negative\" | \"positive\" | \"both\";\n}\n\n/** One constraint for each Number Value, including shorthand declarations. */\nexport type NumberValueConstraints<Values> = {\n readonly [Key in keyof Values as Values[Key] extends\n | NumberConstructor\n | { type: NumberConstructor }\n ? Key\n : never]: NumberBounds;\n};\n\n/** Reusable semantic domains; fractional inputs remain fractional unless excluded. */\nexport const NUMBER_BOUNDS = {\n finite: { finite: true },\n nonNegative: { finite: true, min: 0 },\n positive: { finite: true, exclusiveMin: 0 },\n nonNegativeInteger: { finite: true, min: 0, integer: true },\n positiveInteger: { finite: true, exclusiveMin: 0, integer: true },\n lowerBound: { finite: true, allowInfinity: \"negative\" },\n upperBound: { finite: true, allowInfinity: \"positive\" },\n timer: { finite: true, min: 0, max: MAX_TIMER_DELAY_MS },\n positiveTimer: { finite: true, exclusiveMin: 0, max: MAX_TIMER_DELAY_MS },\n} as const satisfies Record<string, NumberBounds>;\n\n/**\n * Checks all declared bounds without rounding, clamping, or coercing the input.\n * Infinity exceptions relax only finite checking; every other bound still applies.\n */\nexport function matchesNumberBounds(value: number, bounds: NumberBounds): boolean {\n if (!Number.isFinite(value)) {\n const direction = value === Infinity ? \"positive\" : value === -Infinity ? \"negative\" : null;\n if (direction === null) return false;\n if (bounds.allowInfinity !== \"both\" && bounds.allowInfinity !== direction) return false;\n }\n if (bounds.min !== undefined && value < bounds.min) return false;\n if (bounds.max !== undefined && value > bounds.max) return false;\n if (bounds.exclusiveMin !== undefined && value <= bounds.exclusiveMin) return false;\n if (bounds.integer && !Number.isInteger(value)) return false;\n if (bounds.allowedValues !== undefined && !bounds.allowedValues.includes(value)) return false;\n return true;\n}\n\n/** Decodes a Number Value literal; action params use their own JSON decoder. */\nexport function decodeNumberValue(raw: string): number {\n return Number(raw.replace(/_/g, \"\"));\n}\n","/**\n * Numeric coercion for controllers that accept a number through a Value, an action\n * param, or an event detail.\n *\n * Stimulus decodes action params as JSON when possible and leaves other text\n * untouched. CustomEvent detail can also supply a number or numeric string.\n * The reader accepts those two types while rejecting blank and non-finite input.\n */\n\nimport { matchesNumberBounds, type NumberBounds } from \"./number_bounds\";\n\n/**\n * Reads a finite number or nonblank numeric string; other input returns `null`.\n * Blank strings cannot silently reset a value to zero.\n */\nexport function toFiniteNumber(raw: unknown): number | null {\n if (typeof raw !== \"number\" && typeof raw !== \"string\") return null;\n if (typeof raw === \"string\" && raw.trim().length === 0) return null;\n const value = Number(raw);\n return Number.isFinite(value) ? value : null;\n}\n\n/**\n * Returns an accepted decoded Number Value or the caller's fallback unchanged.\n * The caller owns the fallback contract; this reader does not parse or write a Value.\n */\nexport function readNumber(raw: number, fallback: number, bounds: NumberBounds): number {\n return matchesNumberBounds(raw, bounds) ? raw : fallback;\n}\n","import { readNumber } from \"./coerce\";\nimport { matchesNumberBounds, type NumberBounds } from \"./number_bounds\";\n\n/** The instance identity carried by a Number Value read. */\nexport interface NumberValueOwner {\n readonly identifier: string;\n readonly element: Element;\n}\n\n/** Reads current declarations at the point of use without rewriting their attributes. */\nexport class NumberValueReader {\n /** The last rejected literal per Value; no history grows for an unchanged instance. */\n readonly #lastRejected = new Map<string, string>();\n\n /** Resolves the declared number using its own fallback and shared class contract. */\n read(\n owner: NumberValueOwner,\n name: string,\n raw: number,\n fallback: number,\n bounds: NumberBounds,\n ): number {\n const resolved = readNumber(raw, fallback, bounds);\n if (matchesNumberBounds(raw, bounds)) {\n this.#lastRejected.delete(name);\n return resolved;\n }\n const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;\n const literal = owner.element.getAttribute(attribute);\n if (literal === null) {\n this.#lastRejected.delete(name);\n return resolved;\n }\n if (this.#lastRejected.get(name) !== literal) {\n this.#lastRejected.set(name, literal);\n console.warn(\n `Stimeo UI: \"${owner.identifier}\" has an invalid number Value \"${name}\" declaration ${JSON.stringify(literal)}; using ${fallback}.`,\n );\n }\n return resolved;\n }\n}\n","/** Queries physical descendants and nested open shadow trees, including `root`'s own. */\nexport function queryOpenDescendants<T extends Element = Element>(\n root: ParentNode,\n selector: string,\n): T[] {\n const matches: T[] = [];\n const roots: ParentNode[] = [root];\n for (const scope of roots) {\n matches.push(...scope.querySelectorAll<T>(selector));\n if (scope.nodeType === Node.ELEMENT_NODE) {\n const shadow = (scope as Element).shadowRoot;\n if (shadow) roots.push(shadow);\n }\n for (const element of scope.querySelectorAll(\"*\")) {\n if (element.shadowRoot) roots.push(element.shadowRoot);\n }\n }\n return matches;\n}\n","/**\n * One registry per page for every copy of the library.\n *\n * Each `stimeo-ui/controllers/*` file, and each opt-in entry, is built on its own and carries\n * its own copy of every utility it uses, so a page that imports controllers one by one, or one\n * of them next to the barrel, evaluates a utility several times. A registry that coordinates\n * instances of different controllers — the stacks of leased values, the loans of a\n * `tabindex`, the Escape layers, the focus traps — must not be split by that: a dialog inside\n * a drawer, or a character counter and a form field on one input, coordinate whichever files\n * they came from. So such a registry lives once on `globalThis`, under a `Symbol.for` key the\n * copies agree on, and the first copy to ask for it creates it.\n *\n * The key names the registry and the version of its shape\n * (`stimeo-ui.<utility>.registry.v<n>`). Copies whose registries have the same shape share\n * one; a release that changes the shape changes the version, so a copy of another release\n * keeps a registry of its own instead of reading entries it does not understand — the two\n * then coordinate within each release only. An entry another copy put in a registry is read\n * through its fields alone, never through `#private` members, which belong to the class of\n * the copy that created it.\n */\n\n/**\n * The registry stored under `key`, created by `create` on first use.\n *\n * @param key - `stimeo-ui.<utility>.registry.v<n>`: the version is that of the shape `create`\n * returns.\n * @param create - Builds the empty registry.\n */\nexport function sharedRegistry<T extends object>(key: string, create: () => T): T {\n const symbol = Symbol.for(key);\n const scope = globalThis as unknown as Record<symbol, T | undefined>;\n const existing = scope[symbol];\n if (existing !== undefined) return existing;\n const registry = create();\n Object.defineProperty(globalThis, symbol, { value: registry });\n return registry;\n}\n","import { queryOpenDescendants } from \"./query_open_descendants\";\nimport { sharedRegistry } from \"./shared_registry\";\n\n/** One loan's hold on one element's `tabindex`, in the stack every loan of it shares. */\ninterface LoanHold {\n /** The loan holding it; `null` for a loan read from a copy's record until a loan takes it. */\n loan: object | null;\n readonly record: string;\n readonly value: string;\n /** Whether it hands back the value of the hold beneath it; otherwise no `tabindex`. */\n linked: boolean;\n}\n\n/** The loans on each element, bottom first, and every loan's record name. */\ninterface TabindexLoanRegistry {\n readonly stacks: WeakMap<HTMLElement, LoanHold[]>;\n readonly names: Set<string>;\n}\n\n/**\n * Shared bookkeeping for a `tabindex` a controller lends an element temporarily.\n *\n * A controller that must move focus somewhere the author never made focusable\n * (a landmark root, a scroll destination) reaches for the same trick: add a\n * `tabindex` just-in-time and hand it back once it is no longer needed. The\n * borrow is the easy half; the return is what the two conditions below are for.\n *\n * **Returning needs two conditions, not one.** Owning the borrow is not enough:\n * the attribute must also still hold the value this instance wrote. A consumer\n * that changed it afterwards — `tabindex=\"0\"` to make the root its own Tab stop\n * — owns it now, and removing it there silently discards authored markup. The\n * bookkeeping is dropped either way, since the loan is over regardless of who\n * ends up owning the value.\n *\n * **Never borrow over a value no loan holds.** An element whose `tabindex` no loan\n * holds — the author's, or one the page wrote over the loans — is the author's to\n * control, so there is nothing to lend and nothing to return.\n *\n * **Every loan of an element shares one stack of loans**, whatever its owner and\n * whichever file of the package constructed it (the stacks are one per page). A loan\n * lends over the loans that hold the element while its `tabindex` is theirs — sharing\n * their value, or covering it with its own — and lends again where the page removed\n * the `tabindex`. The `tabindex` is the highest loan's that lends its value: returning\n * that loan gives the element the value of the loan beneath it, or no `tabindex`, and\n * any other return only leaves the stack. So two loans of one value — every focus trap\n * lends its container under one owner — keep it until the last of them returns, and a\n * loan lent after the page removed an earlier one's `tabindex` keeps it when the\n * earlier one returns.\n *\n * **A loan is recorded on the element.** Lending writes\n * `data-<owner>-tabindex-loan` holding the value the owner's topmost loan lends next\n * to the `tabindex`, and the owner's last loan to end removes it. A copy of the\n * element — a page Turbo restores from its cache is one — so tells its owners' loans\n * from an authored `tabindex`: `lend()` takes over a loan its owner recorded, and\n * `reclaim()` gives back one no loan has taken over; the `tabindex` goes with the last\n * of them. A copy keeps no order of its loans beyond putting those of the value it\n * carries on top. Without a record a `tabindex` is the author's. Nothing returns a\n * live loan before Turbo caches the page: `turbo:before-cache` also fires on pages\n * that stay, and the loan is still in use there.\n *\n * The registry is keyed by element, so a controller borrowing on a single\n * element (`this.element`) and one borrowing across a changing set of targets\n * use the same API — the single-element case is a set of one. It holds no\n * opinion about *when* to borrow or where focus goes next; that stays in the\n * controller.\n *\n * **The API is deliberately small.** Each consumer entry includes its own copy\n * of the class, so unused methods still increase its runtime output.\n *\n * @example\n * ```ts\n * readonly #tabindex = new TabindexLoan(\"-1\", this.identifier);\n *\n * connect() {\n * this.#tabindex.reclaim(this.element);\n * }\n *\n * #rescueFocus() {\n * this.#tabindex.lend(this.element);\n * this.element.focus();\n * }\n *\n * disconnect() {\n * this.#tabindex.returnAll();\n * }\n * ```\n */\nexport class TabindexLoan<T extends HTMLElement = HTMLElement> {\n /** The loans on each element and the record names, one per page. */\n static readonly #registry = sharedRegistry(\n \"stimeo-ui.tabindex-loan.registry.v1\",\n (): TabindexLoanRegistry => ({ stacks: new WeakMap(), names: new Set() }),\n );\n readonly #value: string;\n readonly #record: string;\n readonly #lent = new Set<T>();\n\n /**\n * @param value - the `tabindex` to lend. `\"-1\"` is programmatically focusable but\n * not a Tab stop; `\"0\"` is a real Tab stop, which a scroll region with no\n * focusable content of its own needs.\n * @param owner - Names the record on the element; the controller's identifier.\n */\n constructor(value: string, owner: string) {\n this.#value = value;\n this.#record = `data-${owner}-tabindex-loan`;\n TabindexLoan.#registry.names.add(this.#record);\n }\n\n /**\n * Lends `element` the value over the loans holding its `tabindex`, or where the page removed\n * it; a `tabindex` no loan holds is left alone, and a loan recorded on a copy taken over.\n */\n lend(element: T): void {\n const stack = this.#stack(element);\n const current = element.getAttribute(\"tabindex\");\n const held =\n stack.find((hold) => hold.loan === this) ??\n stack.find(\n (hold) => hold.loan === null && hold.record === this.#record && hold.value === this.#value,\n );\n const linked = stack.at(-1)?.value === current;\n if (!held && current !== null && !linked) return;\n this.#lent.add(element);\n if (held) held.loan = this;\n else stack.push({ loan: this, record: this.#record, value: this.#value, linked });\n this.#mark(element, stack);\n if (current === null || (!held && current !== this.#value)) {\n element.setAttribute(\"tabindex\", this.#value);\n }\n }\n\n /** Takes back every loan; one whose value the element shows hands it to the loan beneath. */\n returnAll(): void {\n for (const element of this.#lent) {\n const stack = this.#stack(element);\n const hold = stack.find((held) => held.loan === this);\n if (hold) this.#release(element, stack, hold);\n }\n this.#lent.clear();\n }\n\n /**\n * Gives back a loan its owner recorded on a restored copy that no loan has taken over, unless\n * the record holds another value or the element holds focus.\n */\n reclaim(element: HTMLElement): void {\n if (element.getAttribute(this.#record) !== this.#value) return;\n const stack = this.#stack(element);\n const hold = stack.find((held) => held.loan === null && held.record === this.#record);\n if (hold && !element.matches(\":focus\")) this.#release(element, stack, hold);\n }\n\n /** Gives back, as {@link reclaim} does, every loan of its owner recorded inside `root`. */\n reclaimWithin(root: ParentNode): void {\n for (const element of queryOpenDescendants<HTMLElement>(root, `[${this.#record}]`)) {\n this.reclaim(element);\n }\n }\n\n /** The element's loans, read from its records the first time. */\n #stack(element: HTMLElement): LoanHold[] {\n const stacks = TabindexLoan.#registry.stacks;\n const stack = stacks.get(element) ?? this.#seed(element);\n stacks.set(element, stack);\n return stack;\n }\n\n /** The loans a copy's records describe, those of the value it carries on top. */\n #seed(element: HTMLElement): LoanHold[] {\n const current = element.getAttribute(\"tabindex\");\n const holds: LoanHold[] = [];\n for (const record of TabindexLoan.#registry.names) {\n const value = element.getAttribute(record);\n if (value !== null) holds.push({ loan: null, record, value, linked: true });\n }\n holds.sort((one, other) => Number(one.value === current) - Number(other.value === current));\n for (const [index, hold] of holds.entries()) hold.linked = index > 0;\n return holds;\n }\n\n /** Takes `hold` off, handing the value it shows to the loan beneath. */\n #release(element: HTMLElement, stack: LoanHold[], hold: LoanHold): void {\n const current = element.getAttribute(\"tabindex\");\n const index = stack.indexOf(hold);\n const owns =\n current === hold.value && !stack.slice(index + 1).some((above) => above.value === current);\n stack.splice(index, 1);\n const above = stack[index];\n if (above) above.linked &&= hold.linked;\n this.#mark(element, stack);\n if (!owns) return;\n const below = hold.linked ? stack[index - 1] : undefined;\n if (!below) element.removeAttribute(\"tabindex\");\n else if (below.value !== current) element.setAttribute(\"tabindex\", below.value);\n }\n\n /** Leaves each owner's record of the value its topmost loan lends. */\n #mark(element: HTMLElement, stack: readonly LoanHold[]): void {\n const records = new Map<string, string | null>([[this.#record, null]]);\n for (const hold of stack) records.set(hold.record, hold.value);\n for (const [name, recorded] of records) {\n if (element.getAttribute(name) === recorded) continue;\n if (recorded === null) element.removeAttribute(name);\n else element.setAttribute(name, recorded);\n }\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { isReservedArrowChord } from \"../utils/arrow_step\";\nimport { ownerIndex } from \"../utils/event_owner\";\nimport { MorphRenderWatcher } from \"../utils/morph_render_watcher\";\nimport { NUMBER_BOUNDS, type NumberValueConstraints } from \"../utils/number_bounds\";\nimport { NumberValueReader } from \"../utils/number_value\";\nimport { TabindexLoan } from \"../utils/tabindex_loan\";\n\n/** Value defaults, reused when a declaration cannot be read as a percentage. */\nconst DEFAULT_MIN = 0;\nconst DEFAULT_MAX = 100;\nconst DEFAULT_VALUE = 50;\nconst DEFAULT_STEP = 1;\n\n/**\n * Headless, highly accessible Window Splitter / Resizable panes logic.\n *\n * Markup contract (identifier: `stimeo--resizable`):\n * <div data-controller=\"stimeo--resizable\"\n * data-stimeo--resizable-min-value=\"20\"\n * data-stimeo--resizable-max-value=\"80\"\n * data-stimeo--resizable-step-value=\"1\"\n * data-stimeo--resizable-value-value=\"50\">\n * <div data-stimeo--resizable-target=\"primary\" id=\"pane-1\">Pane A</div>\n * <div role=\"separator\" tabindex=\"0\" aria-orientation=\"vertical\"\n * aria-controls=\"pane-1\" aria-valuemin=\"20\" aria-valuemax=\"80\"\n * aria-valuenow=\"50\" aria-label=\"Resize splitter\"\n * data-stimeo--resizable-target=\"separator\"\n * data-action=\"pointerdown->stimeo--resizable#onPointerDown\n * keydown->stimeo--resizable#onKeydown\"></div>\n * <div data-stimeo--resizable-target=\"secondary\">Pane B</div>\n * </div>\n *\n * Implements the WAI-ARIA APG **Window Splitter** pattern:\n * - Robust dragging track using W3C `setPointerCapture` to ensure uninterrupted dragging\n * even when pointers quickly stray outside the separator area.\n * - Arrow keys move the divider by `step` percent, along the axis\n * `aria-orientation` names; `Home` / `End` jump to the ends of the range.\n * - `Enter` collapses the primary pane to the minimum and puts it back where it\n * was, which is what the pattern means by restoring a previous position.\n * - Root-level CSS custom property `--stimeo--resizable-fraction` (`position / 100`) driving\n * presentation styles.\n * - `F6` cycles focus through the panes, which the pattern lists as optional.\n *\n * `change` and `reconcile` dispatch `{ value: number, fraction: number }`.\n *\n * @remarks\n * Behavior only. The controller adjusts the CSS custom property on the root element,\n * updates ARIA values on the separator, and emits `stimeo--resizable:change` events.\n *\n * Both the range and the position are percentages. A bound that is not a finite\n * number falls back to its Value default, a maximum below the minimum collapses\n * onto that minimum, and a step that is not a positive finite number falls back\n * to `1` — so an unreadable declaration narrows what the widget can do without\n * ever publishing `NaN` to CSS or to assistive tech.\n *\n * The Values are inputs. A declared `value` outside the range stays in its\n * attribute as the page wrote it; the separator's ARIA, the fraction and both\n * events carry the clamped position instead, and only a move the user makes\n * writes `value`. `change` reports a key press, drag or toggle that moved the\n * position from the one last confirmed — a drag once, when it ends — and\n * nothing for one that leaves it there: a key at an edge, a press released\n * without moving, a drag released where it started. When a Value the page\n * changes at runtime — a Turbo morph or application code — moves the position,\n * `reconcile` reports it once per batch with the same detail, so a consumer can\n * tell its user's move from the page's. Connecting reports neither. The\n * position last confirmed is the one connecting published, moved by each\n * `change` and `reconcile`; the positions a drag paints on the way do not move\n * it.\n *\n * `aria-orientation` is the author's, and its absence means `horizontal` — the\n * value ARIA gives a separator that does not say. Reading any other default here\n * would make the announced axis and the answering arrow keys disagree.\n */\nexport class ResizableController extends Controller<HTMLElement> {\n /** Numeric read boundaries share one reader for this controller instance. */\n readonly #numbers = new NumberValueReader();\n\n static override targets = [\"primary\", \"secondary\", \"separator\"];\n static override values = {\n min: { type: Number, default: DEFAULT_MIN },\n max: { type: Number, default: DEFAULT_MAX },\n step: { type: Number, default: DEFAULT_STEP },\n value: { type: Number, default: DEFAULT_VALUE },\n };\n\n static valueConstraints = {\n min: NUMBER_BOUNDS.finite,\n max: NUMBER_BOUNDS.finite,\n step: NUMBER_BOUNDS.positive,\n value: NUMBER_BOUNDS.finite,\n } satisfies NumberValueConstraints<typeof ResizableController.values>;\n static actions = [\"onKeydown\", \"onPointerDown\", \"toggle\"] as const;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly primaryTarget: HTMLElement;\n declare readonly secondaryTarget: HTMLElement;\n declare readonly separatorTarget: HTMLElement;\n declare readonly separatorTargets: HTMLElement[];\n declare readonly hasPrimaryTarget: boolean;\n declare readonly hasSecondaryTarget: boolean;\n declare readonly hasSeparatorTarget: boolean;\n\n declare minValue: number;\n declare maxValue: number;\n declare stepValue: number;\n declare valueValue: number;\n\n /** Where the divider sat before the current collapse; `null` when unknown. */\n #valueBeforeCollapse: number | null = null;\n\n /**\n * The position last painted: moved by each move the user makes — every step of\n * a drag included — and by each repaint that finds a page-driven move.\n */\n #painted = DEFAULT_VALUE;\n\n /**\n * The position last confirmed: the one connecting published, then moved by\n * each `change` and `reconcile`. A drag moves the painted position step by\n * step and this one only when it ends.\n */\n #confirmed = DEFAULT_VALUE;\n\n /**\n * The pointer drag in progress: the separator holding the pointer, the pointer's\n * id, and the abort that ends the listeners the drag added to that separator.\n */\n #drag: {\n readonly separator: HTMLElement;\n readonly pointerId: number;\n readonly abort: AbortController;\n } | null = null;\n\n /** `tabindex` lent to a pane so `F6` can put focus on it; panes carry none. */\n readonly #paneTabindex = new TabindexLoan(\"-1\", this.identifier);\n\n /** Releases the pane cycle listener bound in {@link connect}. */\n #cycleAbort: AbortController | null = null;\n\n /** Folds the range and position inputs of one morph batch into a single paint. */\n readonly #repaint = new MorphRenderWatcher(() => this.#render());\n\n override connect(): void {\n this.#paneTabindex.reclaimWithin(this.element);\n this.#repaint.observe(this.element);\n // Stimulus fires the value callbacks before connect, where the coalescer\n // ignores them, so the first paint has to be asked for directly. The\n // position it publishes is taken as reported first, so connecting reports\n // nothing.\n this.#confirmed = this.#position;\n this.#render();\n // Bound on the root rather than the panes so the cycle continues once focus\n // has left the separator — the panes hold consumer markup and the next F6\n // arrives from inside one of them.\n this.#cycleAbort = new AbortController();\n this.element.addEventListener(\"keydown\", this.#onCycleKeydown, {\n signal: this.#cycleAbort.signal,\n });\n }\n\n /** Cancels any active pointer drag so listeners never leak past disconnect. */\n override disconnect(): void {\n this.#endDrag();\n this.#cycleAbort?.abort();\n this.#cycleAbort = null;\n this.#repaint.disconnect();\n this.#paneTabindex.returnAll();\n }\n\n /** Moves focus to the next pane on `F6`, wrapping; entering at the first one. */\n readonly #onCycleKeydown = (event: KeyboardEvent): void => {\n if (event.key !== \"F6\") return;\n // Japanese input methods bind F6 to a conversion, so a press that belongs to\n // a composition steers that conversion and must not move focus away from it.\n if (event.isComposing) return;\n // A descendant widget that already claimed the key must not ALSO cycle the\n // panes; this listener sees consumer markup, so composition depends on it.\n if (event.defaultPrevented) return;\n // The pattern binds a bare F6 only. A chorded one is the browser's or the\n // OS's (Ctrl+F6 cycles frames in several browsers).\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n\n const panes: HTMLElement[] = [];\n if (this.hasPrimaryTarget) panes.push(this.primaryTarget);\n if (this.hasSecondaryTarget) panes.push(this.secondaryTarget);\n\n const current = ownerIndex(panes, event.target);\n // With no panes the modulo is NaN and the read is undefined, which is the\n // same \"nowhere to go\" this guard answers for a cycle that has ends.\n const next = panes[(current + 1) % panes.length];\n if (!next) return;\n\n event.preventDefault();\n this.#paneTabindex.lend(next);\n next.focus();\n };\n\n /** Re-renders when application code (or a Turbo morph) changes `value` at runtime. */\n valueValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Re-renders when application code (or a Turbo morph) changes `min` at runtime. */\n minValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Re-renders when application code (or a Turbo morph) changes `max` at runtime. */\n maxValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Re-publishes range and position onto a separator swapped in after connect. */\n separatorTargetConnected(): void {\n this.#repaint.schedule();\n }\n\n /**\n * Ends a drag whose separator stopped being a target, and brings the separator\n * that stays to the current position. A separator still among the targets has\n * only moved inside the element, and its drag goes on.\n */\n separatorTargetDisconnected(separator: HTMLElement): void {\n if (this.#drag?.separator === separator && !this.separatorTargets.includes(separator)) {\n this.#endDrag();\n }\n this.#repaint.schedule();\n }\n\n /**\n * Starts active pointer drag tracking and locks capture on the separator pressed, so\n * a separator that coexists behind an earlier one drags itself. A press that lands on\n * no separator drags the first one.\n */\n onPointerDown(event: PointerEvent): void {\n if (!this.hasSeparatorTarget || event.button !== 0) return;\n\n event.preventDefault();\n\n const separators = this.separatorTargets;\n const separator = separators[ownerIndex(separators, event.target)] ?? this.separatorTarget;\n separator.setPointerCapture(event.pointerId);\n // preventDefault() above suppresses the implicit focus, so move focus\n // explicitly — otherwise keyboard (arrow) adjustments never reach the\n // separator after a pointer interaction (WCAG 2.1.1).\n separator.focus();\n\n this.element.setAttribute(\"data-dragging\", \"true\");\n\n this.#drag?.abort.abort();\n const abort = new AbortController();\n this.#drag = { separator, pointerId: event.pointerId, abort };\n separator.addEventListener(\"pointermove\", this.#onPointerMove, { signal: abort.signal });\n separator.addEventListener(\"pointerup\", this.#onPointerUp, { signal: abort.signal });\n separator.addEventListener(\"pointercancel\", this.#onPointerUp, { signal: abort.signal });\n }\n\n /** Keydown adjustments for ArrowUp/Down/Left/Right and Home/End. */\n onKeydown(event: KeyboardEvent): void {\n if (isReservedArrowChord(event)) return;\n if (!this.hasSeparatorTarget) return;\n\n const { min, max } = this.#range;\n const isVertical = this.#isVertical;\n\n let handled = true;\n let nextValue = this.#position;\n\n switch (event.key) {\n case \"ArrowLeft\":\n if (isVertical) {\n nextValue -= this.#step;\n } else {\n handled = false;\n }\n break;\n case \"ArrowRight\":\n if (isVertical) {\n nextValue += this.#step;\n } else {\n handled = false;\n }\n break;\n case \"ArrowUp\":\n if (!isVertical) {\n nextValue -= this.#step;\n } else {\n handled = false;\n }\n break;\n case \"ArrowDown\":\n if (!isVertical) {\n nextValue += this.#step;\n } else {\n handled = false;\n }\n break;\n case \"Home\":\n nextValue = min;\n break;\n case \"End\":\n nextValue = max;\n break;\n case \"Enter\":\n event.preventDefault();\n this.toggle();\n return;\n default:\n handled = false;\n break;\n }\n\n if (handled) {\n event.preventDefault();\n this.#commit(nextValue);\n }\n }\n\n /** Collapses the primary pane to its minimum, or returns it to the last position. */\n toggle(): void {\n const { min, max } = this.#range;\n if (this.#position > min) {\n this.#valueBeforeCollapse = this.#position;\n this.#commit(min);\n } else {\n // With nothing remembered — a controller that connected to an already\n // collapsed pane — there is no previous position, so open the pane fully.\n const restored = this.#valueBeforeCollapse ?? max;\n this.#valueBeforeCollapse = null;\n this.#commit(restored);\n }\n }\n\n readonly #onPointerMove = (event: PointerEvent): void => {\n if (!this.hasSeparatorTarget) return;\n\n const rect = this.element.getBoundingClientRect();\n const raw = this.#isVertical\n ? (event.clientX - rect.left) / rect.width\n : (event.clientY - rect.top) / rect.height;\n\n // A container with no extent divides by zero; treat that as the near end\n // rather than letting it reach the published fraction.\n const fraction = Number.isFinite(raw) ? Math.max(0, Math.min(raw, 1)) : 0;\n this.#move(Math.round(fraction * 100));\n };\n\n readonly #onPointerUp = (): void => {\n this.#endDrag();\n this.#confirm();\n };\n\n /**\n * Ends the drag in progress: the `data-dragging` hook, the listeners on the\n * separator that holds the pointer, and that separator's pointer capture. It\n * reads nothing from the current targets, so a separator removed or replaced\n * mid-drag cannot strand the hook or the listeners.\n */\n #endDrag(): void {\n this.element.removeAttribute(\"data-dragging\");\n const drag = this.#drag;\n this.#drag = null;\n if (!drag) return;\n drag.abort.abort();\n try {\n drag.separator.releasePointerCapture?.(drag.pointerId);\n } catch {\n // A pointer that has already ended holds no capture, and the engine throws for its id.\n }\n }\n\n /** Moves to a position the user chose and reports it if it moved. */\n #commit(raw: number): void {\n this.#move(raw);\n this.#confirm();\n }\n\n /**\n * Stores the clamped position the user moved to and paints it. The painted\n * position moves with it before anything is reported, so the repaint the Value\n * write schedules — and any move a subscriber makes while `change` is\n * dispatched — is measured from this position.\n */\n #move(raw: number): void {\n const { min, max } = this.#range;\n const position = Math.max(min, Math.min(raw, max));\n this.valueValue = position;\n this.#painted = position;\n this.#paint();\n }\n\n /**\n * Publishes the position the Values declare without writing it back. A\n * position the user did not paint is the page's move, reported once as\n * `reconcile` unless it lands on the position last confirmed — a drag the page\n * puts back where it started has nothing new to report.\n *\n * @stimeoRenderRoot\n */\n #render(): void {\n this.#paint();\n const position = this.#position;\n if (position === this.#painted) return;\n this.#painted = position;\n if (position === this.#confirmed) return;\n this.#confirmed = position;\n this.dispatch(\"reconcile\", { detail: this.#detail(position) });\n }\n\n /**\n * Publishes the position: the fraction consumer CSS multiplies a pane by, and\n * the range assistive tech reads off the separator.\n */\n #paint(): void {\n if (this.#drag) this.element.setAttribute(\"data-dragging\", \"true\");\n else this.element.removeAttribute(\"data-dragging\");\n const { min, max } = this.#range;\n const position = this.#position;\n\n this.element.style.setProperty(\"--stimeo--resizable-fraction\", String(position / 100));\n\n if (this.hasSeparatorTarget) {\n this.separatorTarget.setAttribute(\"aria-valuenow\", String(position));\n this.separatorTarget.setAttribute(\"aria-valuemin\", String(min));\n this.separatorTarget.setAttribute(\"aria-valuemax\", String(max));\n }\n }\n\n /**\n * Reports the published position as `change` when the user's operation moved\n * it from the position last confirmed. A key at an edge, a press released\n * without moving and a drag released where it started report nothing.\n */\n #confirm(): void {\n const position = this.#position;\n if (position === this.#confirmed) return;\n this.#confirmed = position;\n this.dispatch(\"change\", { detail: this.#detail(position) });\n }\n\n /** The detail both events carry for `position`. */\n #detail(position: number): { value: number; fraction: number } {\n return { value: position, fraction: position / 100 };\n }\n\n /** The declared range after validation; an unreadable bound uses its default. */\n get #range(): { readonly min: number; readonly max: number } {\n const min = this.#safeMin;\n const max = this.#safeMax;\n // A maximum below the minimum describes no range at all; collapsing it onto\n // the minimum keeps the position inside something that can be announced.\n return { min, max: Math.max(min, max) };\n }\n\n /** The declared position, clamped into the validated range. */\n get #position(): number {\n const { min, max } = this.#range;\n const value = this.#safeValue;\n return Math.max(min, Math.min(value, max));\n }\n\n /** The keyboard increment; a non-positive or unreadable one uses the default. */\n get #step(): number {\n return this.#safeStep;\n }\n\n /** Whether the divider runs vertically; a separator that does not say is horizontal. */\n get #isVertical(): boolean {\n return (\n this.hasSeparatorTarget &&\n this.separatorTarget.getAttribute(\"aria-orientation\") === \"vertical\"\n );\n }\n /** Current `min` declaration resolved against its numeric contract. */\n get #safeMin(): number {\n return this.#numbers.read(\n this,\n \"min\",\n this.minValue,\n ResizableController.values.min.default,\n ResizableController.valueConstraints.min,\n );\n }\n\n /** Current `max` declaration resolved against its numeric contract. */\n get #safeMax(): number {\n return this.#numbers.read(\n this,\n \"max\",\n this.maxValue,\n ResizableController.values.max.default,\n ResizableController.valueConstraints.max,\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 ResizableController.values.step.default,\n ResizableController.valueConstraints.step,\n );\n }\n\n /** Current `value` declaration resolved against its numeric contract. */\n get #safeValue(): number {\n return this.#numbers.read(\n this,\n \"value\",\n this.valueValue,\n ResizableController.values.value.default,\n ResizableController.valueConstraints.value,\n );\n }\n}\n"]}
@@ -1,13 +1,9 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
3
- // src/controllers/roving_controller.ts
4
-
5
- // src/utils/logical_scroll.ts
6
3
  function isRtl(element) {
7
4
  return window.getComputedStyle(element).direction === "rtl";
8
5
  }
9
6
 
10
- // src/utils/arrow_step.ts
11
7
  function isReservedArrowChord(event, allow = []) {
12
8
  if (!event.key.startsWith("Arrow")) return false;
13
9
  return event.altKey && !allow.includes("alt") || event.ctrlKey && !allow.includes("ctrl") || event.metaKey && !allow.includes("meta") || event.shiftKey && !allow.includes("shift");
@@ -16,13 +12,11 @@ function hasModifierChord(event) {
16
12
  return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
17
13
  }
18
14
 
19
- // src/utils/event_owner.ts
20
15
  function ownerIndex(candidates, node) {
21
16
  if (!(node instanceof Node)) return -1;
22
17
  return candidates.findIndex((candidate) => candidate.contains(node));
23
18
  }
24
19
 
25
- // src/utils/focus_candidate.ts
26
20
  function inheritsFieldsetDisabled(control) {
27
21
  let fieldset = control.closest("fieldset[disabled]");
28
22
  while (fieldset) {
@@ -33,27 +27,33 @@ function inheritsFieldsetDisabled(control) {
33
27
  return false;
34
28
  }
35
29
 
36
- // src/utils/microtask_coalescer.ts
30
+ var ListenerSet = class {
31
+ #abort = new AbortController();
32
+ add(target, type, handler, options) {
33
+ target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
34
+ }
35
+ dispose() {
36
+ this.#abort.abort();
37
+ this.#abort = new AbortController();
38
+ }
39
+ };
40
+
37
41
  var MicrotaskCoalescer = class {
38
42
  #run;
39
43
  #queued = false;
40
44
  #active = false;
41
45
  #generation = 0;
42
- /** @param run - the single reconciliation pass, invoked at most once per batch. */
43
46
  constructor(run) {
44
47
  this.#run = run;
45
48
  }
46
- /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
47
49
  activate() {
48
50
  this.#active = true;
49
51
  }
50
- /** Closes the window and drops any pending pass; call from `disconnect()`. */
51
52
  cancel() {
52
53
  this.#active = false;
53
54
  this.#queued = false;
54
55
  this.#generation += 1;
55
56
  }
56
- /** Requests one pass after the batch settles. Idempotent; inert outside the window. */
57
57
  schedule() {
58
58
  if (!this.#active || this.#queued) return;
59
59
  this.#queued = true;
@@ -66,31 +66,39 @@ var MicrotaskCoalescer = class {
66
66
  }
67
67
  };
68
68
 
69
- // src/utils/roving_tabindex.ts
69
+ var MorphRenderWatcher = class {
70
+ #listeners = new ListenerSet();
71
+ #pass;
72
+ #element = null;
73
+ #onMorph = () => this.#pass.schedule();
74
+ constructor(run) {
75
+ this.#pass = new MicrotaskCoalescer(run);
76
+ }
77
+ observe(element) {
78
+ if (this.#element === element) return;
79
+ this.disconnect();
80
+ this.#element = element;
81
+ this.#pass.activate();
82
+ this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
83
+ }
84
+ schedule() {
85
+ this.#pass.schedule();
86
+ }
87
+ disconnect() {
88
+ this.#listeners.dispose();
89
+ this.#pass.cancel();
90
+ this.#element = null;
91
+ }
92
+ };
93
+
70
94
  var RovingTabindex = class {
71
- /** Returns the current ordered item elements; called on every operation. */
72
95
  #getItems;
73
- /**
74
- * @param getItems - Returns the current ordered item elements. Called on every
75
- * operation so the live target list is always used.
76
- */
77
96
  constructor(getItems) {
78
97
  this.#getItems = getItems;
79
98
  }
80
- /** Index of the currently tabbable item (`tabindex="0"`), or `-1` if none. */
81
99
  get activeIndex() {
82
100
  return this.#getItems().findIndex((item) => item.tabIndex === 0);
83
101
  }
84
- /**
85
- * Makes exactly the item at `index` tabbable (`tabindex="0"`) and removes every
86
- * other item from the Tab sequence (`tabindex="-1"`). An out-of-range `index`
87
- * (e.g. `-1`) leaves all items at `-1`, which a controller can use to express
88
- * "nothing is currently tabbable".
89
- *
90
- * @param index - Position of the item to make tabbable.
91
- * @param options - Pass `{ focus: true }` to also move DOM focus to that item,
92
- * and `items` to reuse an event-scoped collection snapshot.
93
- */
94
102
  setActive(index, options = {}) {
95
103
  const { focus = false } = options;
96
104
  const items = options.items ?? this.#getItems();
@@ -107,7 +115,6 @@ function rovingMove(current, length, delta, wrap) {
107
115
  return Math.min(length - 1, Math.max(0, next));
108
116
  }
109
117
 
110
- // src/controllers/roving_controller.ts
111
118
  var STATE_ATTRIBUTES = ["disabled", "hidden"];
112
119
  var RovingController = class extends Controller {
113
120
  static targets = ["item"];
@@ -118,7 +125,7 @@ var RovingController = class extends Controller {
118
125
  };
119
126
  static events = ["change"];
120
127
  #roving = new RovingTabindex(() => this.itemTargets);
121
- #reconcile = new MicrotaskCoalescer(() => this.#ensureTabStop(true));
128
+ #reconcile = new MorphRenderWatcher(() => this.#ensureTabStop(true));
122
129
  #connected = false;
123
130
  #observer = null;
124
131
  connect() {
@@ -127,27 +134,24 @@ var RovingController = class extends Controller {
127
134
  this.element.addEventListener("focusin", this.#onFocusin);
128
135
  this.#watchState();
129
136
  this.#connected = true;
130
- this.#reconcile.activate();
137
+ this.#reconcile.observe(this.element);
131
138
  }
132
139
  disconnect() {
133
140
  this.#connected = false;
134
- this.#reconcile.cancel();
141
+ this.#reconcile.disconnect();
135
142
  this.element.removeEventListener("keydown", this.#onKeydown);
136
143
  this.element.removeEventListener("focusin", this.#onFocusin);
137
144
  this.#observer?.disconnect();
138
145
  this.#observer = null;
139
146
  }
140
- /** Drops a runtime-added item from the Tab sequence before batch reconciliation. */
141
147
  itemTargetConnected(item) {
142
148
  if (!this.#connected) return;
143
149
  item.tabIndex = -1;
144
150
  this.#reconcile.schedule();
145
151
  }
146
- /** Re-establishes the single Tab stop after an item leaves the target set. */
147
152
  itemTargetDisconnected() {
148
153
  this.#reconcile.schedule();
149
154
  }
150
- /** Arrow keys move focus + the tab stop; Home/End jump to the ends. */
151
155
  #onKeydown = (event) => {
152
156
  if (event.defaultPrevented) return;
153
157
  if (isReservedArrowChord(event)) return;
@@ -176,21 +180,14 @@ var RovingController = class extends Controller {
176
180
  event.preventDefault();
177
181
  this.#activate(next, true);
178
182
  };
179
- /**
180
- * Syncs the single tab stop to an item that received focus by other means
181
- * (click, programmatic `focus()`), so returning via Tab lands on it. The
182
- * keyboard path's own `focus()` re-enters here but is a no-op (index unchanged).
183
- */
184
183
  #onFocusin = (event) => {
185
184
  const index = this.#indexOf(event.target);
186
185
  if (index === -1 || !this.#reachable(index)) return;
187
186
  this.#activate(index, false);
188
187
  };
189
- /** Resolves the item index owning an event target (the item or a descendant). */
190
188
  #indexOf(target) {
191
189
  return ownerIndex(this.itemTargets, target);
192
190
  }
193
- /** Makes `index` the tab stop (optionally focusing it), emitting `change` once. */
194
191
  #activate(index, focus) {
195
192
  const previous = this.#roving.activeIndex;
196
193
  this.#roving.setActive(index, { focus });
@@ -198,16 +195,6 @@ var RovingController = class extends Controller {
198
195
  this.dispatch("change", { detail: { index, item: this.itemTargets[index] } });
199
196
  }
200
197
  }
201
- /**
202
- * Keeps the Tab stop on a reachable item.
203
- *
204
- * `followFocus` is on for re-establishment only: an item added and focused in
205
- * the same task has already claimed the stop through `focusin`, and the batch
206
- * that follows must not hand it back to the first item. `connect()` passes it
207
- * off so the authored DOM decides the initial stop. With nothing reachable the
208
- * DOM is left as it is — a group inside a collapsed region gets its stop back
209
- * when the region opens, instead of losing it for good.
210
- */
211
198
  #ensureTabStop(followFocus) {
212
199
  const items = this.itemTargets;
213
200
  const focused = followFocus ? items.findIndex((item, i) => item === document.activeElement && this.#reachable(i)) : -1;
@@ -217,15 +204,6 @@ var RovingController = class extends Controller {
217
204
  if (index === -1) return;
218
205
  this.#roving.setActive(index);
219
206
  }
220
- /**
221
- * Resolves the next reachable index in `delta`'s direction, honouring `wrap`.
222
- *
223
- * An arrow on the widget's own axis is the widget's to consume even when the
224
- * position does not change, so a clamped end resolves to the current item
225
- * rather than to nothing. An unreachable origin escapes to the first reachable
226
- * item instead of sitting in a dead end, and `-1` is left for the one case that
227
- * really is not ours: no reachable item anywhere.
228
- */
229
207
  #step(current, delta, wrap) {
230
208
  const length = this.itemTargets.length;
231
209
  let index = current;
@@ -237,23 +215,15 @@ var RovingController = class extends Controller {
237
215
  }
238
216
  return this.#reachable(current) ? current : this.#firstReachable();
239
217
  }
240
- /** Index of the first reachable item, or `-1`. */
241
218
  #firstReachable() {
242
219
  return this.itemTargets.findIndex((_item, i) => this.#reachable(i));
243
220
  }
244
- /** Index of the last reachable item, or `-1`. */
245
221
  #lastReachable() {
246
222
  for (let i = this.itemTargets.length - 1; i >= 0; i -= 1) {
247
223
  if (this.#reachable(i)) return i;
248
224
  }
249
225
  return -1;
250
226
  }
251
- /**
252
- * Whether the item at `index` can hold the Tab stop and take focus.
253
- *
254
- * `aria-disabled` is deliberately not consulted: it keeps an item reachable and
255
- * only suppresses activation, which this part does not own.
256
- */
257
227
  #reachable(index) {
258
228
  const item = this.itemTargets[index];
259
229
  if (!item) return false;
@@ -262,14 +232,6 @@ var RovingController = class extends Controller {
262
232
  if (item.disabled) return false;
263
233
  return !inheritsFieldsetDisabled(item);
264
234
  }
265
- /**
266
- * Whether `item`, or anything between it and the container, is `hidden`.
267
- *
268
- * The walk stops at the container on purpose: a group inside a hidden region is
269
- * already out of the page's Tab order, and calling every item unreachable there
270
- * would drop the stop with nothing left to restore it — the ancestor lies
271
- * outside the subtree whose state attributes are watched.
272
- */
273
235
  #hidden(item) {
274
236
  let node = item;
275
237
  while (node && node !== this.element) {
@@ -278,12 +240,6 @@ var RovingController = class extends Controller {
278
240
  }
279
241
  return false;
280
242
  }
281
- /**
282
- * Watches the attributes that decide reachability, so disabling the item that
283
- * holds the Tab stop hands it to another one instead of taking the whole set
284
- * out of the Tab sequence. An enclosing `fieldset` disables items from outside
285
- * the observed subtree, so each one's own `disabled` is watched too.
286
- */
287
243
  #watchState() {
288
244
  if (typeof MutationObserver === "undefined") return;
289
245
  const observer = new MutationObserver(() => this.#reconcile.schedule());
@@ -300,5 +256,4 @@ var RovingController = class extends Controller {
300
256
  };
301
257
 
302
258
  export { RovingController };
303
- //# sourceMappingURL=roving_controller.js.map
304
259
  //# sourceMappingURL=roving_controller.js.map