stimeo-ui 0.17.0 → 0.18.1

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 (299) hide show
  1. package/CHANGELOG.md +136 -2
  2. package/README.md +19 -10
  3. package/dist/cable/index.d.ts +11 -9
  4. package/dist/cable/index.js +22 -14
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/coerce-JtZVNG5h.d.ts +20 -0
  7. package/dist/controllers/accordion_controller.js +14 -6
  8. package/dist/controllers/accordion_controller.js.map +1 -1
  9. package/dist/controllers/alert_dialog_controller.js +145 -118
  10. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  11. package/dist/controllers/announcer_controller.d.ts +5 -3
  12. package/dist/controllers/announcer_controller.js +113 -17
  13. package/dist/controllers/announcer_controller.js.map +1 -1
  14. package/dist/controllers/auto_submit_controller.js +185 -60
  15. package/dist/controllers/auto_submit_controller.js.map +1 -1
  16. package/dist/controllers/avatar_controller.js +55 -43
  17. package/dist/controllers/avatar_controller.js.map +1 -1
  18. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  19. package/dist/controllers/bulk_select_controller.d.ts +3 -3
  20. package/dist/controllers/bulk_select_controller.js +64 -50
  21. package/dist/controllers/bulk_select_controller.js.map +1 -1
  22. package/dist/controllers/calendar_controller.d.ts +15 -12
  23. package/dist/controllers/calendar_controller.js +55 -53
  24. package/dist/controllers/calendar_controller.js.map +1 -1
  25. package/dist/controllers/carousel_controller.d.ts +9 -5
  26. package/dist/controllers/carousel_controller.js +124 -86
  27. package/dist/controllers/carousel_controller.js.map +1 -1
  28. package/dist/controllers/character_counter_controller.d.ts +27 -6
  29. package/dist/controllers/character_counter_controller.js +291 -95
  30. package/dist/controllers/character_counter_controller.js.map +1 -1
  31. package/dist/controllers/checkbox_controller.js +6 -0
  32. package/dist/controllers/checkbox_controller.js.map +1 -1
  33. package/dist/controllers/clipboard_controller.js +118 -27
  34. package/dist/controllers/clipboard_controller.js.map +1 -1
  35. package/dist/controllers/collapsible_controller.d.ts +1 -1
  36. package/dist/controllers/collapsible_controller.js +52 -49
  37. package/dist/controllers/collapsible_controller.js.map +1 -1
  38. package/dist/controllers/color_picker_controller.js +29 -7
  39. package/dist/controllers/color_picker_controller.js.map +1 -1
  40. package/dist/controllers/combobox_controller.d.ts +1 -1
  41. package/dist/controllers/combobox_controller.js +210 -71
  42. package/dist/controllers/combobox_controller.js.map +1 -1
  43. package/dist/controllers/command_palette_controller.d.ts +9 -9
  44. package/dist/controllers/command_palette_controller.js +290 -140
  45. package/dist/controllers/command_palette_controller.js.map +1 -1
  46. package/dist/controllers/conditional_fields_controller.js +145 -58
  47. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  48. package/dist/controllers/confirm_controller.js +145 -118
  49. package/dist/controllers/confirm_controller.js.map +1 -1
  50. package/dist/controllers/context_menu_controller.d.ts +49 -14
  51. package/dist/controllers/context_menu_controller.js +138 -73
  52. package/dist/controllers/context_menu_controller.js.map +1 -1
  53. package/dist/controllers/count_up_controller.js.map +1 -1
  54. package/dist/controllers/countdown_controller.d.ts +2 -2
  55. package/dist/controllers/countdown_controller.js +109 -21
  56. package/dist/controllers/countdown_controller.js.map +1 -1
  57. package/dist/controllers/currency_input_controller.d.ts +75 -11
  58. package/dist/controllers/currency_input_controller.js +446 -72
  59. package/dist/controllers/currency_input_controller.js.map +1 -1
  60. package/dist/controllers/data_grid_controller.d.ts +10 -8
  61. package/dist/controllers/data_grid_controller.js +134 -28
  62. package/dist/controllers/data_grid_controller.js.map +1 -1
  63. package/dist/controllers/date_range_picker_controller.d.ts +12 -9
  64. package/dist/controllers/date_range_picker_controller.js +93 -72
  65. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  66. package/dist/controllers/dialog_controller.d.ts +4 -5
  67. package/dist/controllers/dialog_controller.js +145 -118
  68. package/dist/controllers/dialog_controller.js.map +1 -1
  69. package/dist/controllers/direct_upload_controller.d.ts +1 -1
  70. package/dist/controllers/direct_upload_controller.js +24 -14
  71. package/dist/controllers/direct_upload_controller.js.map +1 -1
  72. package/dist/controllers/dirty_form_controller.d.ts +6 -1
  73. package/dist/controllers/dirty_form_controller.js +68 -31
  74. package/dist/controllers/dirty_form_controller.js.map +1 -1
  75. package/dist/controllers/dismissible_controller.js +66 -46
  76. package/dist/controllers/dismissible_controller.js.map +1 -1
  77. package/dist/controllers/drawer_controller.js +145 -118
  78. package/dist/controllers/drawer_controller.js.map +1 -1
  79. package/dist/controllers/dropdown_controller.js +76 -63
  80. package/dist/controllers/dropdown_controller.js.map +1 -1
  81. package/dist/controllers/editable_controller.js +200 -62
  82. package/dist/controllers/editable_controller.js.map +1 -1
  83. package/dist/controllers/empty_state_controller.js +13 -6
  84. package/dist/controllers/empty_state_controller.js.map +1 -1
  85. package/dist/controllers/file_dropzone_controller.d.ts +3 -0
  86. package/dist/controllers/file_dropzone_controller.js +55 -48
  87. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  88. package/dist/controllers/filter_controller.js +9 -2
  89. package/dist/controllers/filter_controller.js.map +1 -1
  90. package/dist/controllers/flash_controller.d.ts +4 -4
  91. package/dist/controllers/flash_controller.js +66 -33
  92. package/dist/controllers/flash_controller.js.map +1 -1
  93. package/dist/controllers/focus_controller.d.ts +3 -3
  94. package/dist/controllers/focus_controller.js +39 -14
  95. package/dist/controllers/focus_controller.js.map +1 -1
  96. package/dist/controllers/form_field_controller.d.ts +2 -1
  97. package/dist/controllers/form_field_controller.js +52 -43
  98. package/dist/controllers/form_field_controller.js.map +1 -1
  99. package/dist/controllers/form_validation_controller.d.ts +3 -3
  100. package/dist/controllers/form_validation_controller.js +18 -11
  101. package/dist/controllers/form_validation_controller.js.map +1 -1
  102. package/dist/controllers/frame_loading_controller.d.ts +13 -12
  103. package/dist/controllers/frame_loading_controller.js +55 -48
  104. package/dist/controllers/frame_loading_controller.js.map +1 -1
  105. package/dist/controllers/highlight_controller.d.ts +5 -4
  106. package/dist/controllers/highlight_controller.js.map +1 -1
  107. package/dist/controllers/hover_card_controller.d.ts +4 -1
  108. package/dist/controllers/hover_card_controller.js +67 -61
  109. package/dist/controllers/hover_card_controller.js.map +1 -1
  110. package/dist/controllers/idle_controller.d.ts +6 -5
  111. package/dist/controllers/idle_controller.js +10 -6
  112. package/dist/controllers/idle_controller.js.map +1 -1
  113. package/dist/controllers/input_mask_controller.d.ts +31 -13
  114. package/dist/controllers/input_mask_controller.js +434 -24
  115. package/dist/controllers/input_mask_controller.js.map +1 -1
  116. package/dist/controllers/intersection_controller.js +3 -0
  117. package/dist/controllers/intersection_controller.js.map +1 -1
  118. package/dist/controllers/lazy_frame_controller.d.ts +3 -2
  119. package/dist/controllers/lazy_frame_controller.js +15 -3
  120. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  121. package/dist/controllers/listbox_controller.d.ts +10 -7
  122. package/dist/controllers/listbox_controller.js +260 -79
  123. package/dist/controllers/listbox_controller.js.map +1 -1
  124. package/dist/controllers/local_time_controller.d.ts +8 -6
  125. package/dist/controllers/local_time_controller.js +48 -13
  126. package/dist/controllers/local_time_controller.js.map +1 -1
  127. package/dist/controllers/masonry_controller.js +11 -4
  128. package/dist/controllers/masonry_controller.js.map +1 -1
  129. package/dist/controllers/menu_controller.d.ts +24 -5
  130. package/dist/controllers/menu_controller.js +138 -82
  131. package/dist/controllers/menu_controller.js.map +1 -1
  132. package/dist/controllers/menubar_controller.d.ts +49 -7
  133. package/dist/controllers/menubar_controller.js +65 -19
  134. package/dist/controllers/menubar_controller.js.map +1 -1
  135. package/dist/controllers/meter_controller.d.ts +13 -20
  136. package/dist/controllers/meter_controller.js +270 -24
  137. package/dist/controllers/meter_controller.js.map +1 -1
  138. package/dist/controllers/multi_select_controller.d.ts +19 -16
  139. package/dist/controllers/multi_select_controller.js +272 -95
  140. package/dist/controllers/multi_select_controller.js.map +1 -1
  141. package/dist/controllers/navigation_menu_controller.d.ts +19 -5
  142. package/dist/controllers/navigation_menu_controller.js +67 -19
  143. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  144. package/dist/controllers/nested_form_controller.js +98 -64
  145. package/dist/controllers/nested_form_controller.js.map +1 -1
  146. package/dist/controllers/network_status_controller.js +70 -52
  147. package/dist/controllers/network_status_controller.js.map +1 -1
  148. package/dist/controllers/number_input_controller.d.ts +24 -6
  149. package/dist/controllers/number_input_controller.js +344 -94
  150. package/dist/controllers/number_input_controller.js.map +1 -1
  151. package/dist/controllers/optimistic_controller.d.ts +8 -5
  152. package/dist/controllers/optimistic_controller.js +29 -11
  153. package/dist/controllers/optimistic_controller.js.map +1 -1
  154. package/dist/controllers/otp_controller.d.ts +35 -4
  155. package/dist/controllers/otp_controller.js +502 -104
  156. package/dist/controllers/otp_controller.js.map +1 -1
  157. package/dist/controllers/overflow_indicator_controller.js +6 -0
  158. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  159. package/dist/controllers/overflow_menu_controller.d.ts +10 -9
  160. package/dist/controllers/overflow_menu_controller.js +136 -21
  161. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  162. package/dist/controllers/pagination_controller.d.ts +3 -2
  163. package/dist/controllers/pagination_controller.js +47 -14
  164. package/dist/controllers/pagination_controller.js.map +1 -1
  165. package/dist/controllers/password_reveal_controller.d.ts +5 -4
  166. package/dist/controllers/password_reveal_controller.js +52 -49
  167. package/dist/controllers/password_reveal_controller.js.map +1 -1
  168. package/dist/controllers/password_strength_controller.d.ts +1 -1
  169. package/dist/controllers/password_strength_controller.js +13 -6
  170. package/dist/controllers/password_strength_controller.js.map +1 -1
  171. package/dist/controllers/persist_controller.js +48 -128
  172. package/dist/controllers/persist_controller.js.map +1 -1
  173. package/dist/controllers/pointer_drag_controller.d.ts +20 -8
  174. package/dist/controllers/pointer_drag_controller.js +255 -24
  175. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  176. package/dist/controllers/popover_controller.d.ts +9 -5
  177. package/dist/controllers/popover_controller.js +91 -65
  178. package/dist/controllers/popover_controller.js.map +1 -1
  179. package/dist/controllers/portal_controller.js +6 -0
  180. package/dist/controllers/portal_controller.js.map +1 -1
  181. package/dist/controllers/preview_guard_controller.js +14 -3
  182. package/dist/controllers/preview_guard_controller.js.map +1 -1
  183. package/dist/controllers/progress_controller.d.ts +9 -19
  184. package/dist/controllers/progress_controller.js +271 -27
  185. package/dist/controllers/progress_controller.js.map +1 -1
  186. package/dist/controllers/radio_group_controller.d.ts +11 -8
  187. package/dist/controllers/radio_group_controller.js +167 -80
  188. package/dist/controllers/radio_group_controller.js.map +1 -1
  189. package/dist/controllers/range_slider_controller.d.ts +4 -3
  190. package/dist/controllers/range_slider_controller.js +27 -7
  191. package/dist/controllers/range_slider_controller.js.map +1 -1
  192. package/dist/controllers/rating_controller.js +93 -57
  193. package/dist/controllers/rating_controller.js.map +1 -1
  194. package/dist/controllers/read_more_controller.js +10 -6
  195. package/dist/controllers/read_more_controller.js.map +1 -1
  196. package/dist/controllers/reading_progress_controller.js +22 -5
  197. package/dist/controllers/reading_progress_controller.js.map +1 -1
  198. package/dist/controllers/relative_time_controller.d.ts +4 -4
  199. package/dist/controllers/relative_time_controller.js +75 -11
  200. package/dist/controllers/relative_time_controller.js.map +1 -1
  201. package/dist/controllers/reset_on_restore_controller.d.ts +3 -3
  202. package/dist/controllers/reset_on_restore_controller.js +6 -0
  203. package/dist/controllers/reset_on_restore_controller.js.map +1 -1
  204. package/dist/controllers/resizable_controller.d.ts +3 -0
  205. package/dist/controllers/resizable_controller.js +55 -22
  206. package/dist/controllers/resizable_controller.js.map +1 -1
  207. package/dist/controllers/roving_controller.d.ts +3 -3
  208. package/dist/controllers/roving_controller.js +10 -4
  209. package/dist/controllers/roving_controller.js.map +1 -1
  210. package/dist/controllers/scroll_area_controller.js +129 -88
  211. package/dist/controllers/scroll_area_controller.js.map +1 -1
  212. package/dist/controllers/scroll_restore_controller.d.ts +3 -3
  213. package/dist/controllers/scroll_restore_controller.js +14 -2
  214. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  215. package/dist/controllers/scroll_visibility_controller.js +93 -60
  216. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  217. package/dist/controllers/scrollspy_controller.js +11 -5
  218. package/dist/controllers/scrollspy_controller.js.map +1 -1
  219. package/dist/controllers/separator_controller.d.ts +1 -1
  220. package/dist/controllers/separator_controller.js +59 -43
  221. package/dist/controllers/separator_controller.js.map +1 -1
  222. package/dist/controllers/sidebar_controller.d.ts +1 -1
  223. package/dist/controllers/sidebar_controller.js +150 -122
  224. package/dist/controllers/sidebar_controller.js.map +1 -1
  225. package/dist/controllers/skeleton_controller.js +55 -48
  226. package/dist/controllers/skeleton_controller.js.map +1 -1
  227. package/dist/controllers/slider_controller.d.ts +2 -1
  228. package/dist/controllers/slider_controller.js +27 -6
  229. package/dist/controllers/slider_controller.js.map +1 -1
  230. package/dist/controllers/smart_sticky_header_controller.d.ts +1 -1
  231. package/dist/controllers/smart_sticky_header_controller.js +13 -5
  232. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  233. package/dist/controllers/sortable_controller.d.ts +4 -4
  234. package/dist/controllers/sortable_controller.js +27 -14
  235. package/dist/controllers/sortable_controller.js.map +1 -1
  236. package/dist/controllers/spinner_controller.js +55 -48
  237. package/dist/controllers/spinner_controller.js.map +1 -1
  238. package/dist/controllers/step_indicator_controller.d.ts +4 -4
  239. package/dist/controllers/step_indicator_controller.js +6 -0
  240. package/dist/controllers/step_indicator_controller.js.map +1 -1
  241. package/dist/controllers/stepper_controller.d.ts +2 -3
  242. package/dist/controllers/stepper_controller.js +6 -0
  243. package/dist/controllers/stepper_controller.js.map +1 -1
  244. package/dist/controllers/stick_to_bottom_controller.d.ts +3 -1
  245. package/dist/controllers/stick_to_bottom_controller.js +19 -8
  246. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  247. package/dist/controllers/sticky_observer_controller.js +49 -43
  248. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  249. package/dist/controllers/submit_once_controller.d.ts +2 -1
  250. package/dist/controllers/submit_once_controller.js +145 -85
  251. package/dist/controllers/submit_once_controller.js.map +1 -1
  252. package/dist/controllers/switch_controller.d.ts +7 -4
  253. package/dist/controllers/switch_controller.js +172 -28
  254. package/dist/controllers/switch_controller.js.map +1 -1
  255. package/dist/controllers/tabs_controller.d.ts +7 -4
  256. package/dist/controllers/tabs_controller.js +6 -1
  257. package/dist/controllers/tabs_controller.js.map +1 -1
  258. package/dist/controllers/tags_input_controller.d.ts +4 -3
  259. package/dist/controllers/tags_input_controller.js +157 -28
  260. package/dist/controllers/tags_input_controller.js.map +1 -1
  261. package/dist/controllers/textarea_autosize_controller.d.ts +1 -1
  262. package/dist/controllers/textarea_autosize_controller.js +40 -19
  263. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  264. package/dist/controllers/theme_controller.d.ts +3 -2
  265. package/dist/controllers/theme_controller.js +10 -4
  266. package/dist/controllers/theme_controller.js.map +1 -1
  267. package/dist/controllers/time_picker_controller.d.ts +38 -5
  268. package/dist/controllers/time_picker_controller.js +192 -54
  269. package/dist/controllers/time_picker_controller.js.map +1 -1
  270. package/dist/controllers/toast_controller.d.ts +4 -5
  271. package/dist/controllers/toast_controller.js +58 -27
  272. package/dist/controllers/toast_controller.js.map +1 -1
  273. package/dist/controllers/toggle_group_controller.d.ts +2 -3
  274. package/dist/controllers/toggle_group_controller.js +158 -56
  275. package/dist/controllers/toggle_group_controller.js.map +1 -1
  276. package/dist/controllers/toolbar_controller.d.ts +8 -6
  277. package/dist/controllers/toolbar_controller.js +150 -21
  278. package/dist/controllers/toolbar_controller.js.map +1 -1
  279. package/dist/controllers/tooltip_controller.d.ts +4 -1
  280. package/dist/controllers/tooltip_controller.js.map +1 -1
  281. package/dist/controllers/transition_controller.js.map +1 -1
  282. package/dist/controllers/tree_view_controller.d.ts +1 -1
  283. package/dist/controllers/tree_view_controller.js +134 -25
  284. package/dist/controllers/tree_view_controller.js.map +1 -1
  285. package/dist/index.d.ts +4 -1
  286. package/dist/index.js +2515 -1315
  287. package/dist/index.js.map +1 -1
  288. package/dist/inspector/cli.d.ts +25 -12
  289. package/dist/inspector/cli.js +21 -3
  290. package/dist/inspector/cli.js.map +1 -1
  291. package/dist/inspector/cli_bin.d.ts +1 -1
  292. package/dist/inspector/cli_bin.js +62 -8
  293. package/dist/inspector/cli_bin.js.map +1 -1
  294. package/dist/inspector/examples.json +13 -13
  295. package/dist/inspector/manifest.json +19 -5
  296. package/dist/positioning/index.d.ts +9 -8
  297. package/dist/positioning/index.js +6 -0
  298. package/dist/positioning/index.js.map +1 -1
  299. package/package.json +11 -10
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/shared_registry.ts","../../src/utils/attribute_lease.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/timer_bounds.ts","../../src/utils/number_bounds.ts","../../src/utils/coerce.ts","../../src/utils/number_value.ts","../../src/utils/safe_storage.ts","../../src/utils/safe_timeout.ts","../../src/utils/string_list.ts","../../src/utils/transient_hooks.ts","../../src/controllers/persist_controller.ts"],"names":[],"mappings":"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","file":"persist_controller.js","sourcesContent":["/**\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 { sharedRegistry } from \"./shared_registry\";\n\n/** What a lease's record says: the author's value, its last write, the leases beneath. */\ninterface AttributeLeaseRecord {\n readonly original: string | null;\n readonly written: string | null;\n /** Whether it hands back what the lease right beneath it wrote last. */\n readonly linked: boolean;\n /** The records of the other owners' leases beneath it, nearest first. */\n readonly beneath: readonly string[];\n}\n\n/** One lease's hold on one element's attribute, in the stack every lease of it shares. */\ninterface AttributeHold {\n /** The lease holding it; `null` for a hold read from a copy's record until its lease takes it. */\n lease: object | null;\n readonly record: string;\n written: string | null;\n /** What it hands back with nothing beneath it: the author's value. */\n readonly original: string | null;\n /** Whether it hands back what the hold beneath it wrote last instead. */\n linked: boolean;\n}\n\n/** The holds on each element by attribute, and every lease's record name by attribute. */\ninterface AttributeLeaseRegistry {\n readonly stacks: WeakMap<Element, Map<string, AttributeHold[]>>;\n readonly names: Map<string, Set<string>>;\n}\n\n/** Whether a parsed record entry is an attribute value: a string, or `null` for absence. */\nfunction isAttributeValue(value: unknown): value is string | null {\n return value === null || typeof value === \"string\";\n}\n\n/**\n * Reads the record a lease left on `element`: the author's value, the value the lease wrote\n * last, whether it hands back the value beneath it (`false` before the names when it does not)\n * and the records beneath it. `undefined` when the record is missing or holds anything else.\n */\nfunction readLeaseRecord(element: Element, record: string): AttributeLeaseRecord | undefined {\n try {\n const parsed: unknown = JSON.parse(element.getAttribute(record) ?? \"null\");\n if (!Array.isArray(parsed)) return undefined;\n const [original, written, ...rest] = parsed as unknown[];\n const linked = rest[0] !== false;\n const beneath = linked ? rest : rest.slice(1);\n if (!beneath.every((under): under is string => typeof under === \"string\")) return undefined;\n return isAttributeValue(original) && isAttributeValue(written)\n ? { original, written, linked, beneath }\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The value `element`'s author wrote for `attribute`, as the record a lease of any owner leaves\n * on the element carries it; `undefined` while no lease leaves one, as when nothing has moved\n * the attribute off the author's value. A field a reveal turned from `password` into `text`\n * still reads `\"password\"` here.\n */\nexport function leasedAuthorValue(element: Element, attribute: string): string | null | undefined {\n const suffix = `-${attribute}-lease`;\n for (const name of element.getAttributeNames()) {\n if (!name.startsWith(\"data-\") || !name.endsWith(suffix)) continue;\n const record = readLeaseRecord(element, name);\n if (record) return record.original;\n }\n return undefined;\n}\n\n/**\n * Temporarily controls one attribute across a changing set of elements.\n *\n * The first write remembers the authored value, including the distinction between\n * an absent attribute and an authored empty string. Returning a lease restores that\n * value only while the attribute still matches the controller's last write. If a\n * consumer changed it in the meantime, the consumer owns the new value and teardown\n * leaves it alone.\n *\n * A `null` write deliberately removes the attribute while retaining the lease. This\n * is useful for derived ARIA whose valid absence is itself controller state, such as\n * an unbounded `aria-valuemin` or a blank spinbutton's `aria-valuenow`.\n *\n * **Every lease of an attribute shares one stack of holds per element**, whatever its owner\n * and whichever file of the package constructed it (the stacks are one per page): the holds\n * sit in the order their leases first wrote the element, each with the value it wrote last.\n * The element's value is the highest hold's that carries it, and the page's when none does.\n * A write reaches the element unless a hold above the writer carries the element's value: the\n * top hold always shows its writes, a hold beneath it shows nothing while a hold above keeps\n * its value on the element, and once the page has put a value there that no hold carries, the\n * next write of any hold replaces it. A return gives a value back only from the hold the\n * element's value is: the value the hold beneath it wrote last, or the author's once nothing\n * is beneath it; any other return only leaves the stack, and the page's value stays. Holds\n * that wrote the same value are told apart by the stack, never by the value: the higher one\n * keeps it. A first write over a top hold whose value the page has replaced takes the\n * element's value as the author's. Two instances of one controller on one element — an\n * element outside their scope — stack the same way.\n *\n * A **base lease** (`{ base: true }`) holds the element's own state rather than a value over\n * it — a form field's ARIA on its control is one — so its first write goes to the bottom of\n * the stack, beneath the leases of other owners already there: a temporary value another\n * owner leased stays shown and returns to the base lease's latest value.\n *\n * **The stack travels with the element.** While a hold shows a value other than the author's,\n * lies on another hold or is covered by one, the element carries its owner's record\n * `data-<owner>-<attribute>-lease`: JSON of the author's value and the value the hold wrote\n * last (each a string, or `null` for an absent attribute), `false` where the hold hands back\n * the author's value rather than the latest value of the hold beneath it, and the records of\n * every hold beneath it, nearest first. Returning the last lease of an owner removes its\n * record. A copy of the element — a page Turbo restores from its cache is one — therefore\n * carries the stack, and the first lease to touch the copy reads it back under the record\n * names of the leases constructed so far, which include every lease that wrote a record the\n * cache holds, and orders the holds by the records each one lists beneath it. Each lease takes\n * the hold its owner's record describes over in place. Complete records for distinct owners\n * preserve their order across a copy. The records describe holds by owner, not by instance:\n * one owner holding the element more than once leaves only its topmost hold's record, which\n * the first of its leases to write or return on the copy takes. Lower holds of that owner and\n * their positions are absent; mutually listed owners cannot express their full live order.\n * A hold that showed the author's value alone carries no record and is taken by its first\n * write on the copy. Missing or unreadable records also leave their holds unknown, so copying\n * the DOM does not promise identical decisions for every live stack. Without a record it can\n * read, a new stack takes the current value as the author's. A Turbo morph removes records\n * absent from the server HTML; existing holds remain in memory until their leases return.\n *\n * The lease has no lifecycle of its own, so it never subscribes to document events,\n * and nothing rewinds a live page before Turbo caches it: `turbo:before-cache` also\n * fires on pages that stay.\n */\nexport class AttributeLease<T extends Element = Element> {\n /** The holds on each element, bottom first, and the record names; one per page. */\n static readonly #registry = sharedRegistry(\n \"stimeo-ui.attribute-lease.registry.v1\",\n (): AttributeLeaseRegistry => ({ stacks: new WeakMap(), names: new Map() }),\n );\n readonly #attribute: string;\n readonly #record: string;\n readonly #base: boolean;\n readonly #held = new Set<T>();\n\n /**\n * @param attribute - The attribute whose temporary values this lease owns.\n * @param owner - Names the record on the element; the controller's identifier.\n * @param options - `base`: written beneath the other owners' leases.\n */\n constructor(attribute: string, owner: string, options: { readonly base?: boolean } = {}) {\n this.#attribute = attribute;\n this.#record = `data-${owner}-${attribute}-lease`;\n this.#base = options.base === true;\n const names = AttributeLease.#registry.names;\n names.set(attribute, (names.get(attribute) ?? new Set<string>()).add(this.#record));\n }\n\n /** Writes or removes the leased attribute while preserving its authored value. */\n write(element: T, value: string | null): void {\n const stack = this.#stack(element);\n const hold = this.#take(stack) ?? this.#acquire(element, stack);\n this.#held.add(element);\n const shows = !this.#covered(element, stack, hold);\n hold.written = value;\n this.#mark(element, stack);\n if (shows) this.#reflect(element, value);\n }\n\n /**\n * Returns one lease, also on a restored copy, to the value the hold beneath it wrote last or\n * the author's, without overwriting a value a consumer wrote since. Says whether there was a\n * lease to return: a hold this lease has, or the hold a copy's record describes while no live\n * lease of the owner has taken it — a copy of a page an earlier connection wrote carries one.\n */\n return(element: T): boolean {\n const held = this.#held.delete(element);\n const known = AttributeLease.#registry.stacks.get(element)?.has(this.#attribute);\n const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];\n const hold = this.#take(stack);\n if (!hold) return false;\n const carries = element.getAttribute(this.#attribute) === hold.written;\n const owns = carries && !this.#covered(element, stack, hold);\n const index = stack.indexOf(hold);\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 true;\n const below = hold.linked ? stack[index - 1] : undefined;\n this.#reflect(element, below ? below.written : hold.original);\n return true;\n }\n\n /** Returns every lease it holds, with the same ownership check as {@link return}. */\n returnAll(): void {\n for (const element of Array.from(this.#held)) this.return(element);\n }\n\n /** The element's stack, read from its records the first time. */\n #stack(element: T): AttributeHold[] {\n const stacks = AttributeLease.#registry.stacks;\n const byAttribute = stacks.get(element) ?? new Map<string, AttributeHold[]>();\n stacks.set(element, byAttribute);\n const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);\n byAttribute.set(this.#attribute, stack);\n return stack;\n }\n\n /** The holds a copy's records describe, each above every hold its record lists beneath. */\n #seed(element: T): AttributeHold[] {\n const found: (AttributeLeaseRecord & { readonly record: string })[] = [];\n for (const record of AttributeLease.#registry.names.get(this.#attribute) ?? []) {\n const read = readLeaseRecord(element, record);\n if (read) found.push({ ...read, record });\n }\n const depth = ({ beneath }: (typeof found)[number]) =>\n beneath.filter((name) => found.some((other) => other.record === name)).length;\n return found\n .sort((one, other) => depth(one) - depth(other))\n .map(({ record, written, original, linked }, index) => ({\n lease: null,\n record,\n written,\n original,\n linked: linked && index > 0,\n }));\n }\n\n /** Its hold in `stack`, taking over one read from its record. */\n #take(stack: AttributeHold[]): AttributeHold | undefined {\n const hold =\n stack.find((held) => held.lease === this) ??\n stack.find((held) => held.lease === null && held.record === this.#record);\n if (hold) hold.lease = this;\n return hold;\n }\n\n /** A new hold: on top, over the top hold while the element shows it; a base one at the bottom. */\n #acquire(element: T, stack: AttributeHold[]): AttributeHold {\n const current = element.getAttribute(this.#attribute);\n const top = stack.at(-1);\n const bottom = stack[0];\n const over = top?.written === current ? top : undefined;\n const from = this.#base ? bottom : over;\n const hold: AttributeHold = {\n lease: this,\n record: this.#record,\n written: current,\n original: from ? from.original : current,\n linked: !this.#base && over !== undefined,\n };\n if (this.#base && bottom) {\n bottom.linked = true;\n stack.unshift(hold);\n } else stack.push(hold);\n return hold;\n }\n\n /** Whether a hold above `hold` carries the element's value, which is then that hold's. */\n #covered(element: T, stack: readonly AttributeHold[], hold: AttributeHold): boolean {\n const current = element.getAttribute(this.#attribute);\n return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);\n }\n\n /** Leaves each owner's record of its topmost hold, or none where nothing needs one. */\n #mark(element: T, stack: readonly AttributeHold[]): void {\n const records = new Map<string, string | null>([[this.#record, null]]);\n stack.forEach((hold, index) => {\n const names = stack.slice(0, index).map((under) => under.record);\n const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);\n const marker = hold.linked || beneath.length === 0 ? [] : [false];\n records.set(\n hold.record,\n hold.written === hold.original && beneath.length === 0 && index === stack.length - 1\n ? null\n : JSON.stringify([hold.original, hold.written, ...marker, ...beneath]),\n );\n });\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 /** Reflects only a real value transition, avoiding self-triggered mutation work. */\n #reflect(element: T, value: string | null): void {\n if (element.getAttribute(this.#attribute) === value) return;\n if (value === null) element.removeAttribute(this.#attribute);\n else element.setAttribute(this.#attribute, value);\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","/**\n * Largest delay a timer can hold: the platform stores it in a 32-bit signed\n * integer, and anything larger overflows to `1`, so a delay meant to be far in\n * the future fires almost immediately. A declared delay above this bound names\n * no delay at all, and a controller reading one falls back to its default.\n */\nexport const MAX_TIMER_DELAY_MS = 2_147_483_647;\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","/** A successful guarded storage operation. */\nexport interface StorageSuccess<T> {\n readonly ok: true;\n readonly value: T;\n}\n\n/** A guarded storage operation rejected by the browser. */\nexport interface StorageFailure {\n readonly ok: false;\n readonly error: unknown;\n}\n\n/** Result of accessing browser storage without allowing an exception to escape. */\nexport type StorageResult<T> = StorageSuccess<T> | StorageFailure;\n\n/**\n * Guarded `localStorage` access shared by controllers that persist client state.\n *\n * `window.localStorage` can throw while resolving the storage object or while\n * reading, writing, or removing a key. The result keeps an unavailable store\n * distinct from an available store whose key is unset, so callers can expose an\n * accurate success or failure state without duplicating exception guards.\n */\n\n/**\n * Reads `key` from `localStorage`.\n *\n * @param key - The storage key to read.\n * @returns A successful result containing the stored string or `null`, or a\n * failure result when storage is unavailable.\n */\nexport function readLocalStorage(key: string): StorageResult<string | null> {\n try {\n return { ok: true, value: window.localStorage.getItem(key) };\n } catch (error: unknown) {\n return { ok: false, error };\n }\n}\n\n/**\n * Writes `value` under `key` in `localStorage`.\n *\n * @param key - The storage key to write.\n * @param value - The string to store.\n * @returns Success only after `setItem` completes; otherwise the browser error.\n */\nexport function writeLocalStorage(key: string, value: string): StorageResult<void> {\n try {\n window.localStorage.setItem(key, value);\n return { ok: true, value: undefined };\n } catch (error: unknown) {\n return { ok: false, error };\n }\n}\n\n/**\n * Removes `key` from `localStorage`.\n *\n * @param key - The storage key to remove.\n * @returns Success only after `removeItem` completes; otherwise the browser error.\n */\nexport function removeLocalStorage(key: string): StorageResult<void> {\n try {\n window.localStorage.removeItem(key);\n return { ok: true, value: undefined };\n } catch (error: unknown) {\n return { ok: false, error };\n }\n}\n","/**\n * Self-cleaning timer registries shared by Stimeo controllers.\n *\n * Stimulus controllers frequently schedule `setTimeout` / `setInterval` work\n * (auto-dismiss, debouncing, polling). When the element leaves the DOM — a\n * Turbo Drive navigation, a Turbo Stream replacement, or any `disconnect()` —\n * orphaned timers keep firing against a detached controller, leaking memory and\n * mutating stale state. {@link SafeTimeout} and {@link SafeInterval} track every\n * timer they create so a single {@link TimerRegistry.clearAll | clearAll()} call\n * in `disconnect()` tears them all down.\n *\n * These are intentionally low-level primitives: they own *registration and\n * cleanup only*. Higher-level policy (pause/resume, remaining-time accounting)\n * stays in the individual controllers so per-widget semantics are not flattened\n * into a lowest-common-denominator helper.\n */\n\nexport { MAX_TIMER_DELAY_MS } from \"./timer_bounds\";\n\n/**\n * Shared registry bookkeeping for the timeout/interval variants.\n *\n * Subclasses provide the scheduling primitive ({@link schedule}) and its matching\n * canceller ({@link cancel}); this base owns the set of live ids plus the\n * per-id and bulk teardown shared by both.\n */\nabstract class TimerRegistry {\n /** Live timer ids that have not yet been cleared (or, for timeouts, fired). */\n protected readonly ids = new Set<number>();\n\n /** Schedules the underlying platform timer and returns its id. */\n protected abstract schedule(callback: () => void, delay: number): number;\n\n /** Cancels the underlying platform timer for `id`. */\n protected abstract cancel(id: number): void;\n\n /**\n * Cancels a single tracked timer.\n *\n * No-ops if the id is unknown (already cleared, fired, or never owned by this\n * registry), so callers can clear defensively without guarding.\n */\n clear(id: number): void {\n if (this.ids.delete(id)) {\n this.cancel(id);\n }\n }\n\n /**\n * Cancels every tracked timer. Call this from a controller's `disconnect()`\n * to guarantee no timer outlives the element.\n */\n clearAll(): void {\n for (const id of this.ids) {\n this.cancel(id);\n }\n this.ids.clear();\n }\n\n /** Number of timers currently tracked (pending). */\n get size(): number {\n return this.ids.size;\n }\n}\n\n/**\n * `setTimeout` wrapper that auto-forgets each timer once it fires and supports\n * bulk teardown on disconnect.\n *\n * @example\n * ```ts\n * #timers = new SafeTimeout();\n *\n * connect() {\n * this.#timers.set(() => this.dismiss(), 5000);\n * }\n *\n * disconnect() {\n * this.#timers.clearAll();\n * }\n * ```\n */\nexport class SafeTimeout extends TimerRegistry {\n /**\n * Schedules `callback` after `delay` ms and returns the timer id.\n *\n * The id is removed from the registry automatically when the timeout fires,\n * so {@link TimerRegistry.size | size} reflects only still-pending timers.\n */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(() => {\n this.ids.delete(id);\n callback();\n }, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setTimeout(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearTimeout(id);\n }\n}\n\n/**\n * `setInterval` wrapper that tracks every interval for bulk teardown on\n * disconnect. Unlike {@link SafeTimeout}, intervals are retained until they are\n * explicitly cleared because they fire repeatedly.\n *\n * @example\n * ```ts\n * #intervals = new SafeInterval();\n *\n * connect() {\n * this.#intervals.set(() => this.tick(), 1000);\n * }\n *\n * disconnect() {\n * this.#intervals.clearAll();\n * }\n * ```\n */\nexport class SafeInterval extends TimerRegistry {\n /** Schedules a repeating `callback` every `delay` ms and returns the timer id. */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(callback, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setInterval(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearInterval(id);\n }\n}\n","/**\n * JSON string-list parsing for the controllers that take a list as a Value.\n *\n * Stimulus offers an `Array` Value type, but its reader runs `JSON.parse` inside\n * the value observer — **before** the `<name>ValueChanged` callback — and\n * rethrows on malformed text. The throw propagates out of the observer that runs\n * during connection, so a single unparseable attribute stops the controller from\n * connecting at all: no lifecycle callback runs and the element is left inert\n * rather than degraded. A consumer cannot guard against it either, because the\n * callback that would hold the `try` never runs.\n *\n * Declaring the attribute as a `String` Value and parsing it here keeps a\n * malformed declaration local to the value it declares. The attribute text is\n * identical either way (`'[\"a\", \"b\"]'`), so markup does not change with the\n * declaration.\n */\n\n/**\n * Parses `raw` as a JSON array of strings.\n *\n * Returns `fallback` when the text is absent, unparseable, or not an array, so a\n * malformed declaration behaves like an omitted one. A parsed array keeps only\n * its string entries: every caller indexes or compares strings, and a stray\n * number would otherwise sit in the list without ever matching.\n *\n * An explicit `\"[]\"` is honoured as an empty list rather than falling back — it\n * is the only way to declare \"none\" against a non-empty default.\n *\n * @param raw - the attribute text, e.g. `'[\"password\"]'`.\n * @param fallback - the list to use when `raw` declares nothing usable.\n */\nexport function parseStringList(raw: string, fallback: readonly string[] = []): string[] {\n // The common case is an undeclared attribute, and `JSON.parse(\"\")` answers it\n // by throwing. Reaching the same fallback without building an exception keeps\n // the callers that ask per element off that path.\n const text = raw.trim();\n if (text.length === 0) return [...fallback];\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return [...fallback];\n }\n\n if (!Array.isArray(parsed)) return [...fallback];\n return parsed.filter((entry): entry is string => typeof entry === \"string\");\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()`: Turbo also dispatches that event on pages that stay, where the hook\n * is still true, and an in-page move — the other half of the population — never\n * reaches it, so a hook that arrived with a moved element would survive.\n * `connect()` covers both, because both end in a 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 */\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 { leasedAuthorValue } from \"../utils/attribute_lease\";\nimport { MicrotaskCoalescer } from \"../utils/microtask_coalescer\";\nimport { NUMBER_BOUNDS, type NumberValueConstraints } from \"../utils/number_bounds\";\nimport { NumberValueReader } from \"../utils/number_value\";\nimport { readLocalStorage, removeLocalStorage, writeLocalStorage } from \"../utils/safe_storage\";\nimport { SafeTimeout } from \"../utils/safe_timeout\";\nimport { parseStringList } from \"../utils/string_list\";\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-persist-restored\"] });\n\n/** Field controls this controller can persist. */\ntype PersistField = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n\n/** Values that can be restored without coercing an untrusted storage payload. */\ntype PersistValue = string | boolean | string[];\n\n/** One stable field entry in the versioned storage payload. */\ninterface PersistPayloadField {\n readonly key: string;\n readonly value: PersistValue;\n}\n\n/** Versioned draft payload stored under one controller namespace. */\ninterface PersistPayload {\n readonly version: 1;\n readonly fields: PersistPayloadField[];\n}\n\ntype PersistOperation = \"read\" | \"write\" | \"remove\";\ntype PersistErrorReason = \"unavailable\" | \"invalid-payload\";\n\n/** One scheduled write, including the namespace it was created for. */\ninterface PendingSave {\n readonly id: number;\n readonly logicalKey: string;\n}\n\n/** Input types that carry no meaningful, restorable value. */\nconst NON_VALUE_TYPES = new Set([\"file\", \"submit\", \"reset\", \"button\", \"image\"]);\n/** Passwords are never persisted, even when a custom exclusion list is supplied. */\nconst SENSITIVE_TYPES = new Set([\"password\"]);\n/** Field types and names skipped by the default configuration. */\nconst DEFAULT_EXCLUDE = [\"authenticity_token\", \"_method\", \"utf8\"];\n/** localStorage key prefix so drafts never clobber unrelated app storage. */\nconst STORAGE_PREFIX = \"stimeo--persist:\";\n/** Separator for disambiguating repeated same-name fields. */\nconst OCCURRENCE_SEP = \"\\u0000\";\n/** The one observed attribute that can move fields between nested Persist hosts. */\nconst OWNERSHIP_ATTRIBUTE = \"data-controller\";\nconst DEFAULT_DEBOUNCE = 400;\n\n/** Whether a parsed JSON value is a plain object-like record. */\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Whether a parsed JSON value belongs to the persisted field-value union. */\nconst isPersistValue = (value: unknown): value is PersistValue =>\n typeof value === \"string\" ||\n typeof value === \"boolean\" ||\n (Array.isArray(value) && value.every((item) => typeof item === \"string\"));\n\n/** Parses and validates the complete versioned payload without type assertions. */\nconst parsePayload = (raw: string): PersistPayload | null => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!isRecord(parsed) || parsed.version !== 1 || !Array.isArray(parsed.fields)) return null;\n\n const fields: PersistPayloadField[] = [];\n const keys = new Set<string>();\n for (const candidate of parsed.fields) {\n if (!isRecord(candidate)) return null;\n const { key, value } = candidate;\n if (typeof key !== \"string\" || key.length === 0 || keys.has(key)) return null;\n if (!isPersistValue(value)) return null;\n keys.add(key);\n fields.push({ key, value });\n }\n return { version: 1, fields };\n};\n\n/** Whether a node is one of the native controls supported by Persist. */\nconst isPersistField = (node: unknown): node is PersistField =>\n node instanceof HTMLInputElement ||\n node instanceof HTMLTextAreaElement ||\n node instanceof HTMLSelectElement;\n\n/**\n * Headless draft-autosave behavior: persists form controls to `localStorage`\n * and restores them across Turbo navigation and reloads.\n *\n * Markup contract (identifier: `stimeo--persist`):\n * <form data-controller=\"stimeo--persist\"\n * data-stimeo--persist-key-value=\"contact-draft\">\n * <input name=\"name\">\n * <textarea name=\"message\"></textarea>\n * </form>\n *\n * The optional `field` targets restrict persistence to explicitly targeted\n * controls. The public `clear` action removes the active draft. `key`,\n * `exclude`, and `clearOn` Values can change while connected; `clearOn` is an\n * event name whose occurrence invokes `clear`. `debounce` is read as each edit\n * schedules its save: a pending save keeps the deadline its edit gave it, and\n * the next edit takes the new value.\n *\n * `restore`, `save`, and `clear` dispatch `{ key: string }`. `error` dispatches\n * `{ key: string, operation: \"read\" | \"write\" | \"remove\", reason:\n * \"unavailable\" | \"invalid-payload\" }`. Restore writes are intentionally\n * silent native-control mutations; consumers synchronize from the bubbling\n * `restore` event without treating a restored draft as user input.\n *\n * @remarks\n * Behavior only — restoration never moves focus. Passwords are never stored;\n * the default exclusion also omits Rails request metadata while preserving\n * application-owned hidden fields. Distinct logical keys isolate instances;\n * instances using the same key intentionally share one last-writer-wins draft.\n * Every listener, timer, observer, and queued reconciliation is released on\n * `disconnect()`, after any pending edit is flushed through the normal save\n * path. A reconnect removes stale restored state before reading storage.\n */\nexport class PersistController extends Controller<HTMLElement> {\n /** Numeric read boundaries share one reader for this controller instance. */\n readonly #numbers = new NumberValueReader();\n\n static override targets = [\"field\"];\n static override values = {\n key: { type: String, default: \"\" },\n debounce: { type: Number, default: DEFAULT_DEBOUNCE },\n // A malformed JSON list must fall back without aborting Stimulus connection.\n exclude: { type: String, default: \"\" },\n clearOn: { type: String, default: \"\" },\n };\n\n static valueConstraints = {\n debounce: NUMBER_BOUNDS.timer,\n } satisfies NumberValueConstraints<typeof PersistController.values>;\n static actions = [\"clear\"] as const;\n static events = [\"restore\", \"save\", \"clear\", \"error\"] as const;\n\n declare readonly fieldTargets: Element[];\n declare readonly hasFieldTarget: boolean;\n\n declare keyValue: string;\n declare debounceValue: number;\n declare excludeValue: string;\n declare clearOnValue: string;\n\n readonly #timeouts = new SafeTimeout();\n readonly #restoreDynamic = new MicrotaskCoalescer(() => this.#restoreDynamicFields());\n readonly #observer = new MutationObserver((records) => this.#onMutations(records));\n #pendingSave: PendingSave | null = null;\n #connected = false;\n #logicalKey: string | null = null;\n #payload: PersistPayload | null = null;\n #registeredClearOn: string | null = null;\n #excluded: readonly string[] = DEFAULT_EXCLUDE;\n #knownFields = new WeakSet<PersistField>();\n #forcedRestore = new Set<PersistField>();\n\n readonly #onInput = (event: Event): void => {\n const field = event.target;\n if (!isPersistField(field) || !this.#ownsField(field)) return;\n if (this.hasFieldTarget && !this.fieldTargets.includes(field)) return;\n if (this.#keyOf(field) === null || !this.#persistable(field, this.#excluded)) return;\n this.#scheduleSave();\n };\n\n readonly #onClearEvent = (): void => {\n this.clear();\n };\n\n override connect(): void {\n if (this.#connected) return;\n this.#connected = true;\n this.#logicalKey = this.#resolveLogicalKey();\n this.#excluded = parseStringList(this.excludeValue, DEFAULT_EXCLUDE);\n\n this.element.addEventListener(\"input\", this.#onInput);\n this.element.addEventListener(\"change\", this.#onInput);\n this.#syncClearOn();\n this.#restoreDynamic.activate();\n this.#observer.observe(this.element, {\n attributes: true,\n attributeOldValue: true,\n attributeFilter: [\n \"checked\",\n \"data-controller\",\n `data-${this.identifier}-target`,\n \"id\",\n \"multiple\",\n \"name\",\n \"selected\",\n \"type\",\n \"value\",\n ],\n childList: true,\n subtree: true,\n });\n this.#loadActiveDraft();\n }\n\n override disconnect(): void {\n this.#flushPendingSave();\n this.#connected = false;\n this.element.removeEventListener(\"input\", this.#onInput);\n this.element.removeEventListener(\"change\", this.#onInput);\n this.#unbindClearOn();\n this.#observer.disconnect();\n this.#restoreDynamic.cancel();\n TRANSIENT.reset(this.element);\n this.#payload = null;\n }\n\n /** Drops the active draft after storage confirms the removal. */\n clear(): void {\n const logicalKey = this.#logicalKey ?? this.#resolveLogicalKey();\n if (logicalKey === null) return;\n this.#cancelPendingSave();\n const result = removeLocalStorage(this.#storageKey(logicalKey));\n if (!result.ok) {\n this.#dispatchError(logicalKey, \"remove\", \"unavailable\");\n return;\n }\n this.#payload = null;\n this.element.removeAttribute(\"data-persist-restored\");\n this.dispatch(\"clear\", { detail: { key: logicalKey } });\n }\n\n /** Rebinds the external clear event when its Value changes. */\n clearOnValueChanged(): void {\n if (this.#connected) this.#syncClearOn();\n }\n\n /** Switches storage namespaces without writing old edits under the new key. */\n keyValueChanged(): void {\n if (this.#connected) this.#switchLogicalKey();\n }\n\n /** Restores every field the new exclusion list makes eligible. */\n excludeValueChanged(): void {\n const previous = this.#excluded;\n this.#excluded = parseStringList(this.excludeValue, DEFAULT_EXCLUDE);\n if (!this.#connected) return;\n // A field restored once stays in #knownFields, so releasing it from the exclusion\n // list has to name it explicitly to reach the next batch. Fields the list never\n // covered keep their live value, which is what the next batch already guarantees.\n for (const field of this.#candidateFields()) {\n if (this.#persistable(field, this.#excluded) && !this.#persistable(field, previous)) {\n this.#forcedRestore.add(field);\n }\n }\n this.#restoreDynamic.schedule();\n }\n\n /**\n * Schedules a debounced save on the current `debounce`, replacing a pending one.\n * The save keeps this deadline when `debounce` changes later.\n */\n #scheduleSave(): void {\n const logicalKey = this.#logicalKey;\n if (logicalKey === null) return;\n this.#cancelPendingSave();\n const id = this.#timeouts.set(() => {\n this.#pendingSave = null;\n this.#save(logicalKey);\n }, this.#debounceDelay);\n this.#pendingSave = { id, logicalKey };\n }\n\n /** Cancels the currently pending save, if any. */\n #cancelPendingSave(): void {\n const pending = this.#pendingSave;\n if (pending === null) return;\n this.#timeouts.clear(pending.id);\n this.#pendingSave = null;\n }\n\n /**\n * Flushes a pending edit through the same success/error event path as a timer. The\n * flush is the last write of the namespace the edit was scheduled for, so a save that\n * a `save` or `error` listener schedules while it runs is dropped with it: that save\n * would write whatever the fields hold once the namespace has switched or the\n * controller has disconnected.\n */\n #flushPendingSave(): void {\n const pending = this.#pendingSave;\n if (pending === null) return;\n this.#cancelPendingSave();\n this.#save(pending.logicalKey);\n this.#cancelPendingSave();\n }\n\n /** Writes the active payload and emits `save` only after storage succeeds. */\n #save(logicalKey: string): boolean {\n const payload = this.#serialize();\n const result = writeLocalStorage(this.#storageKey(logicalKey), JSON.stringify(payload));\n if (!result.ok) {\n this.#dispatchError(logicalKey, \"write\", \"unavailable\");\n return false;\n }\n this.#payload = payload;\n this.dispatch(\"save\", { detail: { key: logicalKey } });\n return true;\n }\n\n /** Serializes every persistable field into a versioned, typed payload. */\n #serialize(): PersistPayload {\n const fields: PersistPayloadField[] = [];\n for (const { field, key } of this.#fieldEntries()) {\n if (field instanceof HTMLInputElement && field.type === \"checkbox\") {\n fields.push({ key, value: field.checked });\n } else if (field instanceof HTMLInputElement && field.type === \"radio\") {\n if (field.checked) fields.push({ key, value: field.value });\n } else if (field instanceof HTMLSelectElement && field.multiple) {\n fields.push({\n key,\n value: Array.from(field.selectedOptions).map((option) => option.value),\n });\n } else {\n fields.push({ key, value: field.value });\n }\n }\n return { version: 1, fields };\n }\n\n /** Reads, validates, and restores the active namespace. */\n #loadActiveDraft(): void {\n TRANSIENT.reset(this.element);\n this.#payload = null;\n this.#knownFields = new WeakSet<PersistField>();\n this.#forcedRestore.clear();\n const logicalKey = this.#logicalKey;\n if (logicalKey === null) return;\n\n const result = readLocalStorage(this.#storageKey(logicalKey));\n if (!result.ok) {\n this.#dispatchError(logicalKey, \"read\", \"unavailable\");\n this.#markCurrentFieldsKnown();\n return;\n }\n if (result.value === null) {\n this.#markCurrentFieldsKnown();\n return;\n }\n\n const payload = parsePayload(result.value);\n if (payload === null) {\n const removal = removeLocalStorage(this.#storageKey(logicalKey));\n // Cleanup precedes notification so an error consumer can safely replace\n // the invalid value without that repair being deleted on callback return.\n this.#dispatchError(logicalKey, \"read\", \"invalid-payload\");\n if (!removal.ok) this.#dispatchError(logicalKey, \"remove\", \"unavailable\");\n this.#markCurrentFieldsKnown();\n return;\n }\n this.#payload = payload;\n this.#restoreEntries(null);\n }\n\n /** Restores fields inserted or made eligible after the initial connection. */\n #restoreDynamicFields(): void {\n const selected = new Set<PersistField>(this.#forcedRestore);\n this.#forcedRestore.clear();\n for (const { field } of this.#fieldEntries()) {\n if (!this.#knownFields.has(field)) selected.add(field);\n }\n this.#restoreEntries(selected);\n }\n\n /** Applies the active payload to all fields, or only the supplied candidates. */\n #restoreEntries(selected: ReadonlySet<PersistField> | null): void {\n const entries = this.#fieldEntries();\n for (const { field } of entries) this.#knownFields.add(field);\n const payload = this.#payload;\n if (payload === null) return;\n const savedFields = new Map(payload.fields.map((field) => [field.key, field]));\n const restoredKeys = new Set<string>();\n const processedRadios = new Set<string>();\n\n for (const entry of entries) {\n if (selected !== null && !selected.has(entry.field)) continue;\n const saved = savedFields.get(entry.key);\n if (saved === undefined) continue;\n const { value } = saved;\n\n if (entry.field instanceof HTMLInputElement && entry.field.type === \"radio\") {\n if (processedRadios.has(entry.key)) continue;\n processedRadios.add(entry.key);\n const radios = entries\n .filter(\n ({ key, field }) =>\n key === entry.key && field instanceof HTMLInputElement && field.type === \"radio\",\n )\n .map(({ field }) => field as HTMLInputElement);\n if (typeof value !== \"string\" || !radios.some((radio) => radio.value === value)) continue;\n for (const radio of radios) radio.checked = radio.value === value;\n restoredKeys.add(entry.key);\n continue;\n }\n\n if (this.#applyValue(entry.field, value)) restoredKeys.add(entry.key);\n }\n\n if (restoredKeys.size > 0) {\n // Property writes can reflect to observed attributes in DOM implementations.\n // Drop only records produced by this restore before notifying consumers, so\n // authored mutations made from a restore listener remain observable.\n this.#observer.takeRecords();\n this.element.setAttribute(\"data-persist-restored\", \"true\");\n this.dispatch(\"restore\", { detail: { key: this.#logicalKey } });\n }\n }\n\n /** Applies a type-compatible stored value without coercion. */\n #applyValue(field: PersistField, value: PersistValue): boolean {\n if (field instanceof HTMLInputElement && field.type === \"checkbox\") {\n if (typeof value !== \"boolean\") return false;\n field.checked = value;\n return true;\n }\n if (field instanceof HTMLSelectElement && field.multiple) {\n if (!Array.isArray(value)) return false;\n const available = new Set(Array.from(field.options).map((option) => option.value));\n const selected = value.filter((candidate) => available.has(candidate));\n if (value.length > 0 && selected.length === 0) return false;\n const selectedValues = new Set(selected);\n for (const option of Array.from(field.options)) {\n option.selected = selectedValues.has(option.value);\n }\n return true;\n }\n if (typeof value !== \"string\") return false;\n if (field instanceof HTMLSelectElement) {\n const exists = Array.from(field.options).some((option) => option.value === value);\n if (!exists) return false;\n }\n field.value = value;\n return true;\n }\n\n /** Every control this instance owns, before the exclusion list narrows them. */\n #candidateFields(): PersistField[] {\n return this.hasFieldTarget\n ? this.fieldTargets.filter(isPersistField)\n : Array.from(this.element.querySelectorAll<PersistField>(\"input, textarea, select\")).filter(\n (field) => this.#ownsField(field),\n );\n }\n\n /**\n * Pairs persistable fields with DOM-order occurrence keys. Every HTML radio\n * group (same name and form owner) occupies one shared occurrence slot.\n */\n #fieldEntries(): Array<{ field: PersistField; key: string }> {\n const entries: Array<{ field: PersistField; key: string }> = [];\n const eligible: Array<{ field: PersistField; name: string }> = [];\n for (const field of this.#candidateFields()) {\n const name = this.#keyOf(field);\n if (name === null || !this.#persistable(field, this.#excluded)) continue;\n eligible.push({ field, name });\n }\n\n const nextOccurrence = new Map<string, number>();\n const radioSlots = new Map<string, Map<HTMLFormElement | null, string>>();\n const allocate = (name: string): string => {\n const occurrence = nextOccurrence.get(name) ?? 0;\n nextOccurrence.set(name, occurrence + 1);\n return occurrence === 0 ? name : `${name}${OCCURRENCE_SEP}${occurrence}`;\n };\n for (const { field, name } of eligible) {\n if (field instanceof HTMLInputElement && field.type === \"radio\") {\n const groups = radioSlots.get(name) ?? new Map<HTMLFormElement | null, string>();\n radioSlots.set(name, groups);\n let key = groups.get(field.form);\n if (key === undefined) {\n key = allocate(name);\n groups.set(field.form, key);\n }\n entries.push({ field, key });\n continue;\n }\n entries.push({ field, key: allocate(name) });\n }\n return entries;\n }\n\n /**\n * Whether a field carries a restorable, non-excluded value. A password field is never one,\n * also while a reveal has turned it into a text field: the lease that took its `type` over\n * still records the author's `password`.\n */\n #persistable(field: PersistField, excluded: readonly string[]): boolean {\n if (NON_VALUE_TYPES.has(field.type) || SENSITIVE_TYPES.has(field.type)) return false;\n if (SENSITIVE_TYPES.has(leasedAuthorValue(field, \"type\") ?? \"\")) return false;\n if (excluded.includes(field.type)) return false;\n if (field.name.length > 0 && excluded.includes(field.name)) return false;\n return true;\n }\n\n /** A stable storage sub-key for a field (its name, else id). */\n #keyOf(field: PersistField): string | null {\n return field.name || field.id || null;\n }\n\n /** Whether this instance, rather than a nested Persist host, owns a field. */\n #ownsField(field: PersistField): boolean {\n return field.closest(`[data-controller~=\"${this.identifier}\"]`) === this.element;\n }\n\n /** Marks all currently eligible fields without applying a payload. */\n #markCurrentFieldsKnown(): void {\n for (const { field } of this.#fieldEntries()) this.#knownFields.add(field);\n }\n\n /** Switches namespace after flushing the old namespace's pending edit. */\n #switchLogicalKey(): void {\n const next = this.#resolveLogicalKey();\n if (next === this.#logicalKey) return;\n this.#flushPendingSave();\n this.#logicalKey = next;\n this.#loadActiveDraft();\n }\n\n /** Synchronizes the exact event name owned by the `clearOn` Value. */\n #syncClearOn(): void {\n const next = this.#validEventName(this.clearOnValue);\n if (next === this.#registeredClearOn) return;\n this.#unbindClearOn();\n if (next === null) return;\n this.element.addEventListener(next, this.#onClearEvent);\n this.#registeredClearOn = next;\n }\n\n /** Removes the event listener using the name that was actually registered. */\n #unbindClearOn(): void {\n if (this.#registeredClearOn === null) return;\n this.element.removeEventListener(this.#registeredClearOn, this.#onClearEvent);\n this.#registeredClearOn = null;\n }\n\n /** Returns a non-whitespace event type, or null when the hook is disabled. */\n #validEventName(value: string): string | null {\n const name = value.trim();\n return name.length > 0 && !/\\s/.test(name) ? name : null;\n }\n\n /**\n * Collects dynamic controls and select-option changes into one restore pass.\n *\n * @stimeoRuntimeOnly `key` decides whether an id change moves the storage namespace; it decides\n * nothing shown.\n */\n #onMutations(records: MutationRecord[]): void {\n let rootIdChanged = false;\n // The first record for an element carries its `data-controller` from before the batch.\n const ownershipBefore = new Map<Element, string | null>();\n for (const record of records) {\n if (record.type === \"attributes\") {\n if (record.target === this.element && record.attributeName === \"id\") {\n rootIdChanged = true;\n }\n if (record.attributeName === OWNERSHIP_ATTRIBUTE) {\n // An attribute record's target is always an element.\n const element = record.target as Element;\n if (!ownershipBefore.has(element)) ownershipBefore.set(element, record.oldValue);\n continue;\n }\n this.#collectControlCandidate(record.target);\n continue;\n }\n for (const node of record.addedNodes) this.#collectRestoreCandidate(node);\n }\n for (const [element, before] of ownershipBefore) {\n this.#collectOwnershipCandidate(element, before);\n }\n if (rootIdChanged && this.keyValue.length === 0) this.#switchLogicalKey();\n this.#restoreDynamic.schedule();\n }\n\n /**\n * Adds the controls under an element whose `data-controller` gained or lost this\n * identifier across the batch. That is the only attribute change that moves fields\n * between Persist hosts, so it is the single case worth a subtree sweep; any other\n * `data-controller` change leaves ownership where it was, and sweeping for it would\n * re-apply the stored draft over edits still being debounced.\n */\n #collectOwnershipCandidate(element: Element, before: string | null): void {\n const after = element.getAttribute(OWNERSHIP_ATTRIBUTE);\n if (this.#namesThisIdentifier(before) === this.#namesThisIdentifier(after)) return;\n this.#collectRestoreCandidate(element);\n }\n\n /** Whether a `data-controller` value lists this controller's identifier. */\n #namesThisIdentifier(tokens: string | null): boolean {\n return (tokens ?? \"\").split(/\\s+/).includes(this.identifier);\n }\n\n /** Adds a native control, or the select that owns a mutated option. */\n #collectControlCandidate(node: Node): void {\n if (isPersistField(node)) {\n this.#forcedRestore.add(node);\n return;\n }\n if (node instanceof HTMLOptionElement) {\n const select = node.closest(\"select\");\n if (select) this.#forcedRestore.add(select);\n }\n }\n\n /** Adds every control inside an inserted or newly owned subtree. */\n #collectRestoreCandidate(node: Node): void {\n this.#collectControlCandidate(node);\n if (!(node instanceof Element)) return;\n for (const field of node.querySelectorAll<PersistField>(\"input, textarea, select\")) {\n this.#forcedRestore.add(field);\n }\n }\n\n /**\n * Resolves the logical key from the Value, falling back to the host id.\n *\n * @stimeoRuntimeOnly `key` names the storage namespace; the restored fields come from what is\n * stored there.\n */\n #resolveLogicalKey(): string | null {\n const key = this.keyValue || this.element.id;\n return key.length > 0 ? key : null;\n }\n\n /** Namespaces one logical key within localStorage. */\n #storageKey(logicalKey: string): string {\n return `${STORAGE_PREFIX}${logicalKey}`;\n }\n\n /** Normalizes an invalid `debounce` Value to the `debounce` default. */\n get #debounceDelay(): number {\n return this.#safeDebounce;\n }\n\n /** Dispatches one observable storage failure without exposing browser errors. */\n #dispatchError(key: string, operation: PersistOperation, reason: PersistErrorReason): void {\n this.dispatch(\"error\", { detail: { key, operation, reason } });\n }\n /** Current `debounce` declaration resolved against its numeric contract. */\n get #safeDebounce(): number {\n return this.#numbers.read(\n this,\n \"debounce\",\n this.debounceValue,\n PersistController.values.debounce.default,\n PersistController.valueConstraints.debounce,\n );\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/shared_registry.ts","../../src/utils/attribute_lease.ts","../../src/utils/form_data_projection.ts","../../src/utils/listener_set.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/timer_bounds.ts","../../src/utils/number_bounds.ts","../../src/utils/coerce.ts","../../src/utils/number_value.ts","../../src/utils/safe_storage.ts","../../src/utils/safe_timeout.ts","../../src/utils/string_list.ts","../../src/utils/transient_hooks.ts","../../src/controllers/persist_controller.ts"],"names":["registry"],"mappings":"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","file":"persist_controller.js","sourcesContent":["/**\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 { setAttributeIfChanged } from \"./attribute_write\";\nimport { sharedRegistry } from \"./shared_registry\";\n\n/** What a lease's record says: the author's value, its last write, the leases beneath. */\ninterface AttributeLeaseRecord {\n readonly original: string | null;\n readonly written: string | null;\n /** Whether it hands back what the lease right beneath it wrote last. */\n readonly linked: boolean;\n /** The records of the other owners' leases beneath it, nearest first. */\n readonly beneath: readonly string[];\n}\n\n/** One lease's hold on one element's attribute, in the stack every lease of it shares. */\ninterface AttributeHold {\n /** The lease holding it; `null` for a hold read from a copy's record until its lease takes it. */\n lease: object | null;\n readonly record: string;\n written: string | null;\n /** What it hands back with nothing beneath it: the author's value. */\n readonly original: string | null;\n /** Whether it hands back what the hold beneath it wrote last instead. */\n linked: boolean;\n}\n\n/** The holds on each element by attribute, and every lease's record name by attribute. */\ninterface AttributeLeaseRegistry {\n readonly stacks: WeakMap<Element, Map<string, AttributeHold[]>>;\n readonly names: Map<string, Set<string>>;\n}\n\n/** Holds and record names coordinate across separately built package entries. */\nconst registry = sharedRegistry(\n \"stimeo-ui.attribute-lease.registry.v1\",\n (): AttributeLeaseRegistry => ({ stacks: new WeakMap(), names: new Map() }),\n);\n\n/** Whether a parsed record entry is an attribute value: a string, or `null` for absence. */\nfunction isAttributeValue(value: unknown): value is string | null {\n return value === null || typeof value === \"string\";\n}\n\n/**\n * Reads the record a lease left on `element`: the author's value, the value the lease wrote\n * last, whether it hands back the value beneath it (`false` before the names when it does not)\n * and the records beneath it. `undefined` when the record is missing or holds anything else.\n */\nfunction readLeaseRecord(element: Element, record: string): AttributeLeaseRecord | undefined {\n try {\n const parsed: unknown = JSON.parse(element.getAttribute(record) ?? \"null\");\n if (!Array.isArray(parsed)) return undefined;\n const [original, written, ...rest] = parsed as unknown[];\n const linked = rest[0] !== false;\n const beneath = linked ? rest : rest.slice(1);\n if (!beneath.every((under): under is string => typeof under === \"string\")) return undefined;\n return isAttributeValue(original) && isAttributeValue(written)\n ? { original, written, linked, beneath }\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The element's stack, seeded from complete ownership records once. */\nfunction attributeStack(element: Element, attribute: string): AttributeHold[] {\n const byAttribute = registry.stacks.get(element) ?? new Map<string, AttributeHold[]>();\n registry.stacks.set(element, byAttribute);\n const known = byAttribute.get(attribute);\n if (known) return known;\n const found: (AttributeLeaseRecord & { readonly record: string })[] = [];\n for (const record of registry.names.get(attribute) ?? []) {\n const read = readLeaseRecord(element, record);\n if (read) found.push({ ...read, record });\n }\n const depth = ({ beneath }: (typeof found)[number]) =>\n beneath.filter((name) => found.some((other) => other.record === name)).length;\n const stack = found\n .sort((one, other) => depth(one) - depth(other))\n .map(({ record, written, original, linked }, index) => ({\n lease: null,\n record,\n written,\n original,\n linked: linked && index > 0,\n }));\n byAttribute.set(attribute, stack);\n return stack;\n}\n\n/** The lease's live hold or the unclaimed hold described by its owner's record. */\nfunction findHold(\n stack: readonly AttributeHold[],\n lease: object,\n record: string,\n): AttributeHold | undefined {\n return (\n stack.find((held) => held.lease === lease) ??\n stack.find((held) => held.lease === null && held.record === record)\n );\n}\n\n/**\n * Inspects a derived writer's continuation without acquiring or returning a hold.\n * A covered hold may update beneath its cover. Without a hold, the expected authored\n * value is compared with the original beneath any temporary cover. The original\n * distinguishes an absent attribute from an empty one.\n */\nexport function readAttributeLease(\n element: Element,\n attribute: string,\n owner: string,\n lease: object,\n expected: string | null,\n): { readonly allowed: boolean; readonly original: string | null } {\n const stack = attributeStack(element, attribute);\n const hold = findHold(stack, lease, `data-${owner}-${attribute}-lease`);\n const current = element.getAttribute(attribute);\n const covering = [...stack].reverse().find((other) => other.written === current);\n const original = (hold ?? covering)?.original;\n const authored = original === undefined ? current : original;\n return {\n original: authored,\n allowed: hold\n ? current === hold.written ||\n stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current)\n : authored === expected,\n };\n}\n\n/**\n * The value `element`'s author wrote for `attribute`, as the record a lease of any owner leaves\n * on the element carries it; `undefined` while no lease leaves one, as when nothing has moved\n * the attribute off the author's value. A field a reveal turned from `password` into `text`\n * still reads `\"password\"` here.\n */\nexport function leasedAuthorValue(element: Element, attribute: string): string | null | undefined {\n const suffix = `-${attribute}-lease`;\n for (const name of element.getAttributeNames()) {\n if (!name.startsWith(\"data-\") || !name.endsWith(suffix)) continue;\n const record = readLeaseRecord(element, name);\n if (record) return record.original;\n }\n return undefined;\n}\n\n/**\n * Temporarily controls one attribute across a changing set of elements.\n *\n * The first write remembers the authored value, including the distinction between\n * an absent attribute and an authored empty string. Returning a lease restores that\n * value only while the attribute still matches the controller's last write. If a\n * consumer changed it in the meantime, the consumer owns the new value and teardown\n * leaves it alone.\n *\n * A `null` write deliberately removes the attribute while retaining the lease. This\n * is useful for derived ARIA whose valid absence is itself controller state, such as\n * an unbounded `aria-valuemin` or a blank spinbutton's `aria-valuenow`.\n *\n * **Every lease of an attribute shares one stack of holds per element**, whatever its owner\n * and whichever file of the package constructed it (the stacks are one per page): the holds\n * sit in the order their leases first wrote the element, each with the value it wrote last.\n * The element's value is the highest hold's that carries it, and the page's when none does.\n * A write reaches the element unless a hold above the writer carries the element's value: the\n * top hold always shows its writes, a hold beneath it shows nothing while a hold above keeps\n * its value on the element, and once the page has put a value there that no hold carries, the\n * next write of any hold replaces it. A return gives a value back only from the hold the\n * element's value is: the value the hold beneath it wrote last, or the author's once nothing\n * is beneath it; any other return only leaves the stack, and the page's value stays. Holds\n * that wrote the same value are told apart by the stack, never by the value: the higher one\n * keeps it. A first write over a top hold whose value the page has replaced takes the\n * element's value as the author's. Two instances of one controller on one element — an\n * element outside their scope — stack the same way.\n *\n * A **base lease** (`{ base: true }`) holds the element's own state rather than a value over\n * it — a form field's ARIA on its control is one — so its first write goes to the bottom of\n * the stack, beneath the leases of other owners already there: a temporary value another\n * owner leased stays shown and returns to the base lease's latest value.\n *\n * **The stack travels with the element.** While a hold shows a value other than the author's,\n * lies on another hold or is covered by one, the element carries its owner's record\n * `data-<owner>-<attribute>-lease`: JSON of the author's value and the value the hold wrote\n * last (each a string, or `null` for an absent attribute), `false` where the hold hands back\n * the author's value rather than the latest value of the hold beneath it, and the records of\n * every hold beneath it, nearest first. Returning the last lease of an owner removes its\n * record. A copy of the element — a page Turbo restores from its cache is one — therefore\n * carries the stack, and the first lease to touch the copy reads it back under the record\n * names of the leases constructed so far, which include every lease that wrote a record the\n * cache holds, and orders the holds by the records each one lists beneath it. Each lease takes\n * the hold its owner's record describes over in place. Complete records for distinct owners\n * preserve their order across a copy. The records describe holds by owner, not by instance:\n * one owner holding the element more than once leaves only its topmost hold's record, which\n * the first of its leases to write or return on the copy takes. Lower holds of that owner and\n * their positions are absent; mutually listed owners cannot express their full live order.\n * A hold that showed the author's value alone carries no record and is taken by its first\n * write on the copy. Missing or unreadable records also leave their holds unknown, so copying\n * the DOM does not promise identical decisions for every live stack. Without a record it can\n * read, a new stack takes the current value as the author's. A Turbo morph removes records\n * absent from the server HTML; existing holds remain in memory until their leases return.\n *\n * The lease has no lifecycle of its own, so it never subscribes to document events,\n * and nothing rewinds a live page before Turbo caches it: `turbo:before-cache` also\n * fires on pages that stay.\n */\nexport class AttributeLease<T extends Element = Element> {\n readonly #attribute: string;\n readonly #record: string;\n readonly #base: boolean;\n readonly #preserveAuthor: boolean;\n readonly #held = new Set<T>();\n\n /**\n * @param attribute - The attribute whose temporary values this lease owns.\n * @param owner - Names the record on the element; the controller's identifier.\n * @param options - `base`: written beneath the other owners' leases;\n * `preserveAuthor`: a new base hold keeps a current value that no hold carries as authored.\n */\n constructor(\n attribute: string,\n owner: string,\n options: { readonly base?: boolean; readonly preserveAuthor?: boolean } = {},\n ) {\n this.#attribute = attribute;\n this.#record = `data-${owner}-${attribute}-lease`;\n this.#base = options.base === true;\n this.#preserveAuthor = options.preserveAuthor === true;\n const names = registry.names;\n names.set(attribute, (names.get(attribute) ?? new Set<string>()).add(this.#record));\n }\n\n /** Writes or removes the leased attribute while preserving its authored value. */\n write(element: T, value: string | null): void {\n const stack = attributeStack(element, this.#attribute);\n const hold = this.#take(stack) ?? this.#acquire(element, stack);\n this.#held.add(element);\n const shows = !this.#covered(element, stack, hold);\n hold.written = value;\n this.#mark(element, stack);\n if (shows) this.#reflect(element, value);\n }\n\n /**\n * Returns one lease, also on a restored copy, to the value the hold beneath it wrote last or\n * the author's, without overwriting a value a consumer wrote since. Says whether there was a\n * lease to return: a hold this lease has, or the hold a copy's record describes while no live\n * lease of the owner has taken it — a copy of a page an earlier connection wrote carries one.\n */\n return(element: T): boolean {\n const held = this.#held.delete(element);\n const known = registry.stacks.get(element)?.has(this.#attribute);\n const stack =\n held || known || element.hasAttribute(this.#record)\n ? attributeStack(element, this.#attribute)\n : [];\n const hold = this.#take(stack);\n if (!hold) return false;\n const carries = element.getAttribute(this.#attribute) === hold.written;\n const owns = carries && !this.#covered(element, stack, hold);\n const index = stack.indexOf(hold);\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 true;\n const below = hold.linked ? stack[index - 1] : undefined;\n this.#reflect(element, below ? below.written : hold.original);\n return true;\n }\n\n /** Returns every lease it holds, with the same ownership check as {@link return}. */\n returnAll(): void {\n for (const element of Array.from(this.#held)) this.return(element);\n }\n\n /** Its hold in `stack`, taking over one read from its record. */\n #take(stack: AttributeHold[]): AttributeHold | undefined {\n const hold = findHold(stack, this, this.#record);\n if (hold) hold.lease = this;\n return hold;\n }\n\n /** A new hold: on top, over the top hold while the element shows it; a base one at the bottom. */\n #acquire(element: T, stack: AttributeHold[]): AttributeHold {\n const current = element.getAttribute(this.#attribute);\n const top = stack.at(-1);\n const bottom = stack[0];\n const over = top?.written === current ? top : undefined;\n const from = this.#base\n ? this.#preserveAuthor && !stack.some((held) => held.written === current)\n ? undefined\n : bottom\n : over;\n const hold: AttributeHold = {\n lease: this,\n record: this.#record,\n written: current,\n original: from ? from.original : current,\n linked: !this.#base && over !== undefined,\n };\n if (this.#base && bottom) {\n bottom.linked = true;\n stack.unshift(hold);\n } else stack.push(hold);\n return hold;\n }\n\n /** Whether a hold above `hold` carries the element's value, which is then that hold's. */\n #covered(element: T, stack: readonly AttributeHold[], hold: AttributeHold): boolean {\n const current = element.getAttribute(this.#attribute);\n return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);\n }\n\n /** Leaves each owner's record of its topmost hold, or none where nothing needs one. */\n #mark(element: T, stack: readonly AttributeHold[]): void {\n const records = new Map<string, string | null>([[this.#record, null]]);\n stack.forEach((hold, index) => {\n const names = stack.slice(0, index).map((under) => under.record);\n const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);\n const marker = hold.linked || beneath.length === 0 ? [] : [false];\n records.set(\n hold.record,\n hold.written === hold.original && beneath.length === 0 && index === stack.length - 1\n ? null\n : JSON.stringify([hold.original, hold.written, ...marker, ...beneath]),\n );\n });\n for (const [name, recorded] of records) {\n setAttributeIfChanged(element, name, recorded);\n }\n }\n\n /** Reflects only a real value transition, avoiding self-triggered mutation work. */\n #reflect(element: T, value: string | null): void {\n setAttributeIfChanged(element, this.#attribute, value);\n }\n}\n","import { sharedRegistry } from \"./shared_registry\";\n\n/** Reserved transport names identify one produced entry without grouping equal public names. */\nconst PREFIX = \"__stimeo_raw_v1_\";\n\ninterface Projection {\n readonly field: HTMLInputElement;\n readonly document: Document;\n readonly state: DocumentProjection;\n readonly key: string;\n readonly name: string;\n readonly project: (value: FormDataEntryValue) => FormDataEntryValue;\n readonly restore: () => void;\n}\n\ninterface DocumentProjection {\n readonly fields: Map<string, Projection>;\n readonly handle: (event: Event) => void;\n readonly byField: WeakMap<HTMLInputElement, Projection>;\n}\n\nconst documents = sharedRegistry(\n \"stimeo-ui.form-data-projection.registry.v1\",\n () => new WeakMap<Document, DocumentProjection>(),\n);\n\n/** The public name encoded by a reserved transport name, or null for an ordinary name. */\nfunction decodedName(key: string): string | null {\n if (!key.startsWith(PREFIX)) return null;\n const separator = PREFIX.length + 32;\n if (key[separator] !== \":\") return null;\n try {\n const name: unknown = JSON.parse(key.slice(separator + 1));\n return typeof name === \"string\" ? name : null;\n } catch {\n return null;\n }\n}\n\n/** Reads a field's logical submission name without exposing its transport identity. */\nexport function projectedFieldName(name: string): string {\n return decodedName(name) ?? name;\n}\n\n/** Installs one capture listener for the document's reserved transport namespace. */\nfunction forDocument(document: Document): DocumentProjection {\n const existing = documents.get(document);\n if (existing) return existing;\n const state: DocumentProjection = {\n fields: new Map(),\n byField: new WeakMap(),\n handle: (event) => {\n const data = (event as FormDataEvent).formData;\n if (!data) return;\n const entries = [...data.entries()];\n let changed = false;\n const projected = entries.map(([key, value]): [string, FormDataEntryValue] => {\n const name = decodedName(key);\n if (name === null) return [key, value];\n changed = true;\n const field = state.fields.get(key);\n const live = field && field.field.name === key && field.field.form === event.target;\n return [name, live ? field.project(value) : \"\"];\n });\n if (!changed) return;\n for (const key of new Set(data.keys())) data.delete(key);\n for (const [name, value] of projected) data.append(name, value);\n },\n };\n documents.set(document, state);\n // @stimeoListenerLifetime document Decodes cached or released transport entries even when no\n // producer remains.\n document.addEventListener(\"formdata\", state.handle, { capture: true });\n return state;\n}\n\n/** Prepares a form's projection event path, including while the form is detached. */\nexport function prepareFormDataProjection(form: HTMLFormElement): void {\n const state = forDocument(form.ownerDocument);\n // @stimeoListenerLifetime element A form keeps transport decoding when detached from its\n // document.\n form.addEventListener(\"formdata\", state.handle, { capture: true });\n}\n\n/**\n * Gives a maintained hidden field a unique transport identity while preserving its\n * value. FormData exposes the public name in the same entry position; the producer\n * decides the submitted value without changing the DOM or releasing ownership.\n */\nexport class FormDataProjection {\n #held: Projection | null = null;\n\n /**\n * Claims this field's current name; a normal name written by the page starts a new claim.\n * A Turbo morph that writes the public name back returns the field to this claim at once.\n */\n hold(field: HTMLInputElement, project: Projection[\"project\"]): void {\n const held = this.#held;\n if (held?.field === field && held.key === field.name && held.document === field.ownerDocument) {\n if (field.form) prepareFormDataProjection(field.form);\n return;\n }\n this.release();\n const name = projectedFieldName(field.name);\n if (name === \"\" || (field.type === \"hidden\" && name.toLowerCase() === \"_charset_\")) return;\n const state = forDocument(field.ownerDocument);\n if (field.form) prepareFormDataProjection(field.form);\n const previous = state.byField.get(field);\n if (previous) {\n state.fields.delete(previous.key);\n field.removeEventListener(\"turbo:morph-element\", previous.restore);\n }\n const nonce = Array.from(crypto.getRandomValues(new Uint8Array(16)), (value) =>\n value.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n const key = `${PREFIX}${nonce}:${JSON.stringify(name)}`;\n const projection: Projection = {\n field,\n key,\n name,\n project,\n document: field.ownerDocument,\n state,\n restore: () => {\n if (field.name === name) field.name = key;\n },\n };\n state.fields.set(key, projection);\n state.byField.set(field, projection);\n this.#held = projection;\n field.name = key;\n // @stimeoListenerLifetime element The current claim keeps its name through a morph; a\n // release or a new claim removes it.\n field.addEventListener(\"turbo:morph-element\", projection.restore);\n }\n\n /** Restores only the name this claim still holds; another writer's name stays untouched. */\n release(): void {\n const held = this.#held;\n this.#held = null;\n if (held === null) return;\n held.field.removeEventListener(\"turbo:morph-element\", held.restore);\n const state = held.state;\n if (state.byField.get(held.field) !== held) return;\n state.fields.delete(held.key);\n state.byField.delete(held.field);\n if (held.field.name === held.key) held.field.name = held.name;\n }\n}\n","/** What {@link ListenerSet.add} passes on besides the signal it supplies itself. */\nexport type ListenerOptions = Omit<AddEventListenerOptions, \"signal\">;\n\n/**\n * The event map a target's own `addEventListener` types its handlers with: the\n * window's, a document's, an HTML or SVG element's, any other element's, or a\n * media query list's. Other targets name none.\n */\ntype EventMapOf<T extends EventTarget> = T extends Window\n ? WindowEventMap\n : T extends Document\n ? DocumentEventMap\n : T extends HTMLElement\n ? HTMLElementEventMap\n : T extends SVGElement\n ? SVGElementEventMap\n : T extends Element\n ? ElementEventMap\n : T extends MediaQueryList\n ? MediaQueryListEventMap\n : Record<never, never>;\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.\n * {@link 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 * A lifetime shorter than the connection — while a Value holds, until a first\n * load, while a subscription is open — gets a set of its own, which the end of\n * that lifetime disposes. A controller therefore holds one set per lifetime: the\n * connection's, and one for each swapped receiver or shorter span.\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, listeners of\n * several elements that come and go one at a time, and those one gesture holds\n * keep their own pair of calls or a signal of their own.\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. A removal by hand would have to repeat that\n * flag; aborting the signal releases the listener without it.\n *\n * A `type` the target's own event map names types `handler` with that event,\n * as the target's `addEventListener` does, so a handler written for a\n * `KeyboardEvent` is passed as it is; any other `type` takes an\n * `EventListener`.\n */\n add<T extends EventTarget, K extends keyof EventMapOf<T> & string>(\n target: T,\n type: K,\n handler: (event: EventMapOf<T>[K]) => void,\n options?: ListenerOptions,\n ): void;\n add(target: EventTarget, type: string, handler: EventListener, options?: ListenerOptions): void;\n add(target: EventTarget, type: string, handler: EventListener, options?: ListenerOptions): 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 /** Whether a requested pass has yet to run. */\n get pending(): boolean {\n return this.#queued;\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 * Largest delay a timer can hold: the platform stores it in a 32-bit signed\n * integer, and anything larger wraps around, so a delay meant to be far in the\n * future can fire almost immediately. A declared delay above this bound names\n * no delay at all, and a controller reading one falls back to its default.\n */\nexport const MAX_TIMER_DELAY_MS = 2_147_483_647;\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/** Numeric update input, accepting decoded action params before CustomEvent detail. */\nexport type NumericValueEvent = Event & {\n params?: { amount?: unknown };\n detail?: { value?: unknown };\n};\n\n/** Reads the nullish action-param/detail precedence without falling back from invalid input. */\nexport function eventNumber(event: NumericValueEvent): number | null {\n return toFiniteNumber(event.params?.amount ?? event.detail?.value);\n}\n\n/**\n * Reads a finite number or nonblank numeric string; other input returns `null`.\n * Blank strings cannot silently reset a value to zero.\n */\nexport function toFiniteNumber(raw: unknown): number | null {\n if (typeof raw !== \"number\" && typeof raw !== \"string\") return null;\n if (typeof raw === \"string\" && raw.trim().length === 0) return null;\n const value = Number(raw);\n return Number.isFinite(value) ? value : null;\n}\n\n/**\n * Returns an accepted decoded Number Value or the caller's fallback unchanged.\n * The caller owns the fallback contract; this reader does not parse or write a Value.\n */\nexport function readNumber(raw: number, fallback: number, bounds: NumberBounds): number {\n return matchesNumberBounds(raw, bounds) ? raw : fallback;\n}\n","import { readNumber } from \"./coerce\";\nimport { matchesNumberBounds, type NumberBounds } from \"./number_bounds\";\n\n/** The instance identity carried by a Number Value read. */\nexport interface NumberValueOwner {\n readonly identifier: string;\n readonly element: Element;\n}\n\n/** Reads current declarations at the point of use without rewriting their attributes. */\nexport class NumberValueReader {\n /** The last rejected literal per Value; no history grows for an unchanged instance. */\n readonly #lastRejected = new Map<string, string>();\n\n /** Resolves the declared number using its own fallback and shared class contract. */\n read(\n owner: NumberValueOwner,\n name: string,\n raw: number,\n fallback: number,\n bounds: NumberBounds,\n ): number {\n const resolved = readNumber(raw, fallback, bounds);\n if (matchesNumberBounds(raw, bounds)) {\n this.#lastRejected.delete(name);\n return resolved;\n }\n const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;\n const literal = owner.element.getAttribute(attribute);\n if (literal === null) {\n this.#lastRejected.delete(name);\n return resolved;\n }\n if (this.#lastRejected.get(name) !== literal) {\n this.#lastRejected.set(name, literal);\n console.warn(\n `Stimeo UI: \"${owner.identifier}\" has an invalid number Value \"${name}\" declaration ${JSON.stringify(literal)}; using ${fallback}.`,\n );\n }\n return resolved;\n }\n}\n","/**\n * Guarded `localStorage` access shared by controllers that persist client state.\n *\n * `window.localStorage` can throw while resolving the storage object or while\n * reading, writing, or removing a key. The result keeps an unavailable store\n * distinct from an available store whose key is unset, so callers can expose an\n * accurate success or failure state without duplicating exception guards.\n */\n\n/** A successful guarded storage operation. */\nexport interface StorageSuccess<T> {\n readonly ok: true;\n readonly value: T;\n}\n\n/** A guarded storage operation rejected by the browser. */\nexport interface StorageFailure {\n readonly ok: false;\n readonly error: unknown;\n}\n\n/** Result of accessing browser storage without allowing an exception to escape. */\nexport type StorageResult<T> = StorageSuccess<T> | StorageFailure;\n\n/**\n * Reads `key` from `localStorage`.\n *\n * @param key - The storage key to read.\n * @returns A successful result containing the stored string or `null`, or a\n * failure result when storage is unavailable.\n */\nexport function readLocalStorage(key: string): StorageResult<string | null> {\n try {\n return { ok: true, value: window.localStorage.getItem(key) };\n } catch (error: unknown) {\n return { ok: false, error };\n }\n}\n\n/**\n * Writes `value` under `key` in `localStorage`.\n *\n * @param key - The storage key to write.\n * @param value - The string to store.\n * @returns Success only after `setItem` completes; otherwise the browser error.\n */\nexport function writeLocalStorage(key: string, value: string): StorageResult<void> {\n try {\n window.localStorage.setItem(key, value);\n return { ok: true, value: undefined };\n } catch (error: unknown) {\n return { ok: false, error };\n }\n}\n\n/**\n * Removes `key` from `localStorage`.\n *\n * @param key - The storage key to remove.\n * @returns Success only after `removeItem` completes; otherwise the browser error.\n */\nexport function removeLocalStorage(key: string): StorageResult<void> {\n try {\n window.localStorage.removeItem(key);\n return { ok: true, value: undefined };\n } catch (error: unknown) {\n return { ok: false, error };\n }\n}\n","/**\n * Self-cleaning timer registries shared by Stimeo controllers.\n *\n * Stimulus controllers frequently schedule `setTimeout` / `setInterval` work\n * (auto-dismiss, debouncing, polling). When the element leaves the DOM — a\n * Turbo Drive navigation, a Turbo Stream replacement, or any `disconnect()` —\n * orphaned timers keep firing against a detached controller, leaking memory and\n * mutating stale state. {@link SafeTimeout} and {@link SafeInterval} track every\n * timer they create so a single {@link TimerRegistry.clearAll | clearAll()} call\n * in `disconnect()` tears them all down.\n *\n * These are intentionally low-level primitives: they own *registration and\n * cleanup only*. One pending timer per key is `KeyedTimers`\n * (`keyed_timers.ts`), and a timer a person can hold open, with its remaining-time\n * accounting, is `PausableTimers` (`pausable_timers.ts`).\n */\n\nexport { MAX_TIMER_DELAY_MS } from \"./timer_bounds\";\n\n/**\n * Shared registry bookkeeping for the timeout/interval variants.\n *\n * Subclasses provide the scheduling primitive ({@link schedule}) and its matching\n * canceller ({@link cancel}); this base owns the set of live ids plus the\n * per-id and bulk teardown shared by both.\n */\nabstract class TimerRegistry {\n /** Live timer ids that have not yet been cleared (or, for timeouts, fired). */\n protected readonly ids = new Set<number>();\n\n /** Schedules the underlying platform timer and returns its id. */\n protected abstract schedule(callback: () => void, delay: number): number;\n\n /** Cancels the underlying platform timer for `id`. */\n protected abstract cancel(id: number): void;\n\n /**\n * Cancels a single tracked timer.\n *\n * No-ops if the id is unknown (already cleared, fired, or never owned by this\n * registry), so callers can clear defensively without guarding.\n */\n clear(id: number): void {\n if (this.ids.delete(id)) {\n this.cancel(id);\n }\n }\n\n /**\n * Cancels every tracked timer. Call this from a controller's `disconnect()`\n * to guarantee no timer outlives the element.\n */\n clearAll(): void {\n for (const id of this.ids) {\n this.cancel(id);\n }\n this.ids.clear();\n }\n\n /** Number of timers currently tracked (pending). */\n get size(): number {\n return this.ids.size;\n }\n}\n\n/**\n * `setTimeout` wrapper that auto-forgets each timer once it fires and supports\n * bulk teardown on disconnect.\n *\n * @example\n * ```ts\n * #timers = new SafeTimeout();\n *\n * connect() {\n * this.#timers.set(() => this.dismiss(), 5000);\n * }\n *\n * disconnect() {\n * this.#timers.clearAll();\n * }\n * ```\n */\nexport class SafeTimeout extends TimerRegistry {\n /**\n * Schedules `callback` after `delay` ms and returns the timer id.\n *\n * The id is removed from the registry automatically when the timeout fires,\n * so {@link TimerRegistry.size | size} reflects only still-pending timers.\n */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(() => {\n this.ids.delete(id);\n callback();\n }, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setTimeout(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearTimeout(id);\n }\n}\n\n/**\n * `setInterval` wrapper that tracks every interval for bulk teardown on\n * disconnect. Unlike {@link SafeTimeout}, intervals are retained until they are\n * explicitly cleared because they fire repeatedly.\n *\n * @example\n * ```ts\n * #intervals = new SafeInterval();\n *\n * connect() {\n * this.#intervals.set(() => this.tick(), 1000);\n * }\n *\n * disconnect() {\n * this.#intervals.clearAll();\n * }\n * ```\n */\nexport class SafeInterval extends TimerRegistry {\n /** Schedules a repeating `callback` every `delay` ms and returns the timer id. */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(callback, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setInterval(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearInterval(id);\n }\n}\n","/**\n * JSON string-list parsing for the controllers that take a list as a Value.\n *\n * Stimulus offers an `Array` Value type, but its reader runs `JSON.parse` inside\n * the value observer — **before** the `<name>ValueChanged` callback — and\n * rethrows on malformed text. The throw propagates out of the observer that runs\n * during connection, so a single unparseable attribute stops the controller from\n * connecting at all: no lifecycle callback runs and the element is left inert\n * rather than degraded. A consumer cannot guard against it either, because the\n * callback that would hold the `try` never runs.\n *\n * Declaring the attribute as a `String` Value and parsing it here keeps a\n * malformed declaration local to the value it declares. The attribute text is\n * identical either way (`'[\"a\", \"b\"]'`), so markup does not change with the\n * declaration.\n */\n\n/**\n * Parses `raw` as a JSON array of strings.\n *\n * Returns `fallback` when the text is absent, unparseable, or not an array, so a\n * malformed declaration behaves like an omitted one. A parsed array keeps only\n * its string entries: every caller indexes or compares strings, and a stray\n * number would otherwise sit in the list without ever matching.\n *\n * An explicit `\"[]\"` is honoured as an empty list rather than falling back — it\n * is the only way to declare \"none\" against a non-empty default.\n *\n * @param raw - the attribute text, e.g. `'[\"password\"]'`.\n * @param fallback - the list to use when `raw` declares nothing usable.\n */\nexport function parseStringList(raw: string, fallback: readonly string[] = []): string[] {\n // The common case is an undeclared attribute, and `JSON.parse(\"\")` answers it\n // by throwing. Reaching the same fallback without building an exception keeps\n // the callers that ask per element off that path.\n const text = raw.trim();\n if (text.length === 0) return [...fallback];\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return [...fallback];\n }\n\n if (!Array.isArray(parsed)) return [...fallback];\n return parsed.filter((entry): entry is string => typeof entry === \"string\");\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()`: Turbo also dispatches that event on pages that stay, where the hook\n * is still true, and an in-page move — the other half of the population — never\n * reaches it, so a hook that arrived with a moved element would survive.\n * `connect()` covers both, because both end in a 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 */\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 { leasedAuthorValue } from \"../utils/attribute_lease\";\nimport { projectedFieldName } from \"../utils/form_data_projection\";\nimport { ListenerSet } from \"../utils/listener_set\";\nimport { MicrotaskCoalescer } from \"../utils/microtask_coalescer\";\nimport { NUMBER_BOUNDS, type NumberValueConstraints } from \"../utils/number_bounds\";\nimport { NumberValueReader } from \"../utils/number_value\";\nimport { readLocalStorage, removeLocalStorage, writeLocalStorage } from \"../utils/safe_storage\";\nimport { SafeTimeout } from \"../utils/safe_timeout\";\nimport { parseStringList } from \"../utils/string_list\";\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-persist-restored\"] });\n\n/** Field controls this controller can persist. */\ntype PersistField = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n\n/** Values that can be restored without coercing an untrusted storage payload. */\ntype PersistValue = string | boolean | string[];\n\n/** One stable field entry in the versioned storage payload. */\ninterface PersistPayloadField {\n readonly key: string;\n readonly value: PersistValue;\n}\n\n/** Versioned draft payload stored under one controller namespace. */\ninterface PersistPayload {\n readonly version: 1;\n readonly fields: PersistPayloadField[];\n}\n\ntype PersistOperation = \"read\" | \"write\" | \"remove\";\ntype PersistErrorReason = \"unavailable\" | \"invalid-payload\";\n\n/** One scheduled write, including the namespace it was created for. */\ninterface PendingSave {\n readonly id: number;\n readonly logicalKey: string;\n}\n\n/** Input types that carry no meaningful, restorable value. */\nconst NON_VALUE_TYPES = new Set([\"file\", \"submit\", \"reset\", \"button\", \"image\"]);\n/** Passwords are never persisted, even when a custom exclusion list is supplied. */\nconst SENSITIVE_TYPES = new Set([\"password\"]);\n/** Field types and names skipped by the default configuration. */\nconst DEFAULT_EXCLUDE = [\"authenticity_token\", \"_method\", \"utf8\"];\n/** localStorage key prefix so drafts never clobber unrelated app storage. */\nconst STORAGE_PREFIX = \"stimeo--persist:\";\n/** Separator for disambiguating repeated same-name fields. */\nconst OCCURRENCE_SEP = \"\\u0000\";\n/** The one observed attribute that can move fields between nested `stimeo--persist` hosts. */\nconst OWNERSHIP_ATTRIBUTE = \"data-controller\";\nconst DEFAULT_DEBOUNCE = 400;\n\n/** Whether a parsed JSON value is a plain object-like record. */\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Whether a parsed JSON value belongs to the persisted field-value union. */\nconst isPersistValue = (value: unknown): value is PersistValue =>\n typeof value === \"string\" ||\n typeof value === \"boolean\" ||\n (Array.isArray(value) && value.every((item) => typeof item === \"string\"));\n\n/** Parses and validates the complete versioned payload without type assertions. */\nconst parsePayload = (raw: string): PersistPayload | null => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!isRecord(parsed) || parsed.version !== 1 || !Array.isArray(parsed.fields)) return null;\n\n const fields: PersistPayloadField[] = [];\n const keys = new Set<string>();\n for (const candidate of parsed.fields) {\n if (!isRecord(candidate)) return null;\n const { key, value } = candidate;\n if (typeof key !== \"string\" || key.length === 0 || keys.has(key)) return null;\n if (!isPersistValue(value)) return null;\n keys.add(key);\n fields.push({ key, value });\n }\n return { version: 1, fields };\n};\n\n/** Whether a node is one of the native controls supported by `stimeo--persist`. */\nconst isPersistField = (node: unknown): node is PersistField =>\n node instanceof HTMLInputElement ||\n node instanceof HTMLTextAreaElement ||\n node instanceof HTMLSelectElement;\n\n/**\n * Headless draft-autosave behavior: persists form controls to `localStorage`\n * and restores them across Turbo navigation and reloads.\n *\n * Markup contract (identifier: `stimeo--persist`):\n * <form data-controller=\"stimeo--persist\"\n * data-stimeo--persist-key-value=\"contact-draft\">\n * <input name=\"name\">\n * <textarea name=\"message\"></textarea>\n * </form>\n *\n * The optional `field` targets restrict persistence to explicitly targeted\n * controls. The public `clear` action removes the active draft. `key`,\n * `exclude`, and `clearOn` Values can change while connected; `clearOn` is an\n * event name whose occurrence invokes `clear`. `debounce` is read as each edit\n * schedules its save: a pending save keeps the deadline its edit gave it, and\n * the next edit takes the new value.\n *\n * `restore`, `save`, and `clear` dispatch `{ key: string }`. `error` dispatches\n * `{ key: string, operation: \"read\" | \"write\" | \"remove\", reason:\n * \"unavailable\" | \"invalid-payload\" }`. Restore writes are intentionally\n * silent native-control mutations; consumers synchronize from the bubbling\n * `restore` event without treating a restored draft as user input.\n *\n * @remarks\n * Behavior only — restoration never moves focus. Passwords are never stored;\n * the default exclusion also omits Rails request metadata while preserving\n * application-owned hidden fields. Distinct logical keys isolate instances;\n * instances using the same key intentionally share one last-writer-wins draft.\n * Every listener, timer, observer, and queued reconciliation is released on\n * `disconnect()`, after any pending edit is flushed through the normal save\n * path. A reconnect removes stale restored state before reading storage.\n */\nexport class PersistController extends Controller<HTMLElement> {\n /** Numeric read boundaries share one reader for this controller instance. */\n readonly #numbers = new NumberValueReader();\n\n static override targets = [\"field\"];\n static override values = {\n key: { type: String, default: \"\" },\n debounce: { type: Number, default: DEFAULT_DEBOUNCE },\n // A malformed JSON list must fall back without aborting Stimulus connection.\n exclude: { type: String, default: \"\" },\n clearOn: { type: String, default: \"\" },\n };\n\n static valueConstraints = {\n debounce: NUMBER_BOUNDS.timer,\n } satisfies NumberValueConstraints<typeof PersistController.values>;\n static actions = [\"clear\"] as const;\n static events = [\"restore\", \"save\", \"clear\", \"error\"] as const;\n\n declare readonly fieldTargets: Element[];\n declare readonly hasFieldTarget: boolean;\n\n declare keyValue: string;\n declare debounceValue: number;\n declare excludeValue: string;\n declare clearOnValue: string;\n\n readonly #timeouts = new SafeTimeout();\n readonly #restoreDynamic = new MicrotaskCoalescer(() => this.#restoreDynamicFields());\n readonly #observer = new MutationObserver((records) => this.#onMutations(records));\n #pendingSave: PendingSave | null = null;\n #connected = false;\n #logicalKey: string | null = null;\n #payload: PersistPayload | null = null;\n #registeredClearOn: string | null = null;\n /** The listener for the event `clearOn` names; a new name releases it first. */\n readonly #clearOnListeners = new ListenerSet();\n #excluded: readonly string[] = DEFAULT_EXCLUDE;\n #knownFields = new WeakSet<PersistField>();\n #forcedRestore = new Set<PersistField>();\n\n readonly #onInput = (event: Event): void => {\n const field = event.target;\n if (!isPersistField(field) || !this.#ownsField(field)) return;\n if (this.hasFieldTarget && !this.fieldTargets.includes(field)) return;\n if (this.#keyOf(field) === null || !this.#persistable(field, this.#excluded)) return;\n this.#scheduleSave();\n };\n\n readonly #onClearEvent = (): void => {\n this.clear();\n };\n\n /** The listeners of one connection, released together on `disconnect()`. */\n readonly #listeners = new ListenerSet();\n\n override connect(): void {\n if (this.#connected) return;\n this.#connected = true;\n this.#logicalKey = this.#resolveLogicalKey();\n this.#excluded = parseStringList(this.excludeValue, DEFAULT_EXCLUDE);\n\n this.#listeners.add(this.element, \"input\", this.#onInput);\n this.#listeners.add(this.element, \"change\", this.#onInput);\n this.#syncClearOn();\n this.#restoreDynamic.activate();\n this.#observer.observe(this.element, {\n attributes: true,\n attributeOldValue: true,\n attributeFilter: [\n \"checked\",\n \"data-controller\",\n `data-${this.identifier}-target`,\n \"id\",\n \"multiple\",\n \"name\",\n \"selected\",\n \"type\",\n \"value\",\n ],\n childList: true,\n subtree: true,\n });\n this.#loadActiveDraft();\n }\n\n override disconnect(): void {\n this.#flushPendingSave();\n this.#connected = false;\n this.#listeners.dispose();\n this.#unbindClearOn();\n this.#observer.disconnect();\n this.#restoreDynamic.cancel();\n TRANSIENT.reset(this.element);\n this.#payload = null;\n }\n\n /** Drops the active draft after storage confirms the removal. */\n clear(): void {\n const logicalKey = this.#logicalKey ?? this.#resolveLogicalKey();\n if (logicalKey === null) return;\n this.#cancelPendingSave();\n const result = removeLocalStorage(this.#storageKey(logicalKey));\n if (!result.ok) {\n this.#dispatchError(logicalKey, \"remove\", \"unavailable\");\n return;\n }\n this.#payload = null;\n this.element.removeAttribute(\"data-persist-restored\");\n this.dispatch(\"clear\", { detail: { key: logicalKey } });\n }\n\n /** Rebinds the external clear event when its Value changes. */\n clearOnValueChanged(): void {\n if (this.#connected) this.#syncClearOn();\n }\n\n /** Switches storage namespaces without writing old edits under the new key. */\n keyValueChanged(): void {\n if (this.#connected) this.#switchLogicalKey();\n }\n\n /** Restores every field the new exclusion list makes eligible. */\n excludeValueChanged(): void {\n const previous = this.#excluded;\n this.#excluded = parseStringList(this.excludeValue, DEFAULT_EXCLUDE);\n if (!this.#connected) return;\n // A field restored once stays in #knownFields, so releasing it from the exclusion\n // list has to name it explicitly to reach the next batch. Fields the list never\n // covered keep their live value, which is what the next batch already guarantees.\n for (const field of this.#candidateFields()) {\n if (this.#persistable(field, this.#excluded) && !this.#persistable(field, previous)) {\n this.#forcedRestore.add(field);\n }\n }\n this.#restoreDynamic.schedule();\n }\n\n /**\n * Schedules a debounced save on the current `debounce`, replacing a pending one.\n * The save keeps this deadline when `debounce` changes later.\n */\n #scheduleSave(): void {\n const logicalKey = this.#logicalKey;\n if (logicalKey === null) return;\n this.#cancelPendingSave();\n const id = this.#timeouts.set(() => {\n this.#pendingSave = null;\n this.#save(logicalKey);\n }, this.#debounceDelay);\n this.#pendingSave = { id, logicalKey };\n }\n\n /** Cancels the currently pending save, if any. */\n #cancelPendingSave(): void {\n const pending = this.#pendingSave;\n if (pending === null) return;\n this.#timeouts.clear(pending.id);\n this.#pendingSave = null;\n }\n\n /**\n * Flushes a pending edit through the same success/error event path as a timer. The\n * flush is the last write of the namespace the edit was scheduled for, so a save that\n * a `save` or `error` listener schedules while it runs is dropped with it: that save\n * would write whatever the fields hold once the namespace has switched or the\n * controller has disconnected.\n */\n #flushPendingSave(): void {\n const pending = this.#pendingSave;\n if (pending === null) return;\n this.#cancelPendingSave();\n this.#save(pending.logicalKey);\n this.#cancelPendingSave();\n }\n\n /** Writes the active payload and emits `save` only after storage succeeds. */\n #save(logicalKey: string): boolean {\n const payload = this.#serialize();\n const result = writeLocalStorage(this.#storageKey(logicalKey), JSON.stringify(payload));\n if (!result.ok) {\n this.#dispatchError(logicalKey, \"write\", \"unavailable\");\n return false;\n }\n this.#payload = payload;\n this.dispatch(\"save\", { detail: { key: logicalKey } });\n return true;\n }\n\n /** Serializes every persistable field into a versioned, typed payload. */\n #serialize(): PersistPayload {\n const fields: PersistPayloadField[] = [];\n for (const { field, key } of this.#fieldEntries()) {\n if (field instanceof HTMLInputElement && field.type === \"checkbox\") {\n fields.push({ key, value: field.checked });\n } else if (field instanceof HTMLInputElement && field.type === \"radio\") {\n if (field.checked) fields.push({ key, value: field.value });\n } else if (field instanceof HTMLSelectElement && field.multiple) {\n fields.push({\n key,\n value: Array.from(field.selectedOptions).map((option) => option.value),\n });\n } else {\n fields.push({ key, value: field.value });\n }\n }\n return { version: 1, fields };\n }\n\n /** Reads, validates, and restores the active namespace. */\n #loadActiveDraft(): void {\n TRANSIENT.reset(this.element);\n this.#payload = null;\n this.#knownFields = new WeakSet<PersistField>();\n this.#forcedRestore.clear();\n const logicalKey = this.#logicalKey;\n if (logicalKey === null) return;\n\n const result = readLocalStorage(this.#storageKey(logicalKey));\n if (!result.ok) {\n this.#dispatchError(logicalKey, \"read\", \"unavailable\");\n this.#markCurrentFieldsKnown();\n return;\n }\n if (result.value === null) {\n this.#markCurrentFieldsKnown();\n return;\n }\n\n const payload = parsePayload(result.value);\n if (payload === null) {\n const removal = removeLocalStorage(this.#storageKey(logicalKey));\n // Cleanup precedes notification so an error consumer can safely replace\n // the invalid value without that repair being deleted on callback return.\n this.#dispatchError(logicalKey, \"read\", \"invalid-payload\");\n if (!removal.ok) this.#dispatchError(logicalKey, \"remove\", \"unavailable\");\n this.#markCurrentFieldsKnown();\n return;\n }\n this.#payload = payload;\n this.#restoreEntries(null);\n }\n\n /** Restores fields inserted or made eligible after the initial connection. */\n #restoreDynamicFields(): void {\n const selected = new Set<PersistField>(this.#forcedRestore);\n this.#forcedRestore.clear();\n for (const { field } of this.#fieldEntries()) {\n if (!this.#knownFields.has(field)) selected.add(field);\n }\n this.#restoreEntries(selected);\n }\n\n /** Applies the active payload to all fields, or only the supplied candidates. */\n #restoreEntries(selected: ReadonlySet<PersistField> | null): void {\n const entries = this.#fieldEntries();\n for (const { field } of entries) this.#knownFields.add(field);\n const payload = this.#payload;\n if (payload === null) return;\n const savedFields = new Map(payload.fields.map((field) => [field.key, field]));\n const restoredKeys = new Set<string>();\n const processedRadios = new Set<string>();\n\n for (const entry of entries) {\n if (selected !== null && !selected.has(entry.field)) continue;\n const saved = savedFields.get(entry.key);\n if (saved === undefined) continue;\n const { value } = saved;\n\n if (entry.field instanceof HTMLInputElement && entry.field.type === \"radio\") {\n if (processedRadios.has(entry.key)) continue;\n processedRadios.add(entry.key);\n const radios = entries\n .filter(\n ({ key, field }) =>\n key === entry.key && field instanceof HTMLInputElement && field.type === \"radio\",\n )\n .map(({ field }) => field as HTMLInputElement);\n if (typeof value !== \"string\" || !radios.some((radio) => radio.value === value)) continue;\n for (const radio of radios) radio.checked = radio.value === value;\n restoredKeys.add(entry.key);\n continue;\n }\n\n if (this.#applyValue(entry.field, value)) restoredKeys.add(entry.key);\n }\n\n if (restoredKeys.size > 0) {\n // Property writes can reflect to observed attributes in DOM implementations.\n // Drop only records produced by this restore before notifying consumers, so\n // authored mutations made from a restore listener remain observable.\n this.#observer.takeRecords();\n this.element.setAttribute(\"data-persist-restored\", \"true\");\n this.dispatch(\"restore\", { detail: { key: this.#logicalKey } });\n }\n }\n\n /** Applies a type-compatible stored value without coercion. */\n #applyValue(field: PersistField, value: PersistValue): boolean {\n if (field instanceof HTMLInputElement && field.type === \"checkbox\") {\n if (typeof value !== \"boolean\") return false;\n field.checked = value;\n return true;\n }\n if (field instanceof HTMLSelectElement && field.multiple) {\n if (!Array.isArray(value)) return false;\n const available = new Set(Array.from(field.options).map((option) => option.value));\n const selected = value.filter((candidate) => available.has(candidate));\n if (value.length > 0 && selected.length === 0) return false;\n const selectedValues = new Set(selected);\n for (const option of Array.from(field.options)) {\n option.selected = selectedValues.has(option.value);\n }\n return true;\n }\n if (typeof value !== \"string\") return false;\n if (field instanceof HTMLSelectElement) {\n const exists = Array.from(field.options).some((option) => option.value === value);\n if (!exists) return false;\n }\n field.value = value;\n return true;\n }\n\n /** Every control this instance owns, before the exclusion list narrows them. */\n #candidateFields(): PersistField[] {\n return this.hasFieldTarget\n ? this.fieldTargets.filter(isPersistField)\n : Array.from(this.element.querySelectorAll<PersistField>(\"input, textarea, select\")).filter(\n (field) => this.#ownsField(field),\n );\n }\n\n /**\n * Pairs persistable fields with DOM-order occurrence keys. Every HTML radio\n * group (same name and form owner) occupies one shared occurrence slot.\n */\n #fieldEntries(): Array<{ field: PersistField; key: string }> {\n const entries: Array<{ field: PersistField; key: string }> = [];\n const eligible: Array<{ field: PersistField; name: string }> = [];\n for (const field of this.#candidateFields()) {\n const name = this.#keyOf(field);\n if (name === null || !this.#persistable(field, this.#excluded)) continue;\n eligible.push({ field, name });\n }\n\n const nextOccurrence = new Map<string, number>();\n const radioSlots = new Map<string, Map<HTMLFormElement | null, string>>();\n const allocate = (name: string): string => {\n const occurrence = nextOccurrence.get(name) ?? 0;\n nextOccurrence.set(name, occurrence + 1);\n return occurrence === 0 ? name : `${name}${OCCURRENCE_SEP}${occurrence}`;\n };\n for (const { field, name } of eligible) {\n if (field instanceof HTMLInputElement && field.type === \"radio\") {\n const groups = radioSlots.get(name) ?? new Map<HTMLFormElement | null, string>();\n radioSlots.set(name, groups);\n let key = groups.get(field.form);\n if (key === undefined) {\n key = allocate(name);\n groups.set(field.form, key);\n }\n entries.push({ field, key });\n continue;\n }\n entries.push({ field, key: allocate(name) });\n }\n return entries;\n }\n\n /**\n * Whether a field carries a restorable, non-excluded value. A password field is never one,\n * also while a reveal has turned it into a text field: the lease that took its `type` over\n * still records the author's `password`.\n */\n #persistable(field: PersistField, excluded: readonly string[]): boolean {\n if (NON_VALUE_TYPES.has(field.type) || SENSITIVE_TYPES.has(field.type)) return false;\n if (SENSITIVE_TYPES.has(leasedAuthorValue(field, \"type\") ?? \"\")) return false;\n if (excluded.includes(field.type)) return false;\n const name = projectedFieldName(field.name);\n if (name.length > 0 && excluded.includes(name)) return false;\n return true;\n }\n\n /** A stable storage sub-key for a field (its logical submission name, else id). */\n #keyOf(field: PersistField): string | null {\n return projectedFieldName(field.name) || field.id || null;\n }\n\n /** Whether this instance, rather than a nested `stimeo--persist` host, owns a field. */\n #ownsField(field: PersistField): boolean {\n return field.closest(`[data-controller~=\"${this.identifier}\"]`) === this.element;\n }\n\n /** Marks all currently eligible fields without applying a payload. */\n #markCurrentFieldsKnown(): void {\n for (const { field } of this.#fieldEntries()) this.#knownFields.add(field);\n }\n\n /** Switches namespace after flushing the old namespace's pending edit. */\n #switchLogicalKey(): void {\n const next = this.#resolveLogicalKey();\n if (next === this.#logicalKey) return;\n this.#flushPendingSave();\n this.#logicalKey = next;\n this.#loadActiveDraft();\n }\n\n /** Synchronizes the exact event name owned by the `clearOn` Value. */\n #syncClearOn(): void {\n const next = this.#validEventName(this.clearOnValue);\n if (next === this.#registeredClearOn) return;\n this.#unbindClearOn();\n if (next === null) return;\n this.#clearOnListeners.add(this.element, next, this.#onClearEvent);\n this.#registeredClearOn = next;\n }\n\n /** Releases the listener for the name that was actually registered. */\n #unbindClearOn(): void {\n if (this.#registeredClearOn === null) return;\n this.#clearOnListeners.dispose();\n this.#registeredClearOn = null;\n }\n\n /** Returns a non-whitespace event type, or null when the hook is disabled. */\n #validEventName(value: string): string | null {\n const name = value.trim();\n return name.length > 0 && !/\\s/.test(name) ? name : null;\n }\n\n /**\n * Collects dynamic controls and select-option changes into one restore pass.\n *\n * @stimeoRuntimeOnly `key` decides whether an id change moves the storage namespace; it decides\n * nothing shown.\n */\n #onMutations(records: MutationRecord[]): void {\n let rootIdChanged = false;\n // The first record for an element carries its `data-controller` from before the batch.\n const ownershipBefore = new Map<Element, string | null>();\n for (const record of records) {\n if (record.type === \"attributes\") {\n if (record.target === this.element && record.attributeName === \"id\") {\n rootIdChanged = true;\n }\n if (record.attributeName === OWNERSHIP_ATTRIBUTE) {\n // An attribute record's target is always an element.\n const element = record.target as Element;\n if (!ownershipBefore.has(element)) ownershipBefore.set(element, record.oldValue);\n continue;\n }\n this.#collectControlCandidate(record.target);\n continue;\n }\n for (const node of record.addedNodes) this.#collectRestoreCandidate(node);\n }\n for (const [element, before] of ownershipBefore) {\n this.#collectOwnershipCandidate(element, before);\n }\n if (rootIdChanged && this.keyValue.length === 0) this.#switchLogicalKey();\n this.#restoreDynamic.schedule();\n }\n\n /**\n * Adds the controls under an element whose `data-controller` gained or lost this\n * identifier across the batch. That is the only attribute change that moves fields\n * between `stimeo--persist` hosts, so it is the single case worth a subtree sweep;\n * any other `data-controller` change leaves ownership where it was, and sweeping for\n * it would re-apply the stored draft over edits still being debounced.\n */\n #collectOwnershipCandidate(element: Element, before: string | null): void {\n const after = element.getAttribute(OWNERSHIP_ATTRIBUTE);\n if (this.#namesThisIdentifier(before) === this.#namesThisIdentifier(after)) return;\n this.#collectRestoreCandidate(element);\n }\n\n /** Whether a `data-controller` value lists this controller's identifier. */\n #namesThisIdentifier(tokens: string | null): boolean {\n return (tokens ?? \"\").split(/\\s+/).includes(this.identifier);\n }\n\n /** Adds a native control, or the select that owns a mutated option. */\n #collectControlCandidate(node: Node): void {\n if (isPersistField(node)) {\n this.#forcedRestore.add(node);\n return;\n }\n if (node instanceof HTMLOptionElement) {\n const select = node.closest(\"select\");\n if (select) this.#forcedRestore.add(select);\n }\n }\n\n /** Adds every control inside an inserted or newly owned subtree. */\n #collectRestoreCandidate(node: Node): void {\n this.#collectControlCandidate(node);\n if (!(node instanceof Element)) return;\n for (const field of node.querySelectorAll<PersistField>(\"input, textarea, select\")) {\n this.#forcedRestore.add(field);\n }\n }\n\n /**\n * Resolves the logical key from the Value, falling back to the host id.\n *\n * @stimeoRuntimeOnly `key` names the storage namespace; the restored fields come from what is\n * stored there.\n */\n #resolveLogicalKey(): string | null {\n const key = this.keyValue || this.element.id;\n return key.length > 0 ? key : null;\n }\n\n /** Namespaces one logical key within localStorage. */\n #storageKey(logicalKey: string): string {\n return `${STORAGE_PREFIX}${logicalKey}`;\n }\n\n /** Normalizes an invalid `debounce` Value to the `debounce` default. */\n get #debounceDelay(): number {\n return this.#safeDebounce;\n }\n\n /** Dispatches one observable storage failure without exposing browser errors. */\n #dispatchError(key: string, operation: PersistOperation, reason: PersistErrorReason): void {\n this.dispatch(\"error\", { detail: { key, operation, reason } });\n }\n /** Current `debounce` declaration resolved against its numeric contract. */\n get #safeDebounce(): number {\n return this.#numbers.read(\n this,\n \"debounce\",\n this.debounceValue,\n PersistController.values.debounce.default,\n PersistController.valueConstraints.debounce,\n );\n }\n}\n"]}
@@ -23,11 +23,19 @@ import { Controller } from '@hotwired/stimulus';
23
23
  * movement fires `move` (deltas cumulative from the origin), and release fires
24
24
  * `end` (`pointercancel` → `cancel`). Keyboard flow: Space/Enter on the handle
25
25
  * grabs (`start`, `data-grabbed`), the arrow keys emit synthetic `move` events of
26
- * `keyboardStep` px each, Space/Enter drops (`end`) and Escape cancels — so every
27
- * consumer gets a keyboard path for free.
26
+ * `keyboardStep` px each, Space/Enter drops (`end`) and Escape or focus leaving the
27
+ * keyboard-operable handle cancels — so every consumer gets a keyboard path for free.
28
+ * Bare Home/End preserve a grab without moving; modified Home/End and Tab are yielded.
29
+ * Native controls inside open shadow roots retain their editing keys and cancel a settled grab.
30
+ * Closed shadow roots expose only their host; their editing components must stop propagation
31
+ * of owned keys and use `reset()` when internal focus should end the surrounding grab
32
+ * (`reset()` always ends the gesture in flight; with `follow` on it also returns the
33
+ * element to its origin, dropping the committed follow offset and the inline `translate`,
34
+ * and with `follow` off it leaves the inline `translate` alone).
28
35
  *
29
36
  * `start` dispatches `{ x, y, pointerType }`; `move` dispatches `{ dx, dy, x, y, pointerType }`;
30
- * `end` dispatches `{ dx, dy, pointerType }`; `cancel` dispatches `{ pointerType }`.
37
+ * `end` dispatches `{ dx, dy, pointerType }`; `cancel` dispatches `{ pointerType }`, also
38
+ * when `reset()` ends a started drag or a grab (a press below the threshold ends silently).
31
39
  *
32
40
  * @remarks
33
41
  * Behavior only: consumers own all visuals (ghost, placeholder, transforms) by
@@ -101,15 +109,19 @@ declare class PointerDragController extends Controller<HTMLElement> {
101
109
  connect(): void;
102
110
  disconnect(): void;
103
111
  /**
104
- * Returns the element to its origin: drops the committed follow offset and the
105
- * inline `translate` that carries it.
112
+ * Ends the gesture in flight and, with `follow` on, returns the element to its origin.
106
113
  *
107
- * In follow mode the inline `translate` belongs to this controller, so this is the
108
- * way to put the element back at the start. An in-flight drag is cancelled first,
109
- * or its deltas would land on top of the offset just cleared.
114
+ * A pointer drag or keyboard grab in flight always ends, whatever `follow` says: a
115
+ * started drag or a grab dispatches `cancel`, a press still below the threshold ends
116
+ * silently. With `follow` on the inline `translate` belongs to this controller, so the
117
+ * committed follow offset and the `translate` carrying it are dropped too — the way
118
+ * to put the element back at the start. With `follow` off the inline `translate` is
119
+ * the author's and stays as it is. The `follow` that decides is the one the gesture
120
+ * in flight started with, or the current declaration when no gesture is in flight.
110
121
  */
111
122
  reset(): void;
112
123
  handleTargetConnected(handle: HTMLElement): void;
124
+ /** Releases a departed declaration while preserving current handles across connection moves. */
113
125
  handleTargetDisconnected(handle: HTMLElement): void;
114
126
  /**
115
127
  * Re-derives the handles' touch-action when the axis changes.