stimeo-ui 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/dist/controllers/alert_dialog_controller.d.ts +2 -0
  3. package/dist/controllers/alert_dialog_controller.js +75 -4
  4. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  5. package/dist/controllers/auto_submit_controller.d.ts +2 -0
  6. package/dist/controllers/auto_submit_controller.js.map +1 -1
  7. package/dist/controllers/avatar_controller.js +47 -5
  8. package/dist/controllers/avatar_controller.js.map +1 -1
  9. package/dist/controllers/breadcrumb_controller.d.ts +2 -0
  10. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  11. package/dist/controllers/bulk_select_controller.d.ts +2 -0
  12. package/dist/controllers/bulk_select_controller.js.map +1 -1
  13. package/dist/controllers/calendar_controller.d.ts +2 -0
  14. package/dist/controllers/calendar_controller.js.map +1 -1
  15. package/dist/controllers/character_counter_controller.d.ts +52 -20
  16. package/dist/controllers/character_counter_controller.js +338 -63
  17. package/dist/controllers/character_counter_controller.js.map +1 -1
  18. package/dist/controllers/checkbox_controller.d.ts +3 -0
  19. package/dist/controllers/checkbox_controller.js.map +1 -1
  20. package/dist/controllers/color_picker_controller.d.ts +3 -0
  21. package/dist/controllers/color_picker_controller.js.map +1 -1
  22. package/dist/controllers/combobox_controller.d.ts +2 -0
  23. package/dist/controllers/combobox_controller.js.map +1 -1
  24. package/dist/controllers/command_palette_controller.d.ts +2 -0
  25. package/dist/controllers/command_palette_controller.js +75 -4
  26. package/dist/controllers/command_palette_controller.js.map +1 -1
  27. package/dist/controllers/conditional_fields_controller.d.ts +42 -14
  28. package/dist/controllers/conditional_fields_controller.js +345 -51
  29. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  30. package/dist/controllers/confirm_controller.d.ts +2 -0
  31. package/dist/controllers/confirm_controller.js +75 -4
  32. package/dist/controllers/confirm_controller.js.map +1 -1
  33. package/dist/controllers/count_up_controller.d.ts +2 -0
  34. package/dist/controllers/count_up_controller.js.map +1 -1
  35. package/dist/controllers/countdown_controller.d.ts +4 -0
  36. package/dist/controllers/countdown_controller.js.map +1 -1
  37. package/dist/controllers/currency_input_controller.d.ts +2 -0
  38. package/dist/controllers/currency_input_controller.js.map +1 -1
  39. package/dist/controllers/data_grid_controller.d.ts +3 -0
  40. package/dist/controllers/data_grid_controller.js.map +1 -1
  41. package/dist/controllers/dialog_controller.js +75 -4
  42. package/dist/controllers/dialog_controller.js.map +1 -1
  43. package/dist/controllers/direct_upload_controller.d.ts +56 -24
  44. package/dist/controllers/direct_upload_controller.js +201 -45
  45. package/dist/controllers/direct_upload_controller.js.map +1 -1
  46. package/dist/controllers/dirty_form_controller.d.ts +14 -6
  47. package/dist/controllers/dirty_form_controller.js +192 -29
  48. package/dist/controllers/dirty_form_controller.js.map +1 -1
  49. package/dist/controllers/dismissible_controller.d.ts +2 -0
  50. package/dist/controllers/dismissible_controller.js +83 -18
  51. package/dist/controllers/dismissible_controller.js.map +1 -1
  52. package/dist/controllers/drawer_controller.js +75 -4
  53. package/dist/controllers/drawer_controller.js.map +1 -1
  54. package/dist/controllers/empty_state_controller.d.ts +2 -0
  55. package/dist/controllers/empty_state_controller.js.map +1 -1
  56. package/dist/controllers/file_dropzone_controller.d.ts +2 -0
  57. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  58. package/dist/controllers/filter_controller.d.ts +2 -0
  59. package/dist/controllers/filter_controller.js.map +1 -1
  60. package/dist/controllers/flash_controller.d.ts +4 -0
  61. package/dist/controllers/flash_controller.js.map +1 -1
  62. package/dist/controllers/focus_controller.d.ts +2 -0
  63. package/dist/controllers/focus_controller.js +75 -4
  64. package/dist/controllers/focus_controller.js.map +1 -1
  65. package/dist/controllers/form_field_controller.d.ts +50 -10
  66. package/dist/controllers/form_field_controller.js +280 -62
  67. package/dist/controllers/form_field_controller.js.map +1 -1
  68. package/dist/controllers/form_validation_controller.d.ts +10 -8
  69. package/dist/controllers/form_validation_controller.js +208 -83
  70. package/dist/controllers/form_validation_controller.js.map +1 -1
  71. package/dist/controllers/frame_loading_controller.d.ts +2 -0
  72. package/dist/controllers/frame_loading_controller.js.map +1 -1
  73. package/dist/controllers/highlight_controller.d.ts +2 -0
  74. package/dist/controllers/highlight_controller.js.map +1 -1
  75. package/dist/controllers/idle_controller.d.ts +2 -0
  76. package/dist/controllers/idle_controller.js.map +1 -1
  77. package/dist/controllers/input_mask_controller.d.ts +2 -0
  78. package/dist/controllers/input_mask_controller.js.map +1 -1
  79. package/dist/controllers/lazy_frame_controller.d.ts +2 -0
  80. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  81. package/dist/controllers/listbox_controller.d.ts +2 -0
  82. package/dist/controllers/listbox_controller.js.map +1 -1
  83. package/dist/controllers/local_time_controller.d.ts +2 -0
  84. package/dist/controllers/local_time_controller.js.map +1 -1
  85. package/dist/controllers/masonry_controller.d.ts +2 -0
  86. package/dist/controllers/masonry_controller.js.map +1 -1
  87. package/dist/controllers/meter_controller.d.ts +2 -0
  88. package/dist/controllers/meter_controller.js.map +1 -1
  89. package/dist/controllers/multi_select_controller.d.ts +2 -0
  90. package/dist/controllers/multi_select_controller.js.map +1 -1
  91. package/dist/controllers/nested_form_controller.d.ts +2 -0
  92. package/dist/controllers/nested_form_controller.js.map +1 -1
  93. package/dist/controllers/network_status_controller.d.ts +2 -0
  94. package/dist/controllers/network_status_controller.js.map +1 -1
  95. package/dist/controllers/number_input_controller.d.ts +2 -0
  96. package/dist/controllers/number_input_controller.js +47 -5
  97. package/dist/controllers/number_input_controller.js.map +1 -1
  98. package/dist/controllers/otp_controller.d.ts +3 -0
  99. package/dist/controllers/otp_controller.js.map +1 -1
  100. package/dist/controllers/overflow_indicator_controller.d.ts +2 -0
  101. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  102. package/dist/controllers/overflow_menu_controller.d.ts +2 -0
  103. package/dist/controllers/overflow_menu_controller.js +2 -1
  104. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  105. package/dist/controllers/pagination_controller.d.ts +2 -0
  106. package/dist/controllers/pagination_controller.js +2 -1
  107. package/dist/controllers/pagination_controller.js.map +1 -1
  108. package/dist/controllers/password_reveal_controller.d.ts +2 -0
  109. package/dist/controllers/password_reveal_controller.js.map +1 -1
  110. package/dist/controllers/password_strength_controller.d.ts +2 -0
  111. package/dist/controllers/password_strength_controller.js.map +1 -1
  112. package/dist/controllers/persist_controller.d.ts +30 -16
  113. package/dist/controllers/persist_controller.js +432 -122
  114. package/dist/controllers/persist_controller.js.map +1 -1
  115. package/dist/controllers/pointer_drag_controller.d.ts +3 -0
  116. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  117. package/dist/controllers/popover_controller.js +77 -4
  118. package/dist/controllers/popover_controller.js.map +1 -1
  119. package/dist/controllers/portal_controller.d.ts +2 -0
  120. package/dist/controllers/portal_controller.js.map +1 -1
  121. package/dist/controllers/preview_guard_controller.d.ts +2 -0
  122. package/dist/controllers/preview_guard_controller.js.map +1 -1
  123. package/dist/controllers/progress_controller.d.ts +3 -0
  124. package/dist/controllers/progress_controller.js.map +1 -1
  125. package/dist/controllers/radio_group_controller.d.ts +3 -0
  126. package/dist/controllers/radio_group_controller.js.map +1 -1
  127. package/dist/controllers/rating_controller.d.ts +2 -0
  128. package/dist/controllers/rating_controller.js +9 -5
  129. package/dist/controllers/rating_controller.js.map +1 -1
  130. package/dist/controllers/reading_progress_controller.d.ts +2 -0
  131. package/dist/controllers/reading_progress_controller.js.map +1 -1
  132. package/dist/controllers/resizable_controller.d.ts +2 -0
  133. package/dist/controllers/resizable_controller.js.map +1 -1
  134. package/dist/controllers/roving_controller.d.ts +2 -0
  135. package/dist/controllers/roving_controller.js.map +1 -1
  136. package/dist/controllers/scroll_area_controller.d.ts +23 -15
  137. package/dist/controllers/scroll_area_controller.js +462 -162
  138. package/dist/controllers/scroll_area_controller.js.map +1 -1
  139. package/dist/controllers/scroll_visibility_controller.d.ts +2 -0
  140. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  141. package/dist/controllers/scrollspy_controller.d.ts +2 -0
  142. package/dist/controllers/scrollspy_controller.js.map +1 -1
  143. package/dist/controllers/separator_controller.d.ts +54 -11
  144. package/dist/controllers/separator_controller.js +354 -38
  145. package/dist/controllers/separator_controller.js.map +1 -1
  146. package/dist/controllers/sidebar_controller.js +83 -10
  147. package/dist/controllers/sidebar_controller.js.map +1 -1
  148. package/dist/controllers/skeleton_controller.d.ts +2 -0
  149. package/dist/controllers/skeleton_controller.js.map +1 -1
  150. package/dist/controllers/slider_controller.d.ts +2 -0
  151. package/dist/controllers/slider_controller.js.map +1 -1
  152. package/dist/controllers/smart_sticky_header_controller.d.ts +2 -0
  153. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  154. package/dist/controllers/spinner_controller.d.ts +2 -0
  155. package/dist/controllers/spinner_controller.js.map +1 -1
  156. package/dist/controllers/step_indicator_controller.d.ts +2 -0
  157. package/dist/controllers/step_indicator_controller.js.map +1 -1
  158. package/dist/controllers/stepper_controller.d.ts +2 -0
  159. package/dist/controllers/stepper_controller.js.map +1 -1
  160. package/dist/controllers/stick_to_bottom_controller.d.ts +2 -0
  161. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  162. package/dist/controllers/sticky_observer_controller.d.ts +2 -0
  163. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  164. package/dist/controllers/submit_once_controller.d.ts +94 -38
  165. package/dist/controllers/submit_once_controller.js +399 -121
  166. package/dist/controllers/submit_once_controller.js.map +1 -1
  167. package/dist/controllers/switch_controller.d.ts +2 -0
  168. package/dist/controllers/switch_controller.js.map +1 -1
  169. package/dist/controllers/tags_input_controller.d.ts +2 -0
  170. package/dist/controllers/tags_input_controller.js.map +1 -1
  171. package/dist/controllers/textarea_autosize_controller.d.ts +2 -0
  172. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  173. package/dist/controllers/theme_controller.d.ts +2 -0
  174. package/dist/controllers/theme_controller.js +8 -6
  175. package/dist/controllers/theme_controller.js.map +1 -1
  176. package/dist/controllers/time_picker_controller.d.ts +2 -0
  177. package/dist/controllers/time_picker_controller.js.map +1 -1
  178. package/dist/controllers/toast_controller.d.ts +4 -0
  179. package/dist/controllers/toast_controller.js.map +1 -1
  180. package/dist/controllers/toggle_group_controller.d.ts +2 -0
  181. package/dist/controllers/toggle_group_controller.js.map +1 -1
  182. package/dist/controllers/toolbar_controller.js.map +1 -1
  183. package/dist/controllers/transition_controller.d.ts +2 -0
  184. package/dist/controllers/transition_controller.js.map +1 -1
  185. package/dist/controllers/tree_view_controller.d.ts +2 -0
  186. package/dist/controllers/tree_view_controller.js +2 -1
  187. package/dist/controllers/tree_view_controller.js.map +1 -1
  188. package/dist/index.js +2387 -861
  189. package/dist/index.js.map +1 -1
  190. package/dist/inspector/cli.d.ts +107 -3
  191. package/dist/inspector/cli.js +192 -14
  192. package/dist/inspector/cli.js.map +1 -1
  193. package/dist/inspector/cli_bin.js +254 -46
  194. package/dist/inspector/cli_bin.js.map +1 -1
  195. package/dist/inspector/examples.json +7 -7
  196. package/dist/inspector/manifest.json +434 -44
  197. package/dist/positioning/index.d.ts +2 -0
  198. package/dist/positioning/index.js.map +1 -1
  199. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/arrow_step.ts","../../src/utils/attribute_lease.ts","../../src/utils/composition_tracker.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/safe_timeout.ts","../../src/utils/stepped_value.ts","../../src/controllers/number_input_controller.ts"],"names":["position"],"mappings":"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","file":"number_input_controller.js","sourcesContent":["import { isRtl } from \"./logical_scroll\";\n\n/**\n * Turns an arrow key into a **logical** step: `+1` for \"next\", `-1` for\n * \"previous\", `0` when the key names neither.\n *\n * APG defines the horizontal pair as *next / previous* and says a vertical\n * arrangement swaps in Down/Up for the same meaning — so the pair is one axis's\n * spelling of an order, and the order reverses with the writing direction. Only\n * the horizontal pair reverses. Down/Up name an axis the writing direction does\n * not mirror, and returning them unchanged is the point: many controllers fold\n * both pairs into one branch, where swapping the branches under RTL would flip\n * the vertical axis too — a bug that reads as \"the arrows work\" until someone\n * presses Down.\n *\n * **Direction is read from the element the caller passes, which should be the\n * container that lays the items out** — not the focused child. A child may carry\n * its own `dir` (an LTR input inside an RTL form is ordinary authoring), and\n * probing per handler makes two handlers disagree at the boundary between them.\n *\n * This decides direction only. Whether the axis is even active (an\n * `orientation=\"horizontal\"` widget ignoring Down/Up), how far the step lands,\n * and what wrapping does all stay with the caller.\n *\n * **It encodes the list-order convention: `ArrowDown` is *next*.** Widgets that\n * pair the arrows by *value* instead — `ArrowUp` meaning \"more\", as a rating or a\n * slider does — must not use this, or their vertical axis inverts. Reverse the\n * horizontal pair on its own there.\n *\n * @example\n * ```ts\n * const step = logicalArrowStep(event.key, this.element);\n * if (step === 0) return;\n * this.#roving.setActive(rovingMove(current, length, step, \"wrap\"), { focus: true });\n * ```\n */\nexport function logicalArrowStep(key: string, element: Element): 1 | -1 | 0 {\n if (key === \"ArrowDown\") return 1;\n if (key === \"ArrowUp\") return -1;\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return 0;\n const forward = isRtl(element) ? \"ArrowLeft\" : \"ArrowRight\";\n return key === forward ? 1 : -1;\n}\n\n/**\n * Rewrites `key` so an existing LTR-shaped branch keeps working under RTL:\n * `ArrowRight` and `ArrowLeft` trade places, everything else passes through.\n *\n * The alternative — negating a delta — silently breaks handlers whose two\n * horizontal branches are **not mirror images**. A grid that clamps one edge but\n * not the other, or a segmented field guarding `index > 0` on one side and\n * `index < length - 1` on the other, ends up applying the wrong guard to the\n * wrong direction. Swapping the key leaves each branch, guards and all, exactly\n * where its author put it.\n *\n * Same rule as {@link logicalArrowStep} about which element to read: pass the\n * container that lays the items out, not the focused child.\n *\n * @example\n * ```ts\n * switch (logicalArrowKey(event.key, this.element)) {\n * case \"ArrowLeft\": // \"previous\" — whatever direction that is on screen\n * ```\n */\nexport function logicalArrowKey(key: string, element: Element): string {\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return key;\n if (!isRtl(element)) return key;\n return key === \"ArrowRight\" ? \"ArrowLeft\" : \"ArrowRight\";\n}\n\n/** Modifiers a widget may claim on an arrow key, named for the `allow` list. */\nexport type ArrowModifier = \"alt\" | \"ctrl\" | \"meta\" | \"shift\";\n\n/**\n * True when an arrow key arrived carrying a modifier the widget must leave to\n * the browser: return without calling `preventDefault()` and without moving any\n * state.\n *\n * A bare arrow belongs to the widget; a chorded one usually does not.\n * `Alt`/`Meta` plus a horizontal arrow is history back/forward on every desktop\n * browser, and a widget that swallows it makes the shortcut work or not\n * depending on where focus happens to sit — a coin-flip the user cannot see.\n *\n * `allow` is for the combinations APG assigns to a pattern **and the widget\n * actually implements** — today only Combobox's optional `Alt+Down`/`Alt+Up`.\n * Listing one the widget does not implement defeats the point: the chord then\n * runs the plain-arrow branch, which is exactly what this guard exists to stop.\n * Non-arrow keys return `false`, so chorded letters and\n * `Control+Home`/`Control+End` are untouched.\n *\n * @example\n * ```ts\n * if (isReservedArrowChord(event)) return;\n * ```\n */\nexport function isReservedArrowChord(\n event: KeyboardEvent,\n allow: readonly ArrowModifier[] = [],\n): boolean {\n if (!event.key.startsWith(\"Arrow\")) return false;\n return (\n (event.altKey && !allow.includes(\"alt\")) ||\n (event.ctrlKey && !allow.includes(\"ctrl\")) ||\n (event.metaKey && !allow.includes(\"meta\")) ||\n (event.shiftKey && !allow.includes(\"shift\"))\n );\n}\n","/** One temporarily controlled attribute value and the authored value it displaced. */\ninterface AttributeLeaseRecord {\n readonly original: string | null;\n written: string | null;\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 */\nexport class AttributeLease<T extends Element = Element> {\n readonly #attribute: string;\n readonly #records = new Map<T, AttributeLeaseRecord>();\n\n /** @param attribute - The attribute whose temporary values this lease owns. */\n constructor(attribute: string) {\n this.#attribute = attribute;\n }\n\n /** Writes or removes the leased attribute while preserving its authored value. */\n write(element: T, value: string | null): void {\n const existing = this.#records.get(element);\n if (existing) {\n existing.written = value;\n } else {\n this.#records.set(element, {\n original: element.getAttribute(this.#attribute),\n written: value,\n });\n }\n\n if (value === null) element.removeAttribute(this.#attribute);\n else element.setAttribute(this.#attribute, value);\n }\n\n /** Returns one lease without overwriting a value subsequently authored by a consumer. */\n return(element: T): void {\n const record = this.#records.get(element);\n if (!record) return;\n this.#records.delete(element);\n if (element.getAttribute(this.#attribute) !== record.written) return;\n\n if (record.original === null) element.removeAttribute(this.#attribute);\n else element.setAttribute(this.#attribute, record.original);\n }\n\n /** Returns every outstanding lease using the same ownership check as {@link return}. */\n returnAll(): void {\n for (const element of Array.from(this.#records.keys())) this.return(element);\n }\n}\n","/** Minimal event shape carrying the platform's per-event composition signal. */\nexport interface CompositionSignal {\n readonly isComposing?: boolean;\n}\n\n/** Hooks that keep component-specific work outside {@link CompositionTracker}. */\nexport interface CompositionTrackerOptions {\n /** Runs after lifecycle state is set for a `compositionstart` event. */\n readonly onStart?: (event: Event) => void;\n /** Runs after lifecycle state is cleared for a `compositionend` event. */\n readonly onEnd?: (event: Event) => void;\n}\n\n/**\n * Owns IME composition listeners and transient state for one or more event targets.\n *\n * Some browsers omit `KeyboardEvent.isComposing` on the keydown that confirms a\n * conversion. Tracking `compositionstart` through `compositionend` supplies the\n * missing lifecycle signal without relying on deprecated numeric key codes.\n * Component policy stays with the consumer: filtering, validation, and submission\n * belong in the optional {@link CompositionTrackerOptions.onEnd} callback.\n *\n * @example\n * ```ts\n * #composition = new CompositionTracker({ onEnd: () => this.filter() });\n *\n * connect(): void {\n * this.#composition.observe(this.inputTarget);\n * }\n *\n * disconnect(): void {\n * this.#composition.disconnect();\n * }\n *\n * onKeydown(event: KeyboardEvent): void {\n * if (this.#composition.isComposing(event)) return;\n * }\n * ```\n */\nexport class CompositionTracker {\n readonly #observedTargets = new Set<EventTarget>();\n readonly #activeTargets = new Set<EventTarget>();\n readonly #onStart: ((event: Event) => void) | undefined;\n readonly #onEnd: ((event: Event) => void) | undefined;\n\n constructor(options: CompositionTrackerOptions = {}) {\n this.#onStart = options.onStart;\n this.#onEnd = options.onEnd;\n }\n\n /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */\n observe(target: EventTarget): void {\n if (this.#observedTargets.has(target)) return;\n target.addEventListener(\"compositionstart\", this.#handleStart);\n target.addEventListener(\"compositionend\", this.#handleEnd);\n this.#observedTargets.add(target);\n }\n\n /** Stops tracking one target and clears any active composition it owned. */\n unobserve(target: EventTarget): void {\n if (!this.#observedTargets.delete(target)) return;\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n this.#activeTargets.delete(target);\n }\n\n /** Releases every listener and clears state so reconnect starts cleanly. */\n disconnect(): void {\n for (const target of this.#observedTargets) {\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n }\n this.#observedTargets.clear();\n this.#activeTargets.clear();\n }\n\n /** True when lifecycle tracking or the current event reports composition. */\n isComposing(event?: CompositionSignal): boolean {\n return this.#activeTargets.size > 0 || event?.isComposing === true;\n }\n\n readonly #handleStart = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.add(event.currentTarget);\n this.#onStart?.(event);\n };\n\n readonly #handleEnd = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);\n this.#onEnd?.(event);\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 * This file's own doc block is dropped from `dist`, but every member comment is\n * inlined into each consumer entry (`tsup` builds with `splitting: false`), so\n * rationale belongs here and only the contract belongs on the members.\n *\n * @example\n * ```ts\n * readonly #reconcile = new MicrotaskCoalescer(() => this.#reconcileOptions());\n *\n * connect() { this.#reconcile.activate(); }\n * disconnect() { this.#reconcile.cancel(); }\n *\n * optionTargetConnected() { this.#reconcile.schedule(); }\n * optionTargetDisconnected() { this.#reconcile.schedule(); }\n * ```\n */\nexport class MicrotaskCoalescer {\n readonly #run: () => void;\n #queued = false;\n #active = false;\n #generation = 0;\n\n /** @param run - the single reconciliation pass, invoked at most once per batch. */\n constructor(run: () => void) {\n this.#run = run;\n }\n\n /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */\n activate(): void {\n this.#active = true;\n }\n\n /** Closes the window and drops any pending pass; call from `disconnect()`. */\n cancel(): void {\n this.#active = false;\n this.#queued = false;\n this.#generation += 1;\n }\n\n /** Requests one pass after the batch settles. Idempotent; inert outside the window. */\n schedule(): void {\n if (!this.#active || this.#queued) return;\n this.#queued = true;\n const generation = this.#generation;\n queueMicrotask(() => {\n // A cancelled callback must not consume a pass queued after reconnect.\n if (generation !== this.#generation || !this.#queued || !this.#active) return;\n this.#queued = false;\n this.#run();\n });\n }\n}\n","/**\n * 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\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","/** Configuration for a value constrained to a stepped numeric range. */\nexport interface SteppedRange {\n /** Inclusive lower endpoint. May be infinite for an unbounded control. */\n readonly min: number;\n /** Inclusive upper endpoint. May be infinite for an unbounded control. */\n readonly max: number;\n /** Requested step. Non-finite and non-positive values fall back to `1`. */\n readonly step: number;\n /** Step-grid origin. Defaults to a finite `min`, otherwise `0`. */\n readonly base?: number;\n}\n\n/** The positive finite step used at runtime and by keyboard stepping. */\nexport function effectiveStep(step: number): number {\n return Number.isFinite(step) && step > 0 ? step : 1;\n}\n\n/**\n * Clamps a raw value and selects its nearest allowed value.\n *\n * The allowed set is the step grid plus each finite range endpoint. Keeping the\n * endpoints in that set makes an authored `aria-valuemin`/`aria-valuemax`\n * truthful even when the upper endpoint is not aligned to the grid. A value\n * exactly between two allowed values resolves upward.\n */\nexport function snapSteppedValue(raw: number, range: SteppedRange): number {\n if (!(range.min <= range.max)) return finiteFallback(range.min, range.max);\n\n const input = Number.isNaN(raw) ? finiteFallback(range.min, range.max) : raw;\n const clamped = Math.min(range.max, Math.max(range.min, input));\n const step = effectiveStep(range.step);\n const base = stepBase(range);\n const candidates: number[] = [];\n\n if (Number.isFinite(range.min)) candidates.push(range.min);\n if (Number.isFinite(range.max)) candidates.push(range.max);\n\n const gridPosition = (clamped - base) / step;\n if (Number.isFinite(gridPosition)) {\n addGridCandidate(candidates, Math.floor(gridPosition), range, base, step);\n addGridCandidate(candidates, Math.ceil(gridPosition), range, base, step);\n }\n\n if (candidates.length === 0) return clamped;\n let nearest = candidates[0] as number;\n let nearestDistance = Math.abs(clamped - nearest);\n for (const candidate of candidates.slice(1)) {\n const distance = Math.abs(clamped - candidate);\n if (\n distance < nearestDistance ||\n (nearlyEqual(distance, nearestDistance) && candidate > nearest)\n ) {\n nearest = candidate;\n nearestDistance = distance;\n }\n }\n return nearest;\n}\n\n/**\n * Moves through the ordered allowed-value set by an integer number of steps.\n *\n * This differs from adding `step * count` and snapping afterward at an\n * off-grid endpoint: with `max=94, step=10`, one decrement from `94` must land\n * on `90`, and one increment from `90` must reach the advertised maximum `94`.\n */\nexport function stepSteppedValue(current: number, count: number, range: SteppedRange): number {\n const value = snapSteppedValue(current, range);\n const distance = Math.abs(Math.trunc(count));\n if (!Number.isFinite(distance) || distance === 0) return value;\n const direction = Math.sign(count);\n const adjacent = adjacentSteppedValue(value, direction, range);\n\n // The first move accounts for a possibly off-grid endpoint. From there a\n // direct grid jump is equivalent to repeated adjacency, and avoids work that\n // grows with Page-step magnitudes or programmatic counts.\n const raw = adjacent + direction * (distance - 1) * effectiveStep(range.step);\n return snapSteppedValue(raw, range);\n}\n\n/** Returns the next member of the ordered endpoint-plus-grid set. */\nfunction adjacentSteppedValue(current: number, direction: number, range: SteppedRange): number {\n const step = effectiveStep(range.step);\n const base = stepBase(range);\n const candidates: number[] = [];\n\n if (direction > 0) {\n const position = (current - base) / step;\n if (Number.isFinite(position)) {\n let gridIndex = Math.floor(position) + 1;\n let candidate = cleanGridValue(base + gridIndex * step, base, step);\n if (candidate < current || nearlyEqual(candidate, current)) {\n gridIndex += 1;\n candidate = cleanGridValue(base + gridIndex * step, base, step);\n }\n if (\n candidate > current &&\n !nearlyEqual(candidate, current) &&\n within(candidate, range.min, range.max)\n ) {\n candidates.push(clamp(candidate, range));\n }\n }\n return clamp(Math.min(...candidates), range);\n }\n\n const position = (current - base) / step;\n if (Number.isFinite(position)) {\n let gridIndex = Math.ceil(position) - 1;\n let candidate = cleanGridValue(base + gridIndex * step, base, step);\n if (candidate > current || nearlyEqual(candidate, current)) {\n gridIndex -= 1;\n candidate = cleanGridValue(base + gridIndex * step, base, step);\n }\n if (\n candidate < current &&\n !nearlyEqual(candidate, current) &&\n within(candidate, range.min, range.max)\n ) {\n candidates.push(clamp(candidate, range));\n }\n }\n return clamp(Math.max(...candidates), range);\n}\n\n/** Adds one grid value when it falls inside the inclusive range. */\nfunction addGridCandidate(\n candidates: number[],\n index: number,\n range: SteppedRange,\n base: number,\n step: number,\n): void {\n const candidate = cleanGridValue(base + index * step, base, step);\n if (within(candidate, range.min, range.max)) candidates.push(clamp(candidate, range));\n}\n\n/** A finite authored base wins; otherwise the finite lower bound or zero does. */\nfunction stepBase(range: SteppedRange): number {\n if (range.base !== undefined && Number.isFinite(range.base)) return range.base;\n return Number.isFinite(range.min) ? range.min : 0;\n}\n\n/** Removes binary noise without discarding significant integer-place digits. */\nfunction cleanGridValue(value: number, base: number, step: number): number {\n const precision = Math.max(decimalPlaces(base), decimalPlaces(step));\n // `toFixed` accepts at most 100 fractional digits. Below that limit it rounds\n // according to the authored grid precision rather than an arbitrary total\n // significant-digit count, which keeps unit steps distinct at large bases.\n return precision <= 100 ? Number(value.toFixed(precision)) : value;\n}\n\n/** Number of fractional decimal places represented by a finite JS number. */\nfunction decimalPlaces(value: number): number {\n const [coefficient = \"\", exponentText] = Math.abs(value).toString().toLowerCase().split(\"e\");\n const fractionLength = coefficient.split(\".\")[1]?.length ?? 0;\n const exponent = exponentText === undefined ? 0 : Number(exponentText);\n return Math.max(0, fractionLength - exponent);\n}\n\n/** Inclusive range check tolerant only of arithmetic noise at an endpoint. */\nfunction within(value: number, min: number, max: number): boolean {\n return (value > min || nearlyEqual(value, min)) && (value < max || nearlyEqual(value, max));\n}\n\n/** Clamps a candidate whose only overshoot may be floating-point noise. */\nfunction clamp(value: number, range: SteppedRange): number {\n return Math.min(range.max, Math.max(range.min, value));\n}\n\n/** Relative comparison used only to collapse arithmetic noise, not real steps. */\nfunction nearlyEqual(left: number, right: number): boolean {\n const scale = Math.max(Math.abs(left), Math.abs(right));\n return (\n Number.isFinite(left) &&\n Number.isFinite(right) &&\n Math.abs(left - right) <= Number.EPSILON * scale\n );\n}\n\n/** Stable fallback for malformed ranges or `NaN` input. */\nfunction finiteFallback(min: number, max: number): number {\n if (Number.isFinite(min)) return min;\n if (Number.isFinite(max)) return max;\n return 0;\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { isReservedArrowChord } from \"../utils/arrow_step\";\nimport { AttributeLease } from \"../utils/attribute_lease\";\nimport { CompositionTracker } from \"../utils/composition_tracker\";\nimport { MicrotaskCoalescer } from \"../utils/microtask_coalescer\";\nimport { SafeInterval, SafeTimeout } from \"../utils/safe_timeout\";\nimport { snapSteppedValue, stepSteppedValue } from \"../utils/stepped_value\";\n\n/** Marks a `disabled` state derived and therefore removable by this controller. */\nconst OWNED_DISABLED = \"data-number-input-disabled\";\n\n/**\n * Headless, accessible number / spin-button behavior.\n *\n * Markup contract (identifier: `stimeo--number-input`):\n * <div data-controller=\"stimeo--number-input\"\n * data-stimeo--number-input-min-value=\"0\"\n * data-stimeo--number-input-max-value=\"100\"\n * data-stimeo--number-input-step-value=\"1\">\n * <button type=\"button\" aria-label=\"Decrease\" tabindex=\"-1\"\n * data-stimeo--number-input-target=\"decrement\"\n * data-action=\"click->stimeo--number-input#decrement\">−</button>\n * <input type=\"number\" min=\"0\" max=\"100\" step=\"1\" value=\"0\"\n * data-stimeo--number-input-target=\"input\"\n * data-action=\"change->stimeo--number-input#onInput\n * keydown->stimeo--number-input#onKeydown\" />\n * <button type=\"button\" aria-label=\"Increase\" tabindex=\"-1\"\n * data-stimeo--number-input-target=\"increment\"\n * data-action=\"click->stimeo--number-input#increment\">+</button>\n * </div>\n *\n * Implements the WAI-ARIA APG **Spinbutton** pattern. The arrow/step logic is\n * fully owned by the controller (not delegated to the browser's native number\n * stepping) so the behavior is identical for a native `<input type=\"number\">` and\n * a custom `role=\"spinbutton\"` host.\n *\n * @remarks\n * Behavior only — the consumer styles the field and buttons. The input is the\n * sole Tab stop; the buttons are `tabindex=\"-1\"` and keep focus on the input\n * (pointerdown is suppressed), so stepping never moves focus away.\n *\n * Behavior provided:\n * - `ArrowUp`/`ArrowDown` step by `step`; `PageUp`/`PageDown` by `pageStep`\n * (default `step × 10`); `Home`/`End` jump to a finite `min`/`max`.\n * - Increment/decrement buttons step too, and are `disabled` at the bounds (focus\n * is returned to the input before a focused button is disabled).\n * - **Press-and-hold auto-repeat**: holding a step button steps once, then after a\n * short delay repeats until release, the bound is reached, or the element\n * disconnects. The `click` binding stays the single-step path (a quick click, a\n * synthesized/programmatic click, or assistive activation), so a normal click\n * never double-steps — the trailing click after a hold is swallowed.\n * - Typed input is clamped and snapped to the step grid on `change`;\n * `stimeo--number-input:change` is dispatched once for each changed committed\n * numeric value with `{ value: number }` detail. When a runtime `min`/`max`/\n * `step` change pulls the committed value with it, that same detail arrives as\n * `stimeo--number-input:reconcile` instead, so a consumer can tell its own edit\n * from the controller's repair. Neither event fires on connect.\n * - `step` must be finite and positive; invalid runtime input falls back to `1`,\n * while finite range endpoints remain reachable off the grid.\n */\nexport class NumberInputController extends Controller<HTMLElement> {\n static override targets = [\"input\", \"increment\", \"decrement\"];\n static override values = {\n min: { type: Number, default: Number.NEGATIVE_INFINITY },\n max: { type: Number, default: Number.POSITIVE_INFINITY },\n step: { type: Number, default: 1 },\n pageStep: { type: Number, default: 0 },\n };\n static actions = [\"decrement\", \"increment\", \"onInput\", \"onKeydown\"] as const;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly inputTarget: HTMLInputElement;\n declare readonly hasInputTarget: boolean;\n declare readonly incrementTarget: HTMLButtonElement;\n declare readonly incrementTargets: HTMLButtonElement[];\n declare readonly hasIncrementTarget: boolean;\n declare readonly decrementTarget: HTMLButtonElement;\n declare readonly decrementTargets: HTMLButtonElement[];\n declare readonly hasDecrementTarget: boolean;\n declare minValue: number;\n declare maxValue: number;\n declare stepValue: number;\n declare pageStepValue: number;\n\n /** Delay (ms) a button must be held before auto-repeat starts. */\n static readonly #HOLD_DELAY_MS = 400;\n /** Interval (ms) between auto-repeat steps once a hold has started. */\n static readonly #HOLD_REPEAT_MS = 80;\n /**\n * Window (ms) after a hold ends during which the trailing synthetic `click` is\n * swallowed. A safety net for the (rare) case where that click never arrives\n * (e.g. the pointer was released off the button): the flag self-clears instead\n * of poisoning the next legitimate click.\n */\n static readonly #SUPPRESS_RESET_MS = 250;\n\n /** Aborts global pointer guards on disconnect so none outlive the element. */\n #globalGuards: AbortController | null = null;\n /** Per-target guards allow an old button to be released without touching its replacement. */\n readonly #buttonGuards = new Map<HTMLButtonElement, AbortController>();\n /** Tracks IME lifecycle on the current input, including confirming keys without a signal. */\n readonly #composition = new CompositionTracker();\n /** Restores authored custom-spinbutton ARIA when a target leaves or the controller stops. */\n readonly #ariaValueNow = new AttributeLease<HTMLInputElement>(\"aria-valuenow\");\n readonly #ariaValueMin = new AttributeLease<HTMLInputElement>(\"aria-valuemin\");\n readonly #ariaValueMax = new AttributeLease<HTMLInputElement>(\"aria-valuemax\");\n /** Last reconciled or user-committed numeric value. */\n #lastValue: number | null = null;\n /** Timers for the hold delay and the suppress-reset safety net. */\n readonly #holdTimeouts = new SafeTimeout();\n /** The running auto-repeat interval (one at a time). */\n readonly #holdIntervals = new SafeInterval();\n /** True while a hold is armed/running, making `#stopHold` idempotent. */\n #holdActive = false;\n /** True once a hold actually produced a repeated step (vs. a quick click). */\n #repeatedDuringHold = false;\n /** True when the next `click` is the trailing one after a hold and must be ignored. */\n #suppressNextClick = false;\n /** Button and pointer that own the current hold, so other instances/pointers cannot end it. */\n #holdButton: HTMLButtonElement | null = null;\n #holdPointerId: number | null = null;\n /** Collapses runtime range/step changes into one input reconciliation. */\n readonly #repaint = new MicrotaskCoalescer(() => this.#reconcile());\n\n /** Normalizes any initial value and wires the focus/hold pointer guards. */\n override connect(): void {\n this.#repaint.activate();\n this.#globalGuards = new AbortController();\n const { signal } = this.#globalGuards;\n for (const button of this.incrementTargets) this.#wireButton(button, 1);\n for (const button of this.decrementTargets) this.#wireButton(button, -1);\n // A pointer released or focus lost anywhere stops a running hold, even when\n // the button stopped receiving its own pointerup (e.g. it became disabled at\n // the bound, or the pointer was released off it).\n window.addEventListener(\"pointerup\", this.#onPointerEnd, { signal });\n window.addEventListener(\"pointercancel\", this.#onPointerEnd, { signal });\n window.addEventListener(\"blur\", this.#onWindowBlur, { signal });\n this.#reconcile();\n }\n\n /** Releases listeners, derived attributes, timers, and transient value state. */\n override disconnect(): void {\n this.#repaint.cancel();\n this.#composition.disconnect();\n this.#globalGuards?.abort();\n this.#globalGuards = null;\n const buttons = new Set([\n ...this.#buttonGuards.keys(),\n ...this.incrementTargets,\n ...this.decrementTargets,\n ]);\n for (const guard of this.#buttonGuards.values()) guard.abort();\n this.#buttonGuards.clear();\n for (const button of buttons) this.#releaseButtonState(button);\n this.#stopHold(false);\n this.#repeatedDuringHold = false;\n this.#suppressNextClick = false;\n this.#holdTimeouts.clearAll();\n this.#holdIntervals.clearAll();\n this.#ariaValueNow.returnAll();\n this.#ariaValueMin.returnAll();\n this.#ariaValueMax.returnAll();\n this.#lastValue = null;\n }\n\n /** Reconciles the value against a minimum changed by application code or a Turbo morph. */\n minValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Reconciles the value against a maximum changed by application code or a Turbo morph. */\n maxValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Reconciles the value against a step changed by application code or a Turbo morph. */\n stepValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Tracks and reconciles an input inserted or replaced at runtime. */\n inputTargetConnected(input: HTMLInputElement): void {\n this.#composition.observe(input);\n this.#repaint.schedule();\n }\n\n /** Releases ARIA and composition state owned by an input that left the controller. */\n inputTargetDisconnected(input: HTMLInputElement): void {\n this.#composition.unobserve(input);\n this.#releaseInputAria(input);\n this.#stopHold(false);\n this.#lastValue = null;\n this.#repaint.schedule();\n }\n\n /** Wires focus preservation and hold behavior on a runtime increment target. */\n incrementTargetConnected(button: HTMLButtonElement): void {\n this.#wireButton(button, 1);\n this.#repaint.schedule();\n }\n\n /** Releases only the increment target that actually disconnected. */\n incrementTargetDisconnected(button: HTMLButtonElement): void {\n this.#unwireButton(button);\n this.#repaint.schedule();\n }\n\n /** Wires focus preservation and hold behavior on a runtime decrement target. */\n decrementTargetConnected(button: HTMLButtonElement): void {\n this.#wireButton(button, -1);\n this.#repaint.schedule();\n }\n\n /** Releases only the decrement target that actually disconnected. */\n decrementTargetDisconnected(button: HTMLButtonElement): void {\n this.#unwireButton(button);\n this.#repaint.schedule();\n }\n\n /** Increases by one step. Bound via `data-action` (click). */\n increment(): void {\n if (this.#consumeSuppressedClick()) return;\n if (!this.hasInputTarget) return;\n this.#commitStep(1);\n this.inputTarget.focus();\n }\n\n /** Decreases by one step. Bound via `data-action` (click). */\n decrement(): void {\n if (this.#consumeSuppressedClick()) return;\n if (!this.hasInputTarget) return;\n this.#commitStep(-1);\n this.inputTarget.focus();\n }\n\n /** Clamps and snaps a typed value. Bound via `data-action` (change). */\n onInput(): void {\n if (!this.hasInputTarget) return;\n if (this.inputTarget.value.trim() === \"\") {\n this.#lastValue = null;\n this.#reflectEmpty();\n return;\n }\n this.#commit(this.#currentValue());\n }\n\n /** Keyboard stepping per the APG spinbutton model. */\n onKeydown(event: KeyboardEvent): void {\n if (!this.hasInputTarget) return;\n if (this.#composition.isComposing(event)) return;\n if (isReservedArrowChord(event)) return;\n let next: number | null = null;\n switch (event.key) {\n case \"ArrowUp\":\n next = stepSteppedValue(this.#currentValue(), 1, this.#steppedRange);\n break;\n case \"ArrowDown\":\n next = stepSteppedValue(this.#currentValue(), -1, this.#steppedRange);\n break;\n case \"PageUp\":\n next =\n this.pageStepValue > 0\n ? this.#currentValue() + this.pageStepValue\n : stepSteppedValue(this.#currentValue(), 10, this.#steppedRange);\n break;\n case \"PageDown\":\n next =\n this.pageStepValue > 0\n ? this.#currentValue() - this.pageStepValue\n : stepSteppedValue(this.#currentValue(), -10, this.#steppedRange);\n break;\n case \"Home\":\n if (!Number.isFinite(this.minValue)) return;\n next = this.minValue;\n break;\n case \"End\":\n if (!Number.isFinite(this.maxValue)) return;\n next = this.maxValue;\n break;\n default:\n return;\n }\n event.preventDefault();\n this.#commit(next);\n }\n\n /**\n * Wires a step button: `pointerdown` keeps focus on the input and arms the\n * hold; leaving the button while held stops it (the global listeners cover\n * release/cancel/blur).\n */\n #wireButton(button: HTMLButtonElement, direction: number): void {\n if (this.#buttonGuards.has(button)) return;\n const guard = new AbortController();\n this.#buttonGuards.set(button, guard);\n button.addEventListener(\"pointerdown\", (event) => this.#armHold(event, button, direction), {\n signal: guard.signal,\n });\n button.addEventListener(\n \"pointerleave\",\n (event) => {\n if (this.#holdButton === button && this.#ownsPointer(event)) this.#stopHold();\n },\n { signal: guard.signal },\n );\n }\n\n /** Aborts one target's listeners and returns any state derived onto that button. */\n #unwireButton(button: HTMLButtonElement): void {\n this.#buttonGuards.get(button)?.abort();\n this.#buttonGuards.delete(button);\n if (this.#holdButton === button) this.#stopHold(false);\n this.#releaseButtonState(button);\n }\n\n /** Starts a hold: focus the input, then schedule the first repeat after a delay. */\n #armHold(event: Event, button: HTMLButtonElement, direction: number): void {\n // Ignore secondary buttons (right/middle) when the event exposes one.\n const pointerButton = (event as PointerEvent).button;\n if (typeof pointerButton === \"number\" && pointerButton !== 0) return;\n if (button.disabled || !this.hasInputTarget) return;\n event.preventDefault(); // keep focus on the input rather than the button\n this.inputTarget.focus();\n\n this.#stopHold(false);\n this.#holdActive = true;\n this.#holdButton = button;\n this.#holdPointerId = this.#pointerId(event);\n this.#repeatedDuringHold = false;\n this.#suppressNextClick = false;\n this.#holdTimeouts.set(() => {\n if (!this.#commitStep(direction)) {\n this.#stopHold();\n return;\n }\n this.#repeatedDuringHold = true;\n this.#holdIntervals.set(() => {\n if (!this.#commitStep(direction)) this.#stopHold();\n }, NumberInputController.#HOLD_REPEAT_MS);\n }, NumberInputController.#HOLD_DELAY_MS);\n }\n\n /**\n * Stops the current hold (idempotent). When the hold actually repeated, the\n * trailing synthetic `click` must be ignored, so it is suppressed until the\n * click consumes it or a short safety-net timeout clears it.\n */\n #stopHold(suppressTrailingClick = true): void {\n if (!this.#holdActive) return;\n this.#holdActive = false;\n this.#holdButton = null;\n this.#holdPointerId = null;\n this.#holdTimeouts.clearAll();\n this.#holdIntervals.clearAll();\n if (suppressTrailingClick && this.#repeatedDuringHold) {\n this.#suppressNextClick = true;\n this.#holdTimeouts.set(() => {\n this.#suppressNextClick = false;\n }, NumberInputController.#SUPPRESS_RESET_MS);\n } else if (!suppressTrailingClick) {\n this.#suppressNextClick = false;\n }\n }\n\n /** Ends a hold only for its initiating pointer (legacy/synthetic events remain accepted). */\n readonly #onPointerEnd = (event: Event): void => {\n if (this.#ownsPointer(event)) this.#stopHold();\n };\n\n /** Window deactivation is global and always ends the active hold. */\n readonly #onWindowBlur = (): void => {\n this.#stopHold();\n };\n\n /** Extracts pointer identity when the runtime event exposes it. */\n #pointerId(event: Event): number | null {\n return (event as Partial<PointerEvent>).pointerId ?? null;\n }\n\n /** Whether `event` belongs to the active pointer, with a synthetic-event fallback. */\n #ownsPointer(event: Event): boolean {\n const pointerId = this.#pointerId(event);\n return (\n this.#holdActive &&\n (this.#holdPointerId === null || pointerId === null || pointerId === this.#holdPointerId)\n );\n }\n\n /** Consumes a pending trailing-click suppression; returns true if the click was swallowed. */\n #consumeSuppressedClick(): boolean {\n if (!this.#suppressNextClick) return false;\n this.#suppressNextClick = false;\n this.#holdTimeouts.clearAll();\n return true;\n }\n\n /**\n * Normalizes `raw`, reflects it, and dispatches `{ value: number }` only when\n * the committed numeric value differs from the last reconciled value.\n *\n * @returns Whether the value changed (drives the auto-repeat's bound stop).\n */\n #commit(raw: number): boolean {\n const value = this.#normalize(raw);\n const changed = this.#lastValue === null || value !== this.#lastValue;\n this.#write(value);\n this.#lastValue = value;\n if (changed) this.dispatch(\"change\", { detail: { value } });\n return changed;\n }\n\n /** Commits an adjacent endpoint/grid value and reports whether it moved. */\n #commitStep(count: number): boolean {\n if (!this.hasInputTarget) return false;\n return this.#commit(stepSteppedValue(this.#currentValue(), count, this.#steppedRange));\n }\n\n /**\n * Reflects the current value after a range or step morph, reporting a moved\n * value as `reconcile`.\n *\n * @stimeoRenderRoot\n */\n #reconcile(): void {\n if (!this.hasInputTarget) {\n this.#lastValue = null;\n return;\n }\n if (this.inputTarget.value.trim() !== \"\") {\n const previous = this.#lastValue;\n const value = this.#normalize(this.#currentValue());\n this.#write(value);\n this.#lastValue = value;\n // A range or step the consumer moved at runtime can pull the committed\n // number with it. That is this controller's decision, so it is reported\n // apart from `change`, which stays reserved for user edits.\n if (previous !== null && value !== previous) {\n this.dispatch(\"reconcile\", { detail: { value } });\n }\n } else {\n this.#lastValue = null;\n this.#reflectEmpty();\n }\n }\n\n /** Reflects `value` on the input (and ARIA for non-native hosts) and the buttons. */\n #write(value: number): void {\n const input = this.inputTarget;\n input.value = String(value);\n this.#syncInputAria(input, value);\n this.#updateButtons(value);\n }\n\n /** Reflects a blank value without inventing a numeric `aria-valuenow`. */\n #reflectEmpty(): void {\n this.#syncInputAria(this.inputTarget, null);\n this.#updateButtons(this.#currentValue());\n }\n\n /** Synchronizes controller-derived ARIA while preserving authored teardown values. */\n #syncInputAria(input: HTMLInputElement, value: number | null): void {\n if (input.getAttribute(\"role\") !== \"spinbutton\") {\n this.#releaseInputAria(input);\n return;\n }\n this.#ariaValueNow.write(input, value === null ? null : String(value));\n this.#ariaValueMin.write(input, Number.isFinite(this.minValue) ? String(this.minValue) : null);\n this.#ariaValueMax.write(input, Number.isFinite(this.maxValue) ? String(this.maxValue) : null);\n }\n\n /** Returns all custom-spinbutton ARIA leased on `input`. */\n #releaseInputAria(input: HTMLInputElement): void {\n this.#ariaValueNow.return(input);\n this.#ariaValueMin.return(input);\n this.#ariaValueMax.return(input);\n }\n\n /** Disables a step button at its bound, returning focus to the input first. */\n #updateButtons(value: number): void {\n for (const button of this.incrementTargets) this.#toggleButton(button, value < this.maxValue);\n for (const button of this.decrementTargets) this.#toggleButton(button, value > this.minValue);\n }\n\n /**\n * Enables or disables a step button at its bound, never disabling one while it\n * holds focus. Owns only the `disabled` it sets itself via a marker\n * (`data-number-input-disabled`, like `conditional-fields`/`submit-once`), so an\n * author-disabled button (e.g. the whole control disabled) is never re-enabled.\n */\n #toggleButton(button: HTMLButtonElement, enabled: boolean): void {\n if (enabled) {\n if (button.hasAttribute(OWNED_DISABLED)) {\n button.disabled = false;\n button.removeAttribute(OWNED_DISABLED);\n }\n return;\n }\n if (button.disabled) return; // already disabled (possibly by the author) — leave it\n if (document.activeElement === button && this.hasInputTarget) this.inputTarget.focus();\n button.disabled = true;\n button.setAttribute(OWNED_DISABLED, \"\");\n }\n\n /** Returns `disabled` only when its explicit marker still identifies controller ownership. */\n #releaseButtonState(button: HTMLButtonElement): void {\n if (!button.hasAttribute(OWNED_DISABLED)) return;\n button.disabled = false;\n button.removeAttribute(OWNED_DISABLED);\n }\n\n /** The current numeric value, falling back to a finite min (else 0) when blank. */\n #currentValue(): number {\n const parsed = Number(this.inputTarget.value);\n if (Number.isFinite(parsed) && this.inputTarget.value.trim() !== \"\") return parsed;\n return Number.isFinite(this.minValue) ? this.minValue : 0;\n }\n\n /** Clamps to `[min, max]` and snaps to the step grid anchored at a finite min (else 0). */\n #normalize(raw: number): number {\n return snapSteppedValue(raw, this.#steppedRange);\n }\n\n /** Shared range configuration; finite endpoints remain allowed off the grid. */\n get #steppedRange() {\n return { min: this.minValue, max: this.maxValue, step: this.stepValue };\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/arrow_step.ts","../../src/utils/attribute_lease.ts","../../src/utils/before_cache_reset.ts","../../src/utils/composition_tracker.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/safe_timeout.ts","../../src/utils/stepped_value.ts","../../src/controllers/number_input_controller.ts"],"names":["position"],"mappings":"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","file":"number_input_controller.js","sourcesContent":["import { isRtl } from \"./logical_scroll\";\n\n/**\n * Turns an arrow key into a **logical** step: `+1` for \"next\", `-1` for\n * \"previous\", `0` when the key names neither.\n *\n * APG defines the horizontal pair as *next / previous* and says a vertical\n * arrangement swaps in Down/Up for the same meaning — so the pair is one axis's\n * spelling of an order, and the order reverses with the writing direction. Only\n * the horizontal pair reverses. Down/Up name an axis the writing direction does\n * not mirror, and returning them unchanged is the point: many controllers fold\n * both pairs into one branch, where swapping the branches under RTL would flip\n * the vertical axis too — a bug that reads as \"the arrows work\" until someone\n * presses Down.\n *\n * **Direction is read from the element the caller passes, which should be the\n * container that lays the items out** — not the focused child. A child may carry\n * its own `dir` (an LTR input inside an RTL form is ordinary authoring), and\n * probing per handler makes two handlers disagree at the boundary between them.\n *\n * This decides direction only. Whether the axis is even active (an\n * `orientation=\"horizontal\"` widget ignoring Down/Up), how far the step lands,\n * and what wrapping does all stay with the caller.\n *\n * **It encodes the list-order convention: `ArrowDown` is *next*.** Widgets that\n * pair the arrows by *value* instead — `ArrowUp` meaning \"more\", as a rating or a\n * slider does — must not use this, or their vertical axis inverts. Reverse the\n * horizontal pair on its own there.\n *\n * @example\n * ```ts\n * const step = logicalArrowStep(event.key, this.element);\n * if (step === 0) return;\n * this.#roving.setActive(rovingMove(current, length, step, \"wrap\"), { focus: true });\n * ```\n */\nexport function logicalArrowStep(key: string, element: Element): 1 | -1 | 0 {\n if (key === \"ArrowDown\") return 1;\n if (key === \"ArrowUp\") return -1;\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return 0;\n const forward = isRtl(element) ? \"ArrowLeft\" : \"ArrowRight\";\n return key === forward ? 1 : -1;\n}\n\n/**\n * Rewrites `key` so an existing LTR-shaped branch keeps working under RTL:\n * `ArrowRight` and `ArrowLeft` trade places, everything else passes through.\n *\n * The alternative — negating a delta — silently breaks handlers whose two\n * horizontal branches are **not mirror images**. A grid that clamps one edge but\n * not the other, or a segmented field guarding `index > 0` on one side and\n * `index < length - 1` on the other, ends up applying the wrong guard to the\n * wrong direction. Swapping the key leaves each branch, guards and all, exactly\n * where its author put it.\n *\n * Same rule as {@link logicalArrowStep} about which element to read: pass the\n * container that lays the items out, not the focused child.\n *\n * @example\n * ```ts\n * switch (logicalArrowKey(event.key, this.element)) {\n * case \"ArrowLeft\": // \"previous\" — whatever direction that is on screen\n * ```\n */\nexport function logicalArrowKey(key: string, element: Element): string {\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return key;\n if (!isRtl(element)) return key;\n return key === \"ArrowRight\" ? \"ArrowLeft\" : \"ArrowRight\";\n}\n\n/** Modifiers a widget may claim on an arrow key, named for the `allow` list. */\nexport type ArrowModifier = \"alt\" | \"ctrl\" | \"meta\" | \"shift\";\n\n/**\n * True when an arrow key arrived carrying a modifier the widget must leave to\n * the browser: return without calling `preventDefault()` and without moving any\n * state.\n *\n * A bare arrow belongs to the widget; a chorded one usually does not.\n * `Alt`/`Meta` plus a horizontal arrow is history back/forward on every desktop\n * browser, and a widget that swallows it makes the shortcut work or not\n * depending on where focus happens to sit — a coin-flip the user cannot see.\n *\n * `allow` is for the combinations APG assigns to a pattern **and the widget\n * actually implements** — today only Combobox's optional `Alt+Down`/`Alt+Up`.\n * Listing one the widget does not implement defeats the point: the chord then\n * runs the plain-arrow branch, which is exactly what this guard exists to stop.\n * Non-arrow keys return `false`, so chorded letters and\n * `Control+Home`/`Control+End` are untouched.\n *\n * @example\n * ```ts\n * if (isReservedArrowChord(event)) return;\n * ```\n */\nexport function isReservedArrowChord(\n event: KeyboardEvent,\n allow: readonly ArrowModifier[] = [],\n): boolean {\n if (!event.key.startsWith(\"Arrow\")) return false;\n return (\n (event.altKey && !allow.includes(\"alt\")) ||\n (event.ctrlKey && !allow.includes(\"ctrl\")) ||\n (event.metaKey && !allow.includes(\"meta\")) ||\n (event.shiftKey && !allow.includes(\"shift\"))\n );\n}\n","/** One temporarily controlled attribute value and the authored value it displaced. */\ninterface AttributeLeaseRecord {\n readonly original: string | null;\n written: string | null;\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 * The lease has no lifecycle of its own, so it never subscribes to document events.\n * A consumer that must not let a derived value become the authored baseline of a\n * cached page returns its leases from its own `turbo:before-cache` rewind, where the\n * matching `disconnect()` also releases the subscription.\n */\nexport class AttributeLease<T extends Element = Element> {\n readonly #attribute: string;\n readonly #records = new Map<T, AttributeLeaseRecord>();\n\n /** @param attribute - The attribute whose temporary values this lease owns. */\n constructor(attribute: string) {\n this.#attribute = attribute;\n }\n\n /** Writes or removes the leased attribute while preserving its authored value. */\n write(element: T, value: string | null): void {\n const existing = this.#records.get(element);\n if (existing) {\n existing.written = value;\n } else {\n this.#records.set(element, {\n original: element.getAttribute(this.#attribute),\n written: value,\n });\n }\n\n this.#reflect(element, value);\n }\n\n /** Returns one lease without overwriting a value subsequently authored by a consumer. */\n return(element: T): void {\n const record = this.#records.get(element);\n if (!record) return;\n this.#records.delete(element);\n const stillOwned = element.getAttribute(this.#attribute) === record.written;\n if (stillOwned) this.#reflect(element, record.original);\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 /** Returns every outstanding lease using the same ownership check as {@link return}. */\n returnAll(): void {\n for (const element of Array.from(this.#records.keys())) this.return(element);\n }\n}\n","/**\n * Runs a controller's \"return to the initial state\" pass just before Turbo\n * caches the page.\n *\n * **`disconnect()` cannot do this job, for two independent reasons.** Turbo\n * queues the clone from this event rather than taking it here, and the body swap\n * that runs the controller's `disconnect()` is queued separately — so which of\n * the two lands first is not something a controller can rely on, and a rewind\n * written in `disconnect()` may reach only the DOM being thrown away. In the\n * other direction, `disconnect()` also fires on an in-page move (Stimulus tears\n * down and reconnects the same element), where rewinding would wipe a\n * legitimately in-progress interaction — a spinner mid-load would vanish. One\n * timing is unreliable, the other is too eager; `turbo:before-cache` is the only\n * point that is exactly \"the page is about to be frozen\".\n *\n * Scope is the subscription only: registering on `activate()`, unregistering on\n * `deactivate()`, and one shared document listener no matter how many instances\n * are live. *What* to return to its initial state — which `data-state`, which\n * `hidden`, which `aria-busy` — stays in the controller, because no two\n * consumers answer it the same way (the `MicrotaskCoalescer` split).\n *\n * **Rewind state, not appearance.** The pass writes attributes the controller\n * itself owns; the visual result of those attributes is the consumer's CSS, and\n * a library that reached for style or class names would be guessing at markup\n * it does not own.\n *\n * Both entry points are idempotent, so the lifecycle hooks can call them\n * unconditionally: a second `activate()` does not double-subscribe and does not\n * make the callback run twice, and `deactivate()` on an instance that never\n * subscribed is a no-op.\n *\n * This file's own doc block is dropped from `dist`, but every member comment is\n * inlined into each consumer entry (`tsup` builds with `splitting: false`), so\n * rationale belongs here and only the contract belongs on the members.\n *\n * @example\n * ```ts\n * readonly #beforeCache = new BeforeCacheReset(() => this.#rewind());\n *\n * connect() { this.#beforeCache.activate(); }\n * disconnect() { this.#beforeCache.deactivate(); }\n * ```\n */\nexport class BeforeCacheReset {\n /** Every subscribed instance, iterated by the one shared document listener. */\n static readonly #subscribers = new Set<BeforeCacheReset>();\n\n /** The shared listener; installed while at least one instance is subscribed. */\n static readonly #onBeforeCache = (): void => {\n for (const subscriber of BeforeCacheReset.#subscribers) subscriber.#rewind();\n };\n\n readonly #rewind: () => void;\n\n /** @param rewind - the pass that returns this controller's state to its initial form. */\n constructor(rewind: () => void) {\n this.#rewind = rewind;\n }\n\n /** Subscribes to `turbo:before-cache`; call from `connect()`. Idempotent. */\n activate(): void {\n const first = BeforeCacheReset.#subscribers.size === 0;\n BeforeCacheReset.#subscribers.add(this);\n if (first) {\n document.addEventListener(\"turbo:before-cache\", BeforeCacheReset.#onBeforeCache);\n }\n }\n\n /** Unsubscribes; call from `disconnect()`. Safe when never subscribed. */\n deactivate(): void {\n BeforeCacheReset.#subscribers.delete(this);\n if (BeforeCacheReset.#subscribers.size > 0) return;\n document.removeEventListener(\"turbo:before-cache\", BeforeCacheReset.#onBeforeCache);\n }\n}\n","/** Minimal event shape carrying the platform's per-event composition signal. */\nexport interface CompositionSignal {\n readonly isComposing?: boolean;\n}\n\n/** Hooks that keep component-specific work outside {@link CompositionTracker}. */\nexport interface CompositionTrackerOptions {\n /** Runs after lifecycle state is set for a `compositionstart` event. */\n readonly onStart?: (event: Event) => void;\n /** Runs after lifecycle state is cleared for a `compositionend` event. */\n readonly onEnd?: (event: Event) => void;\n}\n\n/**\n * Owns IME composition listeners and transient state for one or more event targets.\n *\n * Some browsers omit `KeyboardEvent.isComposing` on the keydown that confirms a\n * conversion. Tracking `compositionstart` through `compositionend` supplies the\n * missing lifecycle signal without relying on deprecated numeric key codes.\n * Component policy stays with the consumer: filtering, validation, and submission\n * belong in the optional {@link CompositionTrackerOptions.onEnd} callback.\n *\n * @example\n * ```ts\n * #composition = new CompositionTracker({ onEnd: () => this.filter() });\n *\n * connect(): void {\n * this.#composition.observe(this.inputTarget);\n * }\n *\n * disconnect(): void {\n * this.#composition.disconnect();\n * }\n *\n * onKeydown(event: KeyboardEvent): void {\n * if (this.#composition.isComposing(event)) return;\n * }\n * ```\n */\nexport class CompositionTracker {\n readonly #observedTargets = new Set<EventTarget>();\n readonly #activeTargets = new Set<EventTarget>();\n readonly #onStart: ((event: Event) => void) | undefined;\n readonly #onEnd: ((event: Event) => void) | undefined;\n\n constructor(options: CompositionTrackerOptions = {}) {\n this.#onStart = options.onStart;\n this.#onEnd = options.onEnd;\n }\n\n /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */\n observe(target: EventTarget): void {\n if (this.#observedTargets.has(target)) return;\n target.addEventListener(\"compositionstart\", this.#handleStart);\n target.addEventListener(\"compositionend\", this.#handleEnd);\n this.#observedTargets.add(target);\n }\n\n /** Stops tracking one target and clears any active composition it owned. */\n unobserve(target: EventTarget): void {\n if (!this.#observedTargets.delete(target)) return;\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n this.#activeTargets.delete(target);\n }\n\n /** Releases every listener and clears state so reconnect starts cleanly. */\n disconnect(): void {\n for (const target of this.#observedTargets) {\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n }\n this.#observedTargets.clear();\n this.#activeTargets.clear();\n }\n\n /** True when lifecycle tracking or the current event reports composition. */\n isComposing(event?: CompositionSignal): boolean {\n return this.#activeTargets.size > 0 || event?.isComposing === true;\n }\n\n readonly #handleStart = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.add(event.currentTarget);\n this.#onStart?.(event);\n };\n\n readonly #handleEnd = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);\n this.#onEnd?.(event);\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 * This file's own doc block is dropped from `dist`, but every member comment is\n * inlined into each consumer entry (`tsup` builds with `splitting: false`), so\n * rationale belongs here and only the contract belongs on the members.\n *\n * @example\n * ```ts\n * readonly #reconcile = new MicrotaskCoalescer(() => this.#reconcileOptions());\n *\n * connect() { this.#reconcile.activate(); }\n * disconnect() { this.#reconcile.cancel(); }\n *\n * optionTargetConnected() { this.#reconcile.schedule(); }\n * optionTargetDisconnected() { this.#reconcile.schedule(); }\n * ```\n */\nexport class MicrotaskCoalescer {\n readonly #run: () => void;\n #queued = false;\n #active = false;\n #generation = 0;\n\n /** @param run - the single reconciliation pass, invoked at most once per batch. */\n constructor(run: () => void) {\n this.#run = run;\n }\n\n /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */\n activate(): void {\n this.#active = true;\n }\n\n /** Closes the window and drops any pending pass; call from `disconnect()`. */\n cancel(): void {\n this.#active = false;\n this.#queued = false;\n this.#generation += 1;\n }\n\n /** Requests one pass after the batch settles. Idempotent; inert outside the window. */\n schedule(): void {\n if (!this.#active || this.#queued) return;\n this.#queued = true;\n const generation = this.#generation;\n queueMicrotask(() => {\n // A cancelled callback must not consume a pass queued after reconnect.\n if (generation !== this.#generation || !this.#queued || !this.#active) return;\n this.#queued = false;\n this.#run();\n });\n }\n}\n","/**\n * 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\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","/** Configuration for a value constrained to a stepped numeric range. */\nexport interface SteppedRange {\n /** Inclusive lower endpoint. May be infinite for an unbounded control. */\n readonly min: number;\n /** Inclusive upper endpoint. May be infinite for an unbounded control. */\n readonly max: number;\n /** Requested step. Non-finite and non-positive values fall back to `1`. */\n readonly step: number;\n /** Step-grid origin. Defaults to a finite `min`, otherwise `0`. */\n readonly base?: number;\n}\n\n/** The positive finite step used at runtime and by keyboard stepping. */\nexport function effectiveStep(step: number): number {\n return Number.isFinite(step) && step > 0 ? step : 1;\n}\n\n/**\n * Clamps a raw value and selects its nearest allowed value.\n *\n * The allowed set is the step grid plus each finite range endpoint. Keeping the\n * endpoints in that set makes an authored `aria-valuemin`/`aria-valuemax`\n * truthful even when the upper endpoint is not aligned to the grid. A value\n * exactly between two allowed values resolves upward.\n */\nexport function snapSteppedValue(raw: number, range: SteppedRange): number {\n if (!(range.min <= range.max)) return finiteFallback(range.min, range.max);\n\n const input = Number.isNaN(raw) ? finiteFallback(range.min, range.max) : raw;\n const clamped = Math.min(range.max, Math.max(range.min, input));\n const step = effectiveStep(range.step);\n const base = stepBase(range);\n const candidates: number[] = [];\n\n if (Number.isFinite(range.min)) candidates.push(range.min);\n if (Number.isFinite(range.max)) candidates.push(range.max);\n\n const gridPosition = (clamped - base) / step;\n if (Number.isFinite(gridPosition)) {\n addGridCandidate(candidates, Math.floor(gridPosition), range, base, step);\n addGridCandidate(candidates, Math.ceil(gridPosition), range, base, step);\n }\n\n if (candidates.length === 0) return clamped;\n let nearest = candidates[0] as number;\n let nearestDistance = Math.abs(clamped - nearest);\n for (const candidate of candidates.slice(1)) {\n const distance = Math.abs(clamped - candidate);\n if (\n distance < nearestDistance ||\n (nearlyEqual(distance, nearestDistance) && candidate > nearest)\n ) {\n nearest = candidate;\n nearestDistance = distance;\n }\n }\n return nearest;\n}\n\n/**\n * Moves through the ordered allowed-value set by an integer number of steps.\n *\n * This differs from adding `step * count` and snapping afterward at an\n * off-grid endpoint: with `max=94, step=10`, one decrement from `94` must land\n * on `90`, and one increment from `90` must reach the advertised maximum `94`.\n */\nexport function stepSteppedValue(current: number, count: number, range: SteppedRange): number {\n const value = snapSteppedValue(current, range);\n const distance = Math.abs(Math.trunc(count));\n if (!Number.isFinite(distance) || distance === 0) return value;\n const direction = Math.sign(count);\n const adjacent = adjacentSteppedValue(value, direction, range);\n\n // The first move accounts for a possibly off-grid endpoint. From there a\n // direct grid jump is equivalent to repeated adjacency, and avoids work that\n // grows with Page-step magnitudes or programmatic counts.\n const raw = adjacent + direction * (distance - 1) * effectiveStep(range.step);\n return snapSteppedValue(raw, range);\n}\n\n/** Returns the next member of the ordered endpoint-plus-grid set. */\nfunction adjacentSteppedValue(current: number, direction: number, range: SteppedRange): number {\n const step = effectiveStep(range.step);\n const base = stepBase(range);\n const candidates: number[] = [];\n\n if (direction > 0) {\n const position = (current - base) / step;\n if (Number.isFinite(position)) {\n let gridIndex = Math.floor(position) + 1;\n let candidate = cleanGridValue(base + gridIndex * step, base, step);\n if (candidate < current || nearlyEqual(candidate, current)) {\n gridIndex += 1;\n candidate = cleanGridValue(base + gridIndex * step, base, step);\n }\n if (\n candidate > current &&\n !nearlyEqual(candidate, current) &&\n within(candidate, range.min, range.max)\n ) {\n candidates.push(clamp(candidate, range));\n }\n }\n return clamp(Math.min(...candidates), range);\n }\n\n const position = (current - base) / step;\n if (Number.isFinite(position)) {\n let gridIndex = Math.ceil(position) - 1;\n let candidate = cleanGridValue(base + gridIndex * step, base, step);\n if (candidate > current || nearlyEqual(candidate, current)) {\n gridIndex -= 1;\n candidate = cleanGridValue(base + gridIndex * step, base, step);\n }\n if (\n candidate < current &&\n !nearlyEqual(candidate, current) &&\n within(candidate, range.min, range.max)\n ) {\n candidates.push(clamp(candidate, range));\n }\n }\n return clamp(Math.max(...candidates), range);\n}\n\n/** Adds one grid value when it falls inside the inclusive range. */\nfunction addGridCandidate(\n candidates: number[],\n index: number,\n range: SteppedRange,\n base: number,\n step: number,\n): void {\n const candidate = cleanGridValue(base + index * step, base, step);\n if (within(candidate, range.min, range.max)) candidates.push(clamp(candidate, range));\n}\n\n/** A finite authored base wins; otherwise the finite lower bound or zero does. */\nfunction stepBase(range: SteppedRange): number {\n if (range.base !== undefined && Number.isFinite(range.base)) return range.base;\n return Number.isFinite(range.min) ? range.min : 0;\n}\n\n/** Removes binary noise without discarding significant integer-place digits. */\nfunction cleanGridValue(value: number, base: number, step: number): number {\n const precision = Math.max(decimalPlaces(base), decimalPlaces(step));\n // `toFixed` accepts at most 100 fractional digits. Below that limit it rounds\n // according to the authored grid precision rather than an arbitrary total\n // significant-digit count, which keeps unit steps distinct at large bases.\n return precision <= 100 ? Number(value.toFixed(precision)) : value;\n}\n\n/** Number of fractional decimal places represented by a finite JS number. */\nfunction decimalPlaces(value: number): number {\n const [coefficient = \"\", exponentText] = Math.abs(value).toString().toLowerCase().split(\"e\");\n const fractionLength = coefficient.split(\".\")[1]?.length ?? 0;\n const exponent = exponentText === undefined ? 0 : Number(exponentText);\n return Math.max(0, fractionLength - exponent);\n}\n\n/** Inclusive range check tolerant only of arithmetic noise at an endpoint. */\nfunction within(value: number, min: number, max: number): boolean {\n return (value > min || nearlyEqual(value, min)) && (value < max || nearlyEqual(value, max));\n}\n\n/** Clamps a candidate whose only overshoot may be floating-point noise. */\nfunction clamp(value: number, range: SteppedRange): number {\n return Math.min(range.max, Math.max(range.min, value));\n}\n\n/** Relative comparison used only to collapse arithmetic noise, not real steps. */\nfunction nearlyEqual(left: number, right: number): boolean {\n const scale = Math.max(Math.abs(left), Math.abs(right));\n return (\n Number.isFinite(left) &&\n Number.isFinite(right) &&\n Math.abs(left - right) <= Number.EPSILON * scale\n );\n}\n\n/** Stable fallback for malformed ranges or `NaN` input. */\nfunction finiteFallback(min: number, max: number): number {\n if (Number.isFinite(min)) return min;\n if (Number.isFinite(max)) return max;\n return 0;\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { isReservedArrowChord } from \"../utils/arrow_step\";\nimport { AttributeLease } from \"../utils/attribute_lease\";\nimport { BeforeCacheReset } from \"../utils/before_cache_reset\";\nimport { CompositionTracker } from \"../utils/composition_tracker\";\nimport { MicrotaskCoalescer } from \"../utils/microtask_coalescer\";\nimport { SafeInterval, SafeTimeout } from \"../utils/safe_timeout\";\nimport { snapSteppedValue, stepSteppedValue } from \"../utils/stepped_value\";\n\n/** Marks a `disabled` state derived and therefore removable by this controller. */\nconst OWNED_DISABLED = \"data-number-input-disabled\";\n\n/**\n * Headless, accessible number / spin-button behavior.\n *\n * Markup contract (identifier: `stimeo--number-input`):\n * <div data-controller=\"stimeo--number-input\"\n * data-stimeo--number-input-min-value=\"0\"\n * data-stimeo--number-input-max-value=\"100\"\n * data-stimeo--number-input-step-value=\"1\">\n * <button type=\"button\" aria-label=\"Decrease\" tabindex=\"-1\"\n * data-stimeo--number-input-target=\"decrement\"\n * data-action=\"click->stimeo--number-input#decrement\">−</button>\n * <input type=\"number\" min=\"0\" max=\"100\" step=\"1\" value=\"0\"\n * data-stimeo--number-input-target=\"input\"\n * data-action=\"change->stimeo--number-input#onInput\n * keydown->stimeo--number-input#onKeydown\" />\n * <button type=\"button\" aria-label=\"Increase\" tabindex=\"-1\"\n * data-stimeo--number-input-target=\"increment\"\n * data-action=\"click->stimeo--number-input#increment\">+</button>\n * </div>\n *\n * Implements the WAI-ARIA APG **Spinbutton** pattern. The arrow/step logic is\n * fully owned by the controller (not delegated to the browser's native number\n * stepping) so the behavior is identical for a native `<input type=\"number\">` and\n * a custom `role=\"spinbutton\"` host.\n *\n * `reconcile` dispatches `{ value: number }`.\n *\n * @remarks\n * Behavior only — the consumer styles the field and buttons. The input is the\n * sole Tab stop; the buttons are `tabindex=\"-1\"` and keep focus on the input\n * (pointerdown is suppressed), so stepping never moves focus away.\n *\n * Behavior provided:\n * - `ArrowUp`/`ArrowDown` step by `step`; `PageUp`/`PageDown` by `pageStep`\n * (default `step × 10`); `Home`/`End` jump to a finite `min`/`max`.\n * - Increment/decrement buttons step too, and are `disabled` at the bounds (focus\n * is returned to the input before a focused button is disabled).\n * - **Press-and-hold auto-repeat**: holding a step button steps once, then after a\n * short delay repeats until release, the bound is reached, or the element\n * disconnects. The `click` binding stays the single-step path (a quick click, a\n * synthesized/programmatic click, or assistive activation), so a normal click\n * never double-steps — the trailing click after a hold is swallowed.\n * - Typed input is clamped and snapped to the step grid on `change`;\n * `stimeo--number-input:change` is dispatched once for each changed committed\n * numeric value with `{ value: number }` detail. When a runtime `min`/`max`/\n * `step` change pulls the committed value with it, that same detail arrives as\n * `stimeo--number-input:reconcile` instead, so a consumer can tell its own edit\n * from the controller's repair. Neither event fires on connect.\n * - `step` must be finite and positive; invalid runtime input falls back to `1`,\n * while finite range endpoints remain reachable off the grid.\n */\nexport class NumberInputController extends Controller<HTMLElement> {\n static override targets = [\"input\", \"increment\", \"decrement\"];\n static override values = {\n min: { type: Number, default: Number.NEGATIVE_INFINITY },\n max: { type: Number, default: Number.POSITIVE_INFINITY },\n step: { type: Number, default: 1 },\n pageStep: { type: Number, default: 0 },\n };\n static actions = [\"decrement\", \"increment\", \"onInput\", \"onKeydown\"] as const;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly inputTarget: HTMLInputElement;\n declare readonly hasInputTarget: boolean;\n declare readonly incrementTarget: HTMLButtonElement;\n declare readonly incrementTargets: HTMLButtonElement[];\n declare readonly hasIncrementTarget: boolean;\n declare readonly decrementTarget: HTMLButtonElement;\n declare readonly decrementTargets: HTMLButtonElement[];\n declare readonly hasDecrementTarget: boolean;\n declare minValue: number;\n declare maxValue: number;\n declare stepValue: number;\n declare pageStepValue: number;\n\n /** Delay (ms) a button must be held before auto-repeat starts. */\n static readonly #HOLD_DELAY_MS = 400;\n /** Interval (ms) between auto-repeat steps once a hold has started. */\n static readonly #HOLD_REPEAT_MS = 80;\n /**\n * Window (ms) after a hold ends during which the trailing synthetic `click` is\n * swallowed. A safety net for the (rare) case where that click never arrives\n * (e.g. the pointer was released off the button): the flag self-clears instead\n * of poisoning the next legitimate click.\n */\n static readonly #SUPPRESS_RESET_MS = 250;\n\n /** Aborts global pointer guards on disconnect so none outlive the element. */\n #globalGuards: AbortController | null = null;\n /** Per-target guards allow an old button to be released without touching its replacement. */\n readonly #buttonGuards = new Map<HTMLButtonElement, AbortController>();\n /** Tracks IME lifecycle on the current input, including confirming keys without a signal. */\n readonly #composition = new CompositionTracker();\n /** Restores authored custom-spinbutton ARIA when a target leaves or the controller stops. */\n readonly #beforeCache = new BeforeCacheReset(() => this.#rewindForCache());\n readonly #ariaValueNow = new AttributeLease<HTMLInputElement>(\"aria-valuenow\");\n readonly #ariaValueMin = new AttributeLease<HTMLInputElement>(\"aria-valuemin\");\n readonly #ariaValueMax = new AttributeLease<HTMLInputElement>(\"aria-valuemax\");\n /** Last reconciled or user-committed numeric value. */\n #lastValue: number | null = null;\n /** Timers for the hold delay and the suppress-reset safety net. */\n readonly #holdTimeouts = new SafeTimeout();\n /** The running auto-repeat interval (one at a time). */\n readonly #holdIntervals = new SafeInterval();\n /** True while a hold is armed/running, making `#stopHold` idempotent. */\n #holdActive = false;\n /** True once a hold actually produced a repeated step (vs. a quick click). */\n #repeatedDuringHold = false;\n /** True when the next `click` is the trailing one after a hold and must be ignored. */\n #suppressNextClick = false;\n /** Button and pointer that own the current hold, so other instances/pointers cannot end it. */\n #holdButton: HTMLButtonElement | null = null;\n #holdPointerId: number | null = null;\n /** Collapses runtime range/step changes into one input reconciliation. */\n readonly #repaint = new MicrotaskCoalescer(() => this.#reconcile());\n\n /** Normalizes any initial value and wires the focus/hold pointer guards. */\n override connect(): void {\n this.#repaint.activate();\n this.#beforeCache.activate();\n this.#globalGuards = new AbortController();\n const { signal } = this.#globalGuards;\n for (const button of this.incrementTargets) this.#wireButton(button, 1);\n for (const button of this.decrementTargets) this.#wireButton(button, -1);\n // A pointer released or focus lost anywhere stops a running hold, even when\n // the button stopped receiving its own pointerup (e.g. it became disabled at\n // the bound, or the pointer was released off it).\n window.addEventListener(\"pointerup\", this.#onPointerEnd, { signal });\n window.addEventListener(\"pointercancel\", this.#onPointerEnd, { signal });\n window.addEventListener(\"blur\", this.#onWindowBlur, { signal });\n this.#reconcile();\n }\n\n /** Releases listeners, derived attributes, timers, and transient value state. */\n override disconnect(): void {\n this.#repaint.cancel();\n this.#composition.disconnect();\n this.#beforeCache.deactivate();\n this.#globalGuards?.abort();\n this.#globalGuards = null;\n const buttons = new Set([\n ...this.#buttonGuards.keys(),\n ...this.incrementTargets,\n ...this.decrementTargets,\n ]);\n for (const guard of this.#buttonGuards.values()) guard.abort();\n this.#buttonGuards.clear();\n for (const button of buttons) this.#releaseButtonState(button);\n this.#stopHold(false);\n this.#repeatedDuringHold = false;\n this.#suppressNextClick = false;\n this.#holdTimeouts.clearAll();\n this.#holdIntervals.clearAll();\n this.#ariaValueNow.returnAll();\n this.#ariaValueMin.returnAll();\n this.#ariaValueMax.returnAll();\n this.#lastValue = null;\n }\n\n /** Reconciles the value against a minimum changed by application code or a Turbo morph. */\n minValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Reconciles the value against a maximum changed by application code or a Turbo morph. */\n maxValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Reconciles the value against a step changed by application code or a Turbo morph. */\n stepValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Tracks and reconciles an input inserted or replaced at runtime. */\n inputTargetConnected(input: HTMLInputElement): void {\n this.#composition.observe(input);\n this.#repaint.schedule();\n }\n\n /** Releases ARIA and composition state owned by an input that left the controller. */\n inputTargetDisconnected(input: HTMLInputElement): void {\n this.#composition.unobserve(input);\n this.#releaseInputAria(input);\n this.#stopHold(false);\n this.#lastValue = null;\n this.#repaint.schedule();\n }\n\n /** Wires focus preservation and hold behavior on a runtime increment target. */\n incrementTargetConnected(button: HTMLButtonElement): void {\n this.#wireButton(button, 1);\n this.#repaint.schedule();\n }\n\n /** Releases only the increment target that actually disconnected. */\n incrementTargetDisconnected(button: HTMLButtonElement): void {\n this.#unwireButton(button);\n this.#repaint.schedule();\n }\n\n /** Wires focus preservation and hold behavior on a runtime decrement target. */\n decrementTargetConnected(button: HTMLButtonElement): void {\n this.#wireButton(button, -1);\n this.#repaint.schedule();\n }\n\n /** Releases only the decrement target that actually disconnected. */\n decrementTargetDisconnected(button: HTMLButtonElement): void {\n this.#unwireButton(button);\n this.#repaint.schedule();\n }\n\n /** Increases by one step. Bound via `data-action` (click). */\n increment(): void {\n if (this.#consumeSuppressedClick()) return;\n if (!this.hasInputTarget) return;\n this.#commitStep(1);\n this.inputTarget.focus();\n }\n\n /** Decreases by one step. Bound via `data-action` (click). */\n decrement(): void {\n if (this.#consumeSuppressedClick()) return;\n if (!this.hasInputTarget) return;\n this.#commitStep(-1);\n this.inputTarget.focus();\n }\n\n /** Clamps and snaps a typed value. Bound via `data-action` (change). */\n onInput(): void {\n if (!this.hasInputTarget) return;\n if (this.inputTarget.value.trim() === \"\") {\n this.#lastValue = null;\n this.#reflectEmpty();\n return;\n }\n this.#commit(this.#currentValue());\n }\n\n /** Keyboard stepping per the APG spinbutton model. */\n onKeydown(event: KeyboardEvent): void {\n if (!this.hasInputTarget) return;\n if (this.#composition.isComposing(event)) return;\n if (isReservedArrowChord(event)) return;\n let next: number | null = null;\n switch (event.key) {\n case \"ArrowUp\":\n next = stepSteppedValue(this.#currentValue(), 1, this.#steppedRange);\n break;\n case \"ArrowDown\":\n next = stepSteppedValue(this.#currentValue(), -1, this.#steppedRange);\n break;\n case \"PageUp\":\n next =\n this.pageStepValue > 0\n ? this.#currentValue() + this.pageStepValue\n : stepSteppedValue(this.#currentValue(), 10, this.#steppedRange);\n break;\n case \"PageDown\":\n next =\n this.pageStepValue > 0\n ? this.#currentValue() - this.pageStepValue\n : stepSteppedValue(this.#currentValue(), -10, this.#steppedRange);\n break;\n case \"Home\":\n if (!Number.isFinite(this.minValue)) return;\n next = this.minValue;\n break;\n case \"End\":\n if (!Number.isFinite(this.maxValue)) return;\n next = this.maxValue;\n break;\n default:\n return;\n }\n event.preventDefault();\n this.#commit(next);\n }\n\n /**\n * Wires a step button: `pointerdown` keeps focus on the input and arms the\n * hold; leaving the button while held stops it (the global listeners cover\n * release/cancel/blur).\n */\n #wireButton(button: HTMLButtonElement, direction: number): void {\n if (this.#buttonGuards.has(button)) return;\n const guard = new AbortController();\n this.#buttonGuards.set(button, guard);\n button.addEventListener(\"pointerdown\", (event) => this.#armHold(event, button, direction), {\n signal: guard.signal,\n });\n button.addEventListener(\n \"pointerleave\",\n (event) => {\n if (this.#holdButton === button && this.#ownsPointer(event)) this.#stopHold();\n },\n { signal: guard.signal },\n );\n }\n\n /** Aborts one target's listeners and returns any state derived onto that button. */\n #unwireButton(button: HTMLButtonElement): void {\n this.#buttonGuards.get(button)?.abort();\n this.#buttonGuards.delete(button);\n if (this.#holdButton === button) this.#stopHold(false);\n this.#releaseButtonState(button);\n }\n\n /** Starts a hold: focus the input, then schedule the first repeat after a delay. */\n #armHold(event: Event, button: HTMLButtonElement, direction: number): void {\n // Ignore secondary buttons (right/middle) when the event exposes one.\n const pointerButton = (event as PointerEvent).button;\n if (typeof pointerButton === \"number\" && pointerButton !== 0) return;\n if (button.disabled || !this.hasInputTarget) return;\n event.preventDefault(); // keep focus on the input rather than the button\n this.inputTarget.focus();\n\n this.#stopHold(false);\n this.#holdActive = true;\n this.#holdButton = button;\n this.#holdPointerId = this.#pointerId(event);\n this.#repeatedDuringHold = false;\n this.#suppressNextClick = false;\n this.#holdTimeouts.set(() => {\n if (!this.#commitStep(direction)) {\n this.#stopHold();\n return;\n }\n this.#repeatedDuringHold = true;\n this.#holdIntervals.set(() => {\n if (!this.#commitStep(direction)) this.#stopHold();\n }, NumberInputController.#HOLD_REPEAT_MS);\n }, NumberInputController.#HOLD_DELAY_MS);\n }\n\n /**\n * Stops the current hold (idempotent). When the hold actually repeated, the\n * trailing synthetic `click` must be ignored, so it is suppressed until the\n * click consumes it or a short safety-net timeout clears it.\n */\n #stopHold(suppressTrailingClick = true): void {\n if (!this.#holdActive) return;\n this.#holdActive = false;\n this.#holdButton = null;\n this.#holdPointerId = null;\n this.#holdTimeouts.clearAll();\n this.#holdIntervals.clearAll();\n if (suppressTrailingClick && this.#repeatedDuringHold) {\n this.#suppressNextClick = true;\n this.#holdTimeouts.set(() => {\n this.#suppressNextClick = false;\n }, NumberInputController.#SUPPRESS_RESET_MS);\n } else if (!suppressTrailingClick) {\n this.#suppressNextClick = false;\n }\n }\n\n /** Ends a hold only for its initiating pointer (legacy/synthetic events remain accepted). */\n readonly #onPointerEnd = (event: Event): void => {\n if (this.#ownsPointer(event)) this.#stopHold();\n };\n\n /** Window deactivation is global and always ends the active hold. */\n readonly #onWindowBlur = (): void => {\n this.#stopHold();\n };\n\n /** Extracts pointer identity when the runtime event exposes it. */\n #pointerId(event: Event): number | null {\n return (event as Partial<PointerEvent>).pointerId ?? null;\n }\n\n /** Whether `event` belongs to the active pointer, with a synthetic-event fallback. */\n #ownsPointer(event: Event): boolean {\n const pointerId = this.#pointerId(event);\n return (\n this.#holdActive &&\n (this.#holdPointerId === null || pointerId === null || pointerId === this.#holdPointerId)\n );\n }\n\n /** Consumes a pending trailing-click suppression; returns true if the click was swallowed. */\n #consumeSuppressedClick(): boolean {\n if (!this.#suppressNextClick) return false;\n this.#suppressNextClick = false;\n this.#holdTimeouts.clearAll();\n return true;\n }\n\n /**\n * Normalizes `raw`, reflects it, and dispatches `{ value: number }` only when\n * the committed numeric value differs from the last reconciled value.\n *\n * @returns Whether the value changed (drives the auto-repeat's bound stop).\n */\n #commit(raw: number): boolean {\n const value = this.#normalize(raw);\n const changed = this.#lastValue === null || value !== this.#lastValue;\n this.#write(value);\n this.#lastValue = value;\n if (changed) this.dispatch(\"change\", { detail: { value } });\n return changed;\n }\n\n /** Commits an adjacent endpoint/grid value and reports whether it moved. */\n #commitStep(count: number): boolean {\n if (!this.hasInputTarget) return false;\n return this.#commit(stepSteppedValue(this.#currentValue(), count, this.#steppedRange));\n }\n\n /**\n * Reflects the current value after a range or step morph, reporting a moved\n * value as `reconcile`.\n *\n * @stimeoRenderRoot\n */\n #reconcile(): void {\n if (!this.hasInputTarget) {\n this.#lastValue = null;\n return;\n }\n if (this.inputTarget.value.trim() !== \"\") {\n const previous = this.#lastValue;\n const value = this.#normalize(this.#currentValue());\n this.#write(value);\n this.#lastValue = value;\n // A range or step the consumer moved at runtime can pull the committed\n // number with it. That is this controller's decision, so it is reported\n // apart from `change`, which stays reserved for user edits.\n if (previous !== null && value !== previous) {\n this.dispatch(\"reconcile\", { detail: { value } });\n }\n } else {\n this.#lastValue = null;\n this.#reflectEmpty();\n }\n }\n\n /** Reflects `value` on the input (and ARIA for non-native hosts) and the buttons. */\n #write(value: number): void {\n const input = this.inputTarget;\n input.value = String(value);\n this.#syncInputAria(input, value);\n this.#updateButtons(value);\n }\n\n /** Reflects a blank value without inventing a numeric `aria-valuenow`. */\n #reflectEmpty(): void {\n this.#syncInputAria(this.inputTarget, null);\n this.#updateButtons(this.#currentValue());\n }\n\n /** Synchronizes controller-derived ARIA while preserving authored teardown values. */\n #syncInputAria(input: HTMLInputElement, value: number | null): void {\n if (input.getAttribute(\"role\") !== \"spinbutton\") {\n this.#releaseInputAria(input);\n return;\n }\n this.#ariaValueNow.write(input, value === null ? null : String(value));\n this.#ariaValueMin.write(input, Number.isFinite(this.minValue) ? String(this.minValue) : null);\n this.#ariaValueMax.write(input, Number.isFinite(this.maxValue) ? String(this.maxValue) : null);\n }\n\n /** Returns all custom-spinbutton ARIA leased on `input`. */\n #releaseInputAria(input: HTMLInputElement): void {\n this.#ariaValueNow.return(input);\n this.#ariaValueMin.return(input);\n this.#ariaValueMax.return(input);\n }\n\n /** Disables a step button at its bound, returning focus to the input first. */\n #updateButtons(value: number): void {\n for (const button of this.incrementTargets) this.#toggleButton(button, value < this.maxValue);\n for (const button of this.decrementTargets) this.#toggleButton(button, value > this.minValue);\n }\n\n /**\n * Enables or disables a step button at its bound, never disabling one while it\n * holds focus. Owns only the `disabled` it sets itself via a marker\n * (`data-number-input-disabled`, like `conditional-fields`/`submit-once`), so an\n * author-disabled button (e.g. the whole control disabled) is never re-enabled.\n */\n #toggleButton(button: HTMLButtonElement, enabled: boolean): void {\n if (enabled) {\n if (button.hasAttribute(OWNED_DISABLED)) {\n button.disabled = false;\n button.removeAttribute(OWNED_DISABLED);\n }\n return;\n }\n if (button.disabled) return; // already disabled (possibly by the author) — leave it\n if (document.activeElement === button && this.hasInputTarget) this.inputTarget.focus();\n button.disabled = true;\n button.setAttribute(OWNED_DISABLED, \"\");\n }\n\n /** Returns `disabled` only when its explicit marker still identifies controller ownership. */\n #releaseButtonState(button: HTMLButtonElement): void {\n if (!button.hasAttribute(OWNED_DISABLED)) return;\n button.disabled = false;\n button.removeAttribute(OWNED_DISABLED);\n }\n\n /** The current numeric value, falling back to a finite min (else 0) when blank. */\n #currentValue(): number {\n const parsed = Number(this.inputTarget.value);\n if (Number.isFinite(parsed) && this.inputTarget.value.trim() !== \"\") return parsed;\n return Number.isFinite(this.minValue) ? this.minValue : 0;\n }\n\n /** Clamps to `[min, max]` and snaps to the step grid anchored at a finite min (else 0). */\n #normalize(raw: number): number {\n return snapSteppedValue(raw, this.#steppedRange);\n }\n\n /** Shared range configuration; finite endpoints remain allowed off the grid. */\n get #steppedRange() {\n return { min: this.minValue, max: this.maxValue, step: this.stepValue };\n }\n /** Returns borrowed range ARIA before Turbo snapshots the page. */\n #rewindForCache(): void {\n this.#ariaValueNow.returnAll();\n this.#ariaValueMin.returnAll();\n this.#ariaValueMax.returnAll();\n }\n}\n"]}
@@ -22,6 +22,9 @@ import { Controller } from '@hotwired/stimulus';
22
22
  * - Clipboard intercepting paste division across fields with trailing focus positioning.
23
23
  * - Hidden form sync and complete/change event dispatching.
24
24
  *
25
+ * `change` and `complete` dispatch `{ value: string }`; `invalid` dispatches
26
+ * `{ pattern: string }`.
27
+ *
25
28
  * @remarks
26
29
  * Behavior only. The controller binds events dynamically to pre-rendered inputs,
27
30
  * updates `data-filled` and hidden value bindings, and emits Stimulus custom events.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/logical_scroll.ts","../../src/utils/arrow_step.ts","../../src/utils/composition_tracker.ts","../../src/controllers/otp_controller.ts"],"names":[],"mappings":"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","file":"otp_controller.js","sourcesContent":["/** Normalized scroll position and maximum distance on one logical axis. */\nexport interface LogicalScrollMetrics {\n position: number;\n max: number;\n}\n\n/**\n * Whether horizontal scrolling on `element` follows right-to-left inline flow.\n *\n * Resolved from the **computed** `direction`, so the authoring contract is the\n * usual `dir=\"rtl\"` (or a stylesheet) on the element or any ancestor.\n *\n * Scope: horizontal writing modes. A vertical writing mode (`writing-mode:\n * vertical-rl`) also inverts the horizontal axis, which this check does not\n * model — vertical writing modes are out of scope for the scroll utilities\n * (their consumers describe axes as horizontal/vertical, not inline/block).\n */\nexport function isRtl(element: Element): boolean {\n return window.getComputedStyle(element).direction === \"rtl\";\n}\n\n/**\n * Returns scroll distance from the logical start edge.\n *\n * CSSOM View exposes standards-mode RTL horizontal offsets as `0` at the inline\n * start (right) and increasingly negative values toward the inline end (left).\n * The normalized position is always clamped to `[0, max]`, which also absorbs\n * Safari's elastic overscroll values.\n */\nexport function logicalScrollMetrics(\n element: HTMLElement,\n horizontal: boolean,\n): LogicalScrollMetrics {\n const max = Math.max(\n 0,\n horizontal\n ? element.scrollWidth - element.clientWidth\n : element.scrollHeight - element.clientHeight,\n );\n const raw = horizontal ? element.scrollLeft : element.scrollTop;\n const position = horizontal && isRtl(element) ? -raw : raw;\n return { position: Math.min(max, Math.max(0, position)), max };\n}\n\n/**\n * Converts a logical start/end delta to the physical value accepted by\n * `Element.scrollBy`.\n */\nexport function physicalScrollDelta(\n element: HTMLElement,\n horizontal: boolean,\n logicalDelta: number,\n): number {\n return horizontal && isRtl(element) ? -logicalDelta : logicalDelta;\n}\n","import { isRtl } from \"./logical_scroll\";\n\n/**\n * Turns an arrow key into a **logical** step: `+1` for \"next\", `-1` for\n * \"previous\", `0` when the key names neither.\n *\n * APG defines the horizontal pair as *next / previous* and says a vertical\n * arrangement swaps in Down/Up for the same meaning — so the pair is one axis's\n * spelling of an order, and the order reverses with the writing direction. Only\n * the horizontal pair reverses. Down/Up name an axis the writing direction does\n * not mirror, and returning them unchanged is the point: many controllers fold\n * both pairs into one branch, where swapping the branches under RTL would flip\n * the vertical axis too — a bug that reads as \"the arrows work\" until someone\n * presses Down.\n *\n * **Direction is read from the element the caller passes, which should be the\n * container that lays the items out** — not the focused child. A child may carry\n * its own `dir` (an LTR input inside an RTL form is ordinary authoring), and\n * probing per handler makes two handlers disagree at the boundary between them.\n *\n * This decides direction only. Whether the axis is even active (an\n * `orientation=\"horizontal\"` widget ignoring Down/Up), how far the step lands,\n * and what wrapping does all stay with the caller.\n *\n * **It encodes the list-order convention: `ArrowDown` is *next*.** Widgets that\n * pair the arrows by *value* instead — `ArrowUp` meaning \"more\", as a rating or a\n * slider does — must not use this, or their vertical axis inverts. Reverse the\n * horizontal pair on its own there.\n *\n * @example\n * ```ts\n * const step = logicalArrowStep(event.key, this.element);\n * if (step === 0) return;\n * this.#roving.setActive(rovingMove(current, length, step, \"wrap\"), { focus: true });\n * ```\n */\nexport function logicalArrowStep(key: string, element: Element): 1 | -1 | 0 {\n if (key === \"ArrowDown\") return 1;\n if (key === \"ArrowUp\") return -1;\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return 0;\n const forward = isRtl(element) ? \"ArrowLeft\" : \"ArrowRight\";\n return key === forward ? 1 : -1;\n}\n\n/**\n * Rewrites `key` so an existing LTR-shaped branch keeps working under RTL:\n * `ArrowRight` and `ArrowLeft` trade places, everything else passes through.\n *\n * The alternative — negating a delta — silently breaks handlers whose two\n * horizontal branches are **not mirror images**. A grid that clamps one edge but\n * not the other, or a segmented field guarding `index > 0` on one side and\n * `index < length - 1` on the other, ends up applying the wrong guard to the\n * wrong direction. Swapping the key leaves each branch, guards and all, exactly\n * where its author put it.\n *\n * Same rule as {@link logicalArrowStep} about which element to read: pass the\n * container that lays the items out, not the focused child.\n *\n * @example\n * ```ts\n * switch (logicalArrowKey(event.key, this.element)) {\n * case \"ArrowLeft\": // \"previous\" — whatever direction that is on screen\n * ```\n */\nexport function logicalArrowKey(key: string, element: Element): string {\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return key;\n if (!isRtl(element)) return key;\n return key === \"ArrowRight\" ? \"ArrowLeft\" : \"ArrowRight\";\n}\n\n/** Modifiers a widget may claim on an arrow key, named for the `allow` list. */\nexport type ArrowModifier = \"alt\" | \"ctrl\" | \"meta\" | \"shift\";\n\n/**\n * True when an arrow key arrived carrying a modifier the widget must leave to\n * the browser: return without calling `preventDefault()` and without moving any\n * state.\n *\n * A bare arrow belongs to the widget; a chorded one usually does not.\n * `Alt`/`Meta` plus a horizontal arrow is history back/forward on every desktop\n * browser, and a widget that swallows it makes the shortcut work or not\n * depending on where focus happens to sit — a coin-flip the user cannot see.\n *\n * `allow` is for the combinations APG assigns to a pattern **and the widget\n * actually implements** — today only Combobox's optional `Alt+Down`/`Alt+Up`.\n * Listing one the widget does not implement defeats the point: the chord then\n * runs the plain-arrow branch, which is exactly what this guard exists to stop.\n * Non-arrow keys return `false`, so chorded letters and\n * `Control+Home`/`Control+End` are untouched.\n *\n * @example\n * ```ts\n * if (isReservedArrowChord(event)) return;\n * ```\n */\nexport function isReservedArrowChord(\n event: KeyboardEvent,\n allow: readonly ArrowModifier[] = [],\n): boolean {\n if (!event.key.startsWith(\"Arrow\")) return false;\n return (\n (event.altKey && !allow.includes(\"alt\")) ||\n (event.ctrlKey && !allow.includes(\"ctrl\")) ||\n (event.metaKey && !allow.includes(\"meta\")) ||\n (event.shiftKey && !allow.includes(\"shift\"))\n );\n}\n","/** Minimal event shape carrying the platform's per-event composition signal. */\nexport interface CompositionSignal {\n readonly isComposing?: boolean;\n}\n\n/** Hooks that keep component-specific work outside {@link CompositionTracker}. */\nexport interface CompositionTrackerOptions {\n /** Runs after lifecycle state is set for a `compositionstart` event. */\n readonly onStart?: (event: Event) => void;\n /** Runs after lifecycle state is cleared for a `compositionend` event. */\n readonly onEnd?: (event: Event) => void;\n}\n\n/**\n * Owns IME composition listeners and transient state for one or more event targets.\n *\n * Some browsers omit `KeyboardEvent.isComposing` on the keydown that confirms a\n * conversion. Tracking `compositionstart` through `compositionend` supplies the\n * missing lifecycle signal without relying on deprecated numeric key codes.\n * Component policy stays with the consumer: filtering, validation, and submission\n * belong in the optional {@link CompositionTrackerOptions.onEnd} callback.\n *\n * @example\n * ```ts\n * #composition = new CompositionTracker({ onEnd: () => this.filter() });\n *\n * connect(): void {\n * this.#composition.observe(this.inputTarget);\n * }\n *\n * disconnect(): void {\n * this.#composition.disconnect();\n * }\n *\n * onKeydown(event: KeyboardEvent): void {\n * if (this.#composition.isComposing(event)) return;\n * }\n * ```\n */\nexport class CompositionTracker {\n readonly #observedTargets = new Set<EventTarget>();\n readonly #activeTargets = new Set<EventTarget>();\n readonly #onStart: ((event: Event) => void) | undefined;\n readonly #onEnd: ((event: Event) => void) | undefined;\n\n constructor(options: CompositionTrackerOptions = {}) {\n this.#onStart = options.onStart;\n this.#onEnd = options.onEnd;\n }\n\n /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */\n observe(target: EventTarget): void {\n if (this.#observedTargets.has(target)) return;\n target.addEventListener(\"compositionstart\", this.#handleStart);\n target.addEventListener(\"compositionend\", this.#handleEnd);\n this.#observedTargets.add(target);\n }\n\n /** Stops tracking one target and clears any active composition it owned. */\n unobserve(target: EventTarget): void {\n if (!this.#observedTargets.delete(target)) return;\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n this.#activeTargets.delete(target);\n }\n\n /** Releases every listener and clears state so reconnect starts cleanly. */\n disconnect(): void {\n for (const target of this.#observedTargets) {\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n }\n this.#observedTargets.clear();\n this.#activeTargets.clear();\n }\n\n /** True when lifecycle tracking or the current event reports composition. */\n isComposing(event?: CompositionSignal): boolean {\n return this.#activeTargets.size > 0 || event?.isComposing === true;\n }\n\n readonly #handleStart = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.add(event.currentTarget);\n this.#onStart?.(event);\n };\n\n readonly #handleEnd = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);\n this.#onEnd?.(event);\n };\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { isReservedArrowChord, logicalArrowKey } from \"../utils/arrow_step\";\nimport { CompositionTracker } from \"../utils/composition_tracker\";\n\n/**\n * Headless, accessible One-Time Password / PIN input logic.\n *\n * Markup contract (identifier: `stimeo--otp`):\n * <div data-controller=\"stimeo--otp\"\n * data-stimeo--otp-length-value=\"6\"\n * data-stimeo--otp-pattern-value=\"[0-9]\"\n * role=\"group\" aria-label=\"One-time passcode\">\n * <input data-stimeo--otp-target=\"field\" inputmode=\"numeric\" maxlength=\"1\"\n * data-action=\"input->stimeo--otp#onInput\n * keydown->stimeo--otp#onKeydown\n * paste->stimeo--otp#onPaste\" />\n * <input type=\"hidden\" data-stimeo--otp-target=\"value\" />\n * </div>\n *\n * Implements highly polished UX conventions for single-digit field groups:\n * - Dynamic autofocus advancement upon valid inputs.\n * - Auto-selection `select()` upon gaining focus to enable frictionless digit overwrites.\n * - Retroactive Backspace key focus stepping to clear preceding values safely.\n * - Clipboard intercepting paste division across fields with trailing focus positioning.\n * - Hidden form sync and complete/change event dispatching.\n *\n * @remarks\n * Behavior only. The controller binds events dynamically to pre-rendered inputs,\n * updates `data-filled` and hidden value bindings, and emits Stimulus custom events.\n */\nexport class OtpController extends Controller<HTMLElement> {\n static override targets = [\"field\", \"value\", \"error\"];\n static override values = {\n length: { type: Number, default: 6 },\n pattern: { type: String, default: \"[0-9]\" },\n };\n static actions = [\"onInput\", \"onKeydown\", \"onPaste\"] as const;\n static events = [\"change\", \"complete\", \"invalid\"] as const;\n\n declare readonly fieldTargets: HTMLInputElement[];\n declare readonly valueTarget: HTMLInputElement;\n declare readonly errorTarget: HTMLElement;\n declare readonly hasValueTarget: boolean;\n declare readonly hasErrorTarget: boolean;\n\n declare lengthValue: number;\n declare patternValue: string;\n\n /** Owns IME lifecycle state across every digit field. */\n readonly #composition = new CompositionTracker({\n onEnd: (event) => {\n const input = event.currentTarget as HTMLInputElement | null;\n if (input) this.#handleInputValidation(input);\n },\n });\n\n override connect(): void {\n // Dynamically bind auto-selection and IME tracking logic to all connected inputs\n for (const field of this.fieldTargets) {\n field.addEventListener(\"focus\", this.#onFieldFocus);\n this.#composition.observe(field);\n }\n }\n\n override disconnect(): void {\n for (const field of this.fieldTargets) {\n field.removeEventListener(\"focus\", this.#onFieldFocus);\n }\n this.#composition.disconnect();\n }\n\n /**\n * Stimulus lifecycle callback when a new field target enters the DOM.\n * Ensures new additions are also wired with overwriting support.\n */\n fieldTargetConnected(element: HTMLInputElement): void {\n element.addEventListener(\"focus\", this.#onFieldFocus);\n this.#composition.observe(element);\n }\n\n /** Removes focus listeners when fields are dropped. */\n fieldTargetDisconnected(element: HTMLInputElement): void {\n element.removeEventListener(\"focus\", this.#onFieldFocus);\n this.#composition.unobserve(element);\n }\n\n /** Handles keystroke inputs and advances focus to the next field. */\n onInput(event: Event): void {\n const input = event.currentTarget as HTMLInputElement | null;\n if (!input) return;\n\n // Guard during active composition to prevent premature focus switching\n if (this.#composition.isComposing(event as InputEvent)) return;\n\n this.#handleInputValidation(input);\n }\n\n /** Handles Backspace retreating, arrows, and home/end navigation. */\n onKeydown(event: KeyboardEvent): void {\n if (isReservedArrowChord(event)) return;\n const input = event.currentTarget as HTMLInputElement | null;\n if (!input) return;\n\n const index = this.fieldTargets.indexOf(input);\n if (index === -1) return;\n\n // Do not trigger keydown actions during composition\n if (this.#composition.isComposing(event)) return;\n // Logical, not physical. The key is normalised rather than the\n // delta negated: these two branches are not mirror images — their bounds\n // guards differ — so swapping the key keeps each guard with its own direction.\n\n switch (logicalArrowKey(event.key, this.element)) {\n case \"Backspace\":\n if (!input.value) {\n // Empty field: step backward, wipe previous digit, and focus it\n if (index > 0) {\n event.preventDefault();\n const prevField = this.fieldTargets[index - 1];\n if (prevField) {\n prevField.value = \"\";\n prevField.removeAttribute(\"data-filled\");\n prevField.focus();\n this.#clearError();\n this.#syncAndDispatch();\n }\n }\n } else {\n // Filled field: clear current value\n input.value = \"\";\n input.removeAttribute(\"data-filled\");\n this.#clearError();\n this.#syncAndDispatch();\n }\n break;\n\n case \"ArrowLeft\":\n if (index > 0) {\n event.preventDefault();\n this.fieldTargets[index - 1]?.focus();\n }\n break;\n\n case \"ArrowRight\":\n if (index < this.lengthValue - 1) {\n event.preventDefault();\n this.fieldTargets[index + 1]?.focus();\n }\n break;\n\n case \"Home\":\n event.preventDefault();\n this.fieldTargets[0]?.focus();\n break;\n\n case \"End\":\n event.preventDefault();\n this.fieldTargets[this.lengthValue - 1]?.focus();\n break;\n\n default:\n break;\n }\n }\n\n /** Divides pasted string characters across available input fields. */\n onPaste(event: ClipboardEvent): void {\n const input = event.currentTarget as HTMLInputElement | null;\n if (!input) return;\n\n const startIndex = this.fieldTargets.indexOf(input);\n if (startIndex === -1) return;\n\n event.preventDefault();\n\n const rawText = event.clipboardData?.getData(\"text\") || \"\";\n const text = this.#normalizeValue(rawText);\n const regex = new RegExp(`^${this.patternValue}$`);\n const validChars = Array.from(text).filter((char) => regex.test(char));\n\n if (validChars.length === 0) {\n this.#showError();\n return;\n }\n\n const limit = Math.min(validChars.length, this.lengthValue - startIndex);\n let lastFocusedIndex = startIndex;\n\n for (let i = 0; i < limit; i++) {\n const fieldIndex = startIndex + i;\n const field = this.fieldTargets[fieldIndex];\n const char = validChars[i];\n\n if (field && char) {\n field.value = char;\n field.setAttribute(\"data-filled\", \"true\");\n lastFocusedIndex = fieldIndex;\n }\n }\n\n this.#clearError();\n\n // Set trailing focus position to the last filled box (or next empty if one exists)\n const focusTargetIndex =\n lastFocusedIndex < this.lengthValue - 1 ? lastFocusedIndex + 1 : lastFocusedIndex;\n this.fieldTargets[focusTargetIndex]?.focus();\n\n this.#syncAndDispatch();\n }\n\n readonly #onFieldFocus = (event: FocusEvent): void => {\n const input = event.currentTarget as HTMLInputElement | null;\n if (input) {\n // Auto-selection enables effortless character overwrites\n input.select();\n }\n };\n\n #handleInputValidation(input: HTMLInputElement): void {\n const index = this.fieldTargets.indexOf(input);\n if (index === -1) return;\n\n const rawValue = input.value;\n const normalized = this.#normalizeValue(rawValue);\n const regex = new RegExp(`^${this.patternValue}$`);\n\n if (normalized && regex.test(normalized)) {\n input.value = normalized;\n input.setAttribute(\"data-filled\", \"true\");\n this.#clearError();\n\n // Step focus forward\n if (index < this.lengthValue - 1) {\n const nextField = this.fieldTargets[index + 1];\n nextField?.focus();\n }\n } else if (normalized) {\n input.value = \"\";\n input.removeAttribute(\"data-filled\");\n this.#showError();\n } else {\n input.removeAttribute(\"data-filled\");\n }\n\n this.#syncAndDispatch();\n }\n\n #normalizeValue(val: string): string {\n // Replaces full-width numbers (0-9) with standard half-width ones (0-9)\n return val.replace(/[0-9]/g, (s) => String.fromCharCode(s.charCodeAt(0) - 0xfee0));\n }\n\n #showError(): void {\n if (this.hasErrorTarget) {\n this.errorTarget.removeAttribute(\"hidden\");\n }\n // Behavior only: emit a neutral payload and let the consumer compose/localize\n // the user-facing message. The pattern is reported so consumers can word it.\n this.dispatch(\"invalid\", { detail: { pattern: this.patternValue } });\n }\n\n #clearError(): void {\n if (this.hasErrorTarget) {\n this.errorTarget.setAttribute(\"hidden\", \"true\");\n }\n }\n\n #syncAndDispatch(): void {\n const fields = this.fieldTargets;\n const combinedValue = fields.map((f) => f.value).join(\"\");\n\n if (this.hasValueTarget) {\n this.valueTarget.value = combinedValue;\n }\n\n this.dispatch(\"change\", { detail: { value: combinedValue } });\n\n // Completed state when all fields contain a digit\n const isCompleted =\n fields.every((f) => f.value.length > 0) && combinedValue.length === this.lengthValue;\n if (isCompleted) {\n this.dispatch(\"complete\", { detail: { value: combinedValue } });\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/logical_scroll.ts","../../src/utils/arrow_step.ts","../../src/utils/composition_tracker.ts","../../src/controllers/otp_controller.ts"],"names":[],"mappings":"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","file":"otp_controller.js","sourcesContent":["/** Normalized scroll position and maximum distance on one logical axis. */\nexport interface LogicalScrollMetrics {\n position: number;\n max: number;\n}\n\n/**\n * Whether horizontal scrolling on `element` follows right-to-left inline flow.\n *\n * Resolved from the **computed** `direction`, so the authoring contract is the\n * usual `dir=\"rtl\"` (or a stylesheet) on the element or any ancestor.\n *\n * Scope: horizontal writing modes. A vertical writing mode (`writing-mode:\n * vertical-rl`) also inverts the horizontal axis, which this check does not\n * model — vertical writing modes are out of scope for the scroll utilities\n * (their consumers describe axes as horizontal/vertical, not inline/block).\n */\nexport function isRtl(element: Element): boolean {\n return window.getComputedStyle(element).direction === \"rtl\";\n}\n\n/**\n * Returns scroll distance from the logical start edge.\n *\n * CSSOM View exposes standards-mode RTL horizontal offsets as `0` at the inline\n * start (right) and increasingly negative values toward the inline end (left).\n * The normalized position is always clamped to `[0, max]`, which also absorbs\n * Safari's elastic overscroll values.\n */\nexport function logicalScrollMetrics(\n element: HTMLElement,\n horizontal: boolean,\n): LogicalScrollMetrics {\n const max = Math.max(\n 0,\n horizontal\n ? element.scrollWidth - element.clientWidth\n : element.scrollHeight - element.clientHeight,\n );\n const raw = horizontal ? element.scrollLeft : element.scrollTop;\n const position = horizontal && isRtl(element) ? -raw : raw;\n return { position: Math.min(max, Math.max(0, position)), max };\n}\n\n/**\n * Converts a logical start/end delta to the physical value accepted by\n * `Element.scrollBy`.\n */\nexport function physicalScrollDelta(\n element: HTMLElement,\n horizontal: boolean,\n logicalDelta: number,\n): number {\n return horizontal && isRtl(element) ? -logicalDelta : logicalDelta;\n}\n","import { isRtl } from \"./logical_scroll\";\n\n/**\n * Turns an arrow key into a **logical** step: `+1` for \"next\", `-1` for\n * \"previous\", `0` when the key names neither.\n *\n * APG defines the horizontal pair as *next / previous* and says a vertical\n * arrangement swaps in Down/Up for the same meaning — so the pair is one axis's\n * spelling of an order, and the order reverses with the writing direction. Only\n * the horizontal pair reverses. Down/Up name an axis the writing direction does\n * not mirror, and returning them unchanged is the point: many controllers fold\n * both pairs into one branch, where swapping the branches under RTL would flip\n * the vertical axis too — a bug that reads as \"the arrows work\" until someone\n * presses Down.\n *\n * **Direction is read from the element the caller passes, which should be the\n * container that lays the items out** — not the focused child. A child may carry\n * its own `dir` (an LTR input inside an RTL form is ordinary authoring), and\n * probing per handler makes two handlers disagree at the boundary between them.\n *\n * This decides direction only. Whether the axis is even active (an\n * `orientation=\"horizontal\"` widget ignoring Down/Up), how far the step lands,\n * and what wrapping does all stay with the caller.\n *\n * **It encodes the list-order convention: `ArrowDown` is *next*.** Widgets that\n * pair the arrows by *value* instead — `ArrowUp` meaning \"more\", as a rating or a\n * slider does — must not use this, or their vertical axis inverts. Reverse the\n * horizontal pair on its own there.\n *\n * @example\n * ```ts\n * const step = logicalArrowStep(event.key, this.element);\n * if (step === 0) return;\n * this.#roving.setActive(rovingMove(current, length, step, \"wrap\"), { focus: true });\n * ```\n */\nexport function logicalArrowStep(key: string, element: Element): 1 | -1 | 0 {\n if (key === \"ArrowDown\") return 1;\n if (key === \"ArrowUp\") return -1;\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return 0;\n const forward = isRtl(element) ? \"ArrowLeft\" : \"ArrowRight\";\n return key === forward ? 1 : -1;\n}\n\n/**\n * Rewrites `key` so an existing LTR-shaped branch keeps working under RTL:\n * `ArrowRight` and `ArrowLeft` trade places, everything else passes through.\n *\n * The alternative — negating a delta — silently breaks handlers whose two\n * horizontal branches are **not mirror images**. A grid that clamps one edge but\n * not the other, or a segmented field guarding `index > 0` on one side and\n * `index < length - 1` on the other, ends up applying the wrong guard to the\n * wrong direction. Swapping the key leaves each branch, guards and all, exactly\n * where its author put it.\n *\n * Same rule as {@link logicalArrowStep} about which element to read: pass the\n * container that lays the items out, not the focused child.\n *\n * @example\n * ```ts\n * switch (logicalArrowKey(event.key, this.element)) {\n * case \"ArrowLeft\": // \"previous\" — whatever direction that is on screen\n * ```\n */\nexport function logicalArrowKey(key: string, element: Element): string {\n if (key !== \"ArrowRight\" && key !== \"ArrowLeft\") return key;\n if (!isRtl(element)) return key;\n return key === \"ArrowRight\" ? \"ArrowLeft\" : \"ArrowRight\";\n}\n\n/** Modifiers a widget may claim on an arrow key, named for the `allow` list. */\nexport type ArrowModifier = \"alt\" | \"ctrl\" | \"meta\" | \"shift\";\n\n/**\n * True when an arrow key arrived carrying a modifier the widget must leave to\n * the browser: return without calling `preventDefault()` and without moving any\n * state.\n *\n * A bare arrow belongs to the widget; a chorded one usually does not.\n * `Alt`/`Meta` plus a horizontal arrow is history back/forward on every desktop\n * browser, and a widget that swallows it makes the shortcut work or not\n * depending on where focus happens to sit — a coin-flip the user cannot see.\n *\n * `allow` is for the combinations APG assigns to a pattern **and the widget\n * actually implements** — today only Combobox's optional `Alt+Down`/`Alt+Up`.\n * Listing one the widget does not implement defeats the point: the chord then\n * runs the plain-arrow branch, which is exactly what this guard exists to stop.\n * Non-arrow keys return `false`, so chorded letters and\n * `Control+Home`/`Control+End` are untouched.\n *\n * @example\n * ```ts\n * if (isReservedArrowChord(event)) return;\n * ```\n */\nexport function isReservedArrowChord(\n event: KeyboardEvent,\n allow: readonly ArrowModifier[] = [],\n): boolean {\n if (!event.key.startsWith(\"Arrow\")) return false;\n return (\n (event.altKey && !allow.includes(\"alt\")) ||\n (event.ctrlKey && !allow.includes(\"ctrl\")) ||\n (event.metaKey && !allow.includes(\"meta\")) ||\n (event.shiftKey && !allow.includes(\"shift\"))\n );\n}\n","/** Minimal event shape carrying the platform's per-event composition signal. */\nexport interface CompositionSignal {\n readonly isComposing?: boolean;\n}\n\n/** Hooks that keep component-specific work outside {@link CompositionTracker}. */\nexport interface CompositionTrackerOptions {\n /** Runs after lifecycle state is set for a `compositionstart` event. */\n readonly onStart?: (event: Event) => void;\n /** Runs after lifecycle state is cleared for a `compositionend` event. */\n readonly onEnd?: (event: Event) => void;\n}\n\n/**\n * Owns IME composition listeners and transient state for one or more event targets.\n *\n * Some browsers omit `KeyboardEvent.isComposing` on the keydown that confirms a\n * conversion. Tracking `compositionstart` through `compositionend` supplies the\n * missing lifecycle signal without relying on deprecated numeric key codes.\n * Component policy stays with the consumer: filtering, validation, and submission\n * belong in the optional {@link CompositionTrackerOptions.onEnd} callback.\n *\n * @example\n * ```ts\n * #composition = new CompositionTracker({ onEnd: () => this.filter() });\n *\n * connect(): void {\n * this.#composition.observe(this.inputTarget);\n * }\n *\n * disconnect(): void {\n * this.#composition.disconnect();\n * }\n *\n * onKeydown(event: KeyboardEvent): void {\n * if (this.#composition.isComposing(event)) return;\n * }\n * ```\n */\nexport class CompositionTracker {\n readonly #observedTargets = new Set<EventTarget>();\n readonly #activeTargets = new Set<EventTarget>();\n readonly #onStart: ((event: Event) => void) | undefined;\n readonly #onEnd: ((event: Event) => void) | undefined;\n\n constructor(options: CompositionTrackerOptions = {}) {\n this.#onStart = options.onStart;\n this.#onEnd = options.onEnd;\n }\n\n /** Starts lifecycle tracking for `target`; repeated calls are idempotent. */\n observe(target: EventTarget): void {\n if (this.#observedTargets.has(target)) return;\n target.addEventListener(\"compositionstart\", this.#handleStart);\n target.addEventListener(\"compositionend\", this.#handleEnd);\n this.#observedTargets.add(target);\n }\n\n /** Stops tracking one target and clears any active composition it owned. */\n unobserve(target: EventTarget): void {\n if (!this.#observedTargets.delete(target)) return;\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n this.#activeTargets.delete(target);\n }\n\n /** Releases every listener and clears state so reconnect starts cleanly. */\n disconnect(): void {\n for (const target of this.#observedTargets) {\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n }\n this.#observedTargets.clear();\n this.#activeTargets.clear();\n }\n\n /** True when lifecycle tracking or the current event reports composition. */\n isComposing(event?: CompositionSignal): boolean {\n return this.#activeTargets.size > 0 || event?.isComposing === true;\n }\n\n readonly #handleStart = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.add(event.currentTarget);\n this.#onStart?.(event);\n };\n\n readonly #handleEnd = (event: Event): void => {\n if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);\n this.#onEnd?.(event);\n };\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { isReservedArrowChord, logicalArrowKey } from \"../utils/arrow_step\";\nimport { CompositionTracker } from \"../utils/composition_tracker\";\n\n/**\n * Headless, accessible One-Time Password / PIN input logic.\n *\n * Markup contract (identifier: `stimeo--otp`):\n * <div data-controller=\"stimeo--otp\"\n * data-stimeo--otp-length-value=\"6\"\n * data-stimeo--otp-pattern-value=\"[0-9]\"\n * role=\"group\" aria-label=\"One-time passcode\">\n * <input data-stimeo--otp-target=\"field\" inputmode=\"numeric\" maxlength=\"1\"\n * data-action=\"input->stimeo--otp#onInput\n * keydown->stimeo--otp#onKeydown\n * paste->stimeo--otp#onPaste\" />\n * <input type=\"hidden\" data-stimeo--otp-target=\"value\" />\n * </div>\n *\n * Implements highly polished UX conventions for single-digit field groups:\n * - Dynamic autofocus advancement upon valid inputs.\n * - Auto-selection `select()` upon gaining focus to enable frictionless digit overwrites.\n * - Retroactive Backspace key focus stepping to clear preceding values safely.\n * - Clipboard intercepting paste division across fields with trailing focus positioning.\n * - Hidden form sync and complete/change event dispatching.\n *\n * `change` and `complete` dispatch `{ value: string }`; `invalid` dispatches\n * `{ pattern: string }`.\n *\n * @remarks\n * Behavior only. The controller binds events dynamically to pre-rendered inputs,\n * updates `data-filled` and hidden value bindings, and emits Stimulus custom events.\n */\nexport class OtpController extends Controller<HTMLElement> {\n static override targets = [\"field\", \"value\", \"error\"];\n static override values = {\n length: { type: Number, default: 6 },\n pattern: { type: String, default: \"[0-9]\" },\n };\n static actions = [\"onInput\", \"onKeydown\", \"onPaste\"] as const;\n static events = [\"change\", \"complete\", \"invalid\"] as const;\n\n declare readonly fieldTargets: HTMLInputElement[];\n declare readonly valueTarget: HTMLInputElement;\n declare readonly errorTarget: HTMLElement;\n declare readonly hasValueTarget: boolean;\n declare readonly hasErrorTarget: boolean;\n\n declare lengthValue: number;\n declare patternValue: string;\n\n /** Owns IME lifecycle state across every digit field. */\n readonly #composition = new CompositionTracker({\n onEnd: (event) => {\n const input = event.currentTarget as HTMLInputElement | null;\n if (input) this.#handleInputValidation(input);\n },\n });\n\n override connect(): void {\n // Dynamically bind auto-selection and IME tracking logic to all connected inputs\n for (const field of this.fieldTargets) {\n field.addEventListener(\"focus\", this.#onFieldFocus);\n this.#composition.observe(field);\n }\n }\n\n override disconnect(): void {\n for (const field of this.fieldTargets) {\n field.removeEventListener(\"focus\", this.#onFieldFocus);\n }\n this.#composition.disconnect();\n }\n\n /**\n * Stimulus lifecycle callback when a new field target enters the DOM.\n * Ensures new additions are also wired with overwriting support.\n */\n fieldTargetConnected(element: HTMLInputElement): void {\n element.addEventListener(\"focus\", this.#onFieldFocus);\n this.#composition.observe(element);\n }\n\n /** Removes focus listeners when fields are dropped. */\n fieldTargetDisconnected(element: HTMLInputElement): void {\n element.removeEventListener(\"focus\", this.#onFieldFocus);\n this.#composition.unobserve(element);\n }\n\n /** Handles keystroke inputs and advances focus to the next field. */\n onInput(event: Event): void {\n const input = event.currentTarget as HTMLInputElement | null;\n if (!input) return;\n\n // Guard during active composition to prevent premature focus switching\n if (this.#composition.isComposing(event as InputEvent)) return;\n\n this.#handleInputValidation(input);\n }\n\n /** Handles Backspace retreating, arrows, and home/end navigation. */\n onKeydown(event: KeyboardEvent): void {\n if (isReservedArrowChord(event)) return;\n const input = event.currentTarget as HTMLInputElement | null;\n if (!input) return;\n\n const index = this.fieldTargets.indexOf(input);\n if (index === -1) return;\n\n // Do not trigger keydown actions during composition\n if (this.#composition.isComposing(event)) return;\n // Logical, not physical. The key is normalised rather than the\n // delta negated: these two branches are not mirror images — their bounds\n // guards differ — so swapping the key keeps each guard with its own direction.\n\n switch (logicalArrowKey(event.key, this.element)) {\n case \"Backspace\":\n if (!input.value) {\n // Empty field: step backward, wipe previous digit, and focus it\n if (index > 0) {\n event.preventDefault();\n const prevField = this.fieldTargets[index - 1];\n if (prevField) {\n prevField.value = \"\";\n prevField.removeAttribute(\"data-filled\");\n prevField.focus();\n this.#clearError();\n this.#syncAndDispatch();\n }\n }\n } else {\n // Filled field: clear current value\n input.value = \"\";\n input.removeAttribute(\"data-filled\");\n this.#clearError();\n this.#syncAndDispatch();\n }\n break;\n\n case \"ArrowLeft\":\n if (index > 0) {\n event.preventDefault();\n this.fieldTargets[index - 1]?.focus();\n }\n break;\n\n case \"ArrowRight\":\n if (index < this.lengthValue - 1) {\n event.preventDefault();\n this.fieldTargets[index + 1]?.focus();\n }\n break;\n\n case \"Home\":\n event.preventDefault();\n this.fieldTargets[0]?.focus();\n break;\n\n case \"End\":\n event.preventDefault();\n this.fieldTargets[this.lengthValue - 1]?.focus();\n break;\n\n default:\n break;\n }\n }\n\n /** Divides pasted string characters across available input fields. */\n onPaste(event: ClipboardEvent): void {\n const input = event.currentTarget as HTMLInputElement | null;\n if (!input) return;\n\n const startIndex = this.fieldTargets.indexOf(input);\n if (startIndex === -1) return;\n\n event.preventDefault();\n\n const rawText = event.clipboardData?.getData(\"text\") || \"\";\n const text = this.#normalizeValue(rawText);\n const regex = new RegExp(`^${this.patternValue}$`);\n const validChars = Array.from(text).filter((char) => regex.test(char));\n\n if (validChars.length === 0) {\n this.#showError();\n return;\n }\n\n const limit = Math.min(validChars.length, this.lengthValue - startIndex);\n let lastFocusedIndex = startIndex;\n\n for (let i = 0; i < limit; i++) {\n const fieldIndex = startIndex + i;\n const field = this.fieldTargets[fieldIndex];\n const char = validChars[i];\n\n if (field && char) {\n field.value = char;\n field.setAttribute(\"data-filled\", \"true\");\n lastFocusedIndex = fieldIndex;\n }\n }\n\n this.#clearError();\n\n // Set trailing focus position to the last filled box (or next empty if one exists)\n const focusTargetIndex =\n lastFocusedIndex < this.lengthValue - 1 ? lastFocusedIndex + 1 : lastFocusedIndex;\n this.fieldTargets[focusTargetIndex]?.focus();\n\n this.#syncAndDispatch();\n }\n\n readonly #onFieldFocus = (event: FocusEvent): void => {\n const input = event.currentTarget as HTMLInputElement | null;\n if (input) {\n // Auto-selection enables effortless character overwrites\n input.select();\n }\n };\n\n #handleInputValidation(input: HTMLInputElement): void {\n const index = this.fieldTargets.indexOf(input);\n if (index === -1) return;\n\n const rawValue = input.value;\n const normalized = this.#normalizeValue(rawValue);\n const regex = new RegExp(`^${this.patternValue}$`);\n\n if (normalized && regex.test(normalized)) {\n input.value = normalized;\n input.setAttribute(\"data-filled\", \"true\");\n this.#clearError();\n\n // Step focus forward\n if (index < this.lengthValue - 1) {\n const nextField = this.fieldTargets[index + 1];\n nextField?.focus();\n }\n } else if (normalized) {\n input.value = \"\";\n input.removeAttribute(\"data-filled\");\n this.#showError();\n } else {\n input.removeAttribute(\"data-filled\");\n }\n\n this.#syncAndDispatch();\n }\n\n #normalizeValue(val: string): string {\n // Replaces full-width numbers (0-9) with standard half-width ones (0-9)\n return val.replace(/[0-9]/g, (s) => String.fromCharCode(s.charCodeAt(0) - 0xfee0));\n }\n\n #showError(): void {\n if (this.hasErrorTarget) {\n this.errorTarget.removeAttribute(\"hidden\");\n }\n // Behavior only: emit a neutral payload and let the consumer compose/localize\n // the user-facing message. The pattern is reported so consumers can word it.\n this.dispatch(\"invalid\", { detail: { pattern: this.patternValue } });\n }\n\n #clearError(): void {\n if (this.hasErrorTarget) {\n this.errorTarget.setAttribute(\"hidden\", \"true\");\n }\n }\n\n #syncAndDispatch(): void {\n const fields = this.fieldTargets;\n const combinedValue = fields.map((f) => f.value).join(\"\");\n\n if (this.hasValueTarget) {\n this.valueTarget.value = combinedValue;\n }\n\n this.dispatch(\"change\", { detail: { value: combinedValue } });\n\n // Completed state when all fields contain a digit\n const isCompleted =\n fields.every((f) => f.value.length > 0) && combinedValue.length === this.lengthValue;\n if (isCompleted) {\n this.dispatch(\"complete\", { detail: { value: combinedValue } });\n }\n }\n}\n"]}
@@ -27,6 +27,8 @@ import { Controller } from '@hotwired/stimulus';
27
27
  * scroll one logical viewport page at a time (including RTL) and have their
28
28
  * disabled state synced to the matching direction's remaining room.
29
29
  *
30
+ * `change` dispatches `{ start: boolean, end: boolean }`.
31
+ *
30
32
  * @remarks
31
33
  * Behavior only — shadows, arrows, and gradients are the consumer's CSS;
32
34
  * `data-overflow-*` carry no ARIA semantics. All observers/listeners are released