stimeo-ui 0.16.0 → 0.18.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.
- package/CHANGELOG.md +136 -0
- package/README.md +27 -11
- package/dist/cable/index.d.ts +88 -31
- package/dist/cable/index.js +384 -449
- package/dist/cable/index.js.map +1 -1
- package/dist/coerce-JtZVNG5h.d.ts +20 -0
- package/dist/controllers/accordion_controller.d.ts +4 -2
- package/dist/controllers/accordion_controller.js +174 -55
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.d.ts +12 -2
- package/dist/controllers/alert_dialog_controller.js +903 -235
- package/dist/controllers/alert_dialog_controller.js.map +1 -1
- package/dist/controllers/announcer_controller.d.ts +37 -5
- package/dist/controllers/announcer_controller.js +238 -205
- package/dist/controllers/announcer_controller.js.map +1 -1
- package/dist/controllers/aspect_ratio_controller.js +0 -10
- package/dist/controllers/aspect_ratio_controller.js.map +1 -1
- package/dist/controllers/auto_submit_controller.d.ts +30 -6
- package/dist/controllers/auto_submit_controller.js +414 -145
- package/dist/controllers/auto_submit_controller.js.map +1 -1
- package/dist/controllers/avatar_controller.js +185 -107
- package/dist/controllers/avatar_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.js +0 -130
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/bulk_select_controller.d.ts +21 -3
- package/dist/controllers/bulk_select_controller.js +282 -58
- package/dist/controllers/bulk_select_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +38 -16
- package/dist/controllers/calendar_controller.js +228 -260
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +43 -12
- package/dist/controllers/carousel_controller.js +536 -436
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/character_counter_controller.d.ts +44 -7
- package/dist/controllers/character_counter_controller.js +493 -207
- package/dist/controllers/character_counter_controller.js.map +1 -1
- package/dist/controllers/checkbox_controller.d.ts +7 -2
- package/dist/controllers/checkbox_controller.js +38 -74
- package/dist/controllers/checkbox_controller.js.map +1 -1
- package/dist/controllers/clipboard_controller.d.ts +16 -5
- package/dist/controllers/clipboard_controller.js +261 -149
- package/dist/controllers/clipboard_controller.js.map +1 -1
- package/dist/controllers/collapsible_controller.d.ts +17 -5
- package/dist/controllers/collapsible_controller.js +304 -120
- package/dist/controllers/collapsible_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.d.ts +18 -6
- package/dist/controllers/color_picker_controller.js +178 -146
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.d.ts +24 -6
- package/dist/controllers/combobox_controller.js +522 -156
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +51 -20
- package/dist/controllers/command_palette_controller.js +1156 -395
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/conditional_fields_controller.d.ts +15 -2
- package/dist/controllers/conditional_fields_controller.js +300 -171
- package/dist/controllers/conditional_fields_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.d.ts +49 -12
- package/dist/controllers/confirm_controller.js +980 -262
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +80 -18
- package/dist/controllers/context_menu_controller.js +346 -153
- package/dist/controllers/context_menu_controller.js.map +1 -1
- package/dist/controllers/count_up_controller.d.ts +13 -1
- package/dist/controllers/count_up_controller.js +73 -21
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/countdown_controller.d.ts +47 -3
- package/dist/controllers/countdown_controller.js +281 -158
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +93 -10
- package/dist/controllers/currency_input_controller.js +575 -225
- package/dist/controllers/currency_input_controller.js.map +1 -1
- package/dist/controllers/data_grid_controller.d.ts +25 -12
- package/dist/controllers/data_grid_controller.js +248 -214
- package/dist/controllers/data_grid_controller.js.map +1 -1
- package/dist/controllers/date_range_picker_controller.d.ts +42 -14
- package/dist/controllers/date_range_picker_controller.js +338 -235
- package/dist/controllers/date_range_picker_controller.js.map +1 -1
- package/dist/controllers/dialog_controller.d.ts +17 -6
- package/dist/controllers/dialog_controller.js +899 -237
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.d.ts +25 -8
- package/dist/controllers/direct_upload_controller.js +97 -167
- package/dist/controllers/direct_upload_controller.js.map +1 -1
- package/dist/controllers/dirty_form_controller.d.ts +6 -1
- package/dist/controllers/dirty_form_controller.js +72 -69
- package/dist/controllers/dirty_form_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.d.ts +19 -0
- package/dist/controllers/dismissible_controller.js +196 -24
- package/dist/controllers/dismissible_controller.js.map +1 -1
- package/dist/controllers/drawer_controller.d.ts +39 -11
- package/dist/controllers/drawer_controller.js +974 -355
- package/dist/controllers/drawer_controller.js.map +1 -1
- package/dist/controllers/dropdown_controller.d.ts +31 -1
- package/dist/controllers/dropdown_controller.js +339 -96
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.d.ts +12 -1
- package/dist/controllers/editable_controller.js +315 -88
- package/dist/controllers/editable_controller.js.map +1 -1
- package/dist/controllers/empty_state_controller.js +79 -58
- package/dist/controllers/empty_state_controller.js.map +1 -1
- package/dist/controllers/file_dropzone_controller.d.ts +63 -18
- package/dist/controllers/file_dropzone_controller.js +322 -211
- package/dist/controllers/file_dropzone_controller.js.map +1 -1
- package/dist/controllers/filter_controller.js +77 -42
- package/dist/controllers/filter_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +35 -12
- package/dist/controllers/flash_controller.js +238 -347
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +15 -6
- package/dist/controllers/focus_controller.js +679 -240
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.js +156 -132
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.d.ts +3 -3
- package/dist/controllers/form_validation_controller.js +31 -97
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.d.ts +47 -14
- package/dist/controllers/frame_loading_controller.js +275 -217
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.d.ts +27 -6
- package/dist/controllers/highlight_controller.js +107 -75
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +60 -4
- package/dist/controllers/hover_card_controller.js +327 -130
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +48 -6
- package/dist/controllers/idle_controller.js +271 -101
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/input_mask_controller.d.ts +30 -13
- package/dist/controllers/input_mask_controller.js +483 -97
- package/dist/controllers/input_mask_controller.js.map +1 -1
- package/dist/controllers/intersection_controller.d.ts +32 -13
- package/dist/controllers/intersection_controller.js +150 -106
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.d.ts +19 -2
- package/dist/controllers/lazy_frame_controller.js +24 -68
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +44 -9
- package/dist/controllers/listbox_controller.js +523 -240
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.d.ts +9 -7
- package/dist/controllers/local_time_controller.js +102 -77
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.d.ts +11 -3
- package/dist/controllers/masonry_controller.js +80 -96
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/menu_controller.d.ts +55 -11
- package/dist/controllers/menu_controller.js +302 -188
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +51 -9
- package/dist/controllers/menubar_controller.js +232 -345
- package/dist/controllers/menubar_controller.js.map +1 -1
- package/dist/controllers/meter_controller.d.ts +33 -20
- package/dist/controllers/meter_controller.js +417 -87
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +48 -18
- package/dist/controllers/multi_select_controller.js +785 -393
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/navigation_menu_controller.d.ts +27 -6
- package/dist/controllers/navigation_menu_controller.js +190 -250
- package/dist/controllers/navigation_menu_controller.js.map +1 -1
- package/dist/controllers/nested_form_controller.d.ts +10 -0
- package/dist/controllers/nested_form_controller.js +396 -192
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/network_status_controller.d.ts +23 -0
- package/dist/controllers/network_status_controller.js +268 -62
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +50 -8
- package/dist/controllers/number_input_controller.js +610 -303
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/optimistic_controller.d.ts +8 -5
- package/dist/controllers/optimistic_controller.js +45 -87
- package/dist/controllers/optimistic_controller.js.map +1 -1
- package/dist/controllers/otp_controller.d.ts +55 -8
- package/dist/controllers/otp_controller.js +658 -255
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.d.ts +5 -0
- package/dist/controllers/overflow_indicator_controller.js +122 -113
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +58 -20
- package/dist/controllers/overflow_menu_controller.js +470 -295
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +37 -7
- package/dist/controllers/pagination_controller.js +332 -123
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +46 -8
- package/dist/controllers/password_reveal_controller.js +392 -121
- package/dist/controllers/password_reveal_controller.js.map +1 -1
- package/dist/controllers/password_strength_controller.d.ts +15 -6
- package/dist/controllers/password_strength_controller.js +111 -158
- package/dist/controllers/password_strength_controller.js.map +1 -1
- package/dist/controllers/persist_controller.d.ts +11 -4
- package/dist/controllers/persist_controller.js +165 -111
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +35 -12
- package/dist/controllers/pointer_drag_controller.js +434 -188
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +41 -5
- package/dist/controllers/popover_controller.js +269 -113
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +44 -4
- package/dist/controllers/portal_controller.js +215 -76
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/preview_guard_controller.d.ts +10 -4
- package/dist/controllers/preview_guard_controller.js +243 -116
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/progress_controller.d.ts +20 -19
- package/dist/controllers/progress_controller.js +391 -78
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.d.ts +21 -9
- package/dist/controllers/radio_group_controller.js +278 -211
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +47 -6
- package/dist/controllers/range_slider_controller.js +220 -113
- package/dist/controllers/range_slider_controller.js.map +1 -1
- package/dist/controllers/rating_controller.d.ts +20 -4
- package/dist/controllers/rating_controller.js +458 -211
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.d.ts +2 -0
- package/dist/controllers/read_more_controller.js +138 -63
- package/dist/controllers/read_more_controller.js.map +1 -1
- package/dist/controllers/reading_progress_controller.d.ts +1 -1
- package/dist/controllers/reading_progress_controller.js +166 -137
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/relative_time_controller.d.ts +20 -6
- package/dist/controllers/relative_time_controller.js +211 -112
- package/dist/controllers/relative_time_controller.js.map +1 -1
- package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
- package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +103 -38
- package/dist/controllers/reset_on_restore_controller.js.map +1 -0
- package/dist/controllers/resizable_controller.d.ts +31 -2
- package/dist/controllers/resizable_controller.js +299 -150
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.d.ts +3 -3
- package/dist/controllers/roving_controller.js +49 -88
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.d.ts +7 -3
- package/dist/controllers/scroll_area_controller.js +490 -246
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_restore_controller.d.ts +3 -3
- package/dist/controllers/scroll_restore_controller.js +14 -55
- package/dist/controllers/scroll_restore_controller.js.map +1 -1
- package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
- package/dist/controllers/scroll_visibility_controller.js +432 -149
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.d.ts +6 -1
- package/dist/controllers/scrollspy_controller.js +193 -248
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +20 -5
- package/dist/controllers/separator_controller.js +285 -142
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/sidebar_controller.d.ts +65 -8
- package/dist/controllers/sidebar_controller.js +1069 -404
- package/dist/controllers/sidebar_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.d.ts +23 -0
- package/dist/controllers/skeleton_controller.js +259 -101
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +29 -2
- package/dist/controllers/slider_controller.js +187 -86
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.d.ts +22 -4
- package/dist/controllers/smart_sticky_header_controller.js +173 -66
- package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.d.ts +4 -4
- package/dist/controllers/sortable_controller.js +26 -125
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.d.ts +39 -4
- package/dist/controllers/spinner_controller.js +288 -173
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +9 -4
- package/dist/controllers/step_indicator_controller.js +105 -46
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +14 -6
- package/dist/controllers/stepper_controller.js +120 -73
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +9 -1
- package/dist/controllers/stick_to_bottom_controller.js +275 -140
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.d.ts +11 -0
- package/dist/controllers/sticky_observer_controller.js +220 -49
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +24 -8
- package/dist/controllers/submit_once_controller.js +376 -227
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +18 -4
- package/dist/controllers/switch_controller.js +201 -84
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +9 -6
- package/dist/controllers/tabs_controller.js +41 -30
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +16 -3
- package/dist/controllers/tags_input_controller.js +293 -173
- package/dist/controllers/tags_input_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.d.ts +11 -1
- package/dist/controllers/textarea_autosize_controller.js +108 -74
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/theme_controller.d.ts +24 -11
- package/dist/controllers/theme_controller.js +140 -116
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +55 -5
- package/dist/controllers/time_picker_controller.js +331 -127
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/toast_controller.d.ts +40 -16
- package/dist/controllers/toast_controller.js +244 -324
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.d.ts +14 -6
- package/dist/controllers/toggle_group_controller.js +252 -191
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.d.ts +8 -6
- package/dist/controllers/toolbar_controller.js +219 -120
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +49 -4
- package/dist/controllers/tooltip_controller.js +158 -124
- package/dist/controllers/tooltip_controller.js.map +1 -1
- package/dist/controllers/transition_controller.d.ts +22 -4
- package/dist/controllers/transition_controller.js +123 -119
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +22 -12
- package/dist/controllers/tree_view_controller.js +283 -369
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.js +8573 -10410
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +38 -14
- package/dist/inspector/cli.js +108 -40
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +145 -64
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +20 -20
- package/dist/inspector/manifest.json +802 -101
- package/dist/positioning/index.d.ts +15 -7
- package/dist/positioning/index.js +154 -47
- package/dist/positioning/index.js.map +1 -1
- package/package.json +11 -10
- package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
- package/dist/controllers/reset_before_cache_controller.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/announce.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/controllers/character_counter_controller.ts"],"names":[],"mappings":"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","file":"character_counter_controller.js","sourcesContent":["/**\n * Sends one message to the page's shared `stimeo--announcer`.\n *\n * A component that has to reach assistive tech does not carry a live region of its\n * own: a region only announces what changes *after* assistive tech already knows\n * about it, which a region that appears (or is un-hidden) with its message cannot\n * satisfy. The one region that can is the announcer sitting in the page from the\n * start, so state changes are handed to it as an event and it does the reading.\n *\n * The event goes to `window` because the announcer is usually a sibling high in the\n * document rather than an ancestor of the component dispatching it.\n *\n * Wording comes from the consumer — the library ships no English strings — so an\n * empty message is silently dropped and nothing is announced.\n *\n * @example\n * ```ts\n * announce(this.announceTextValue, { assertive: false });\n * ```\n */\nexport function announce(message: string, options: { assertive?: boolean } = {}): void {\n const text = message.trim();\n if (text.length === 0) return;\n window.dispatchEvent(\n new CustomEvent(\"stimeo--announcer:announce\", {\n detail: { message: text, assertive: options.assertive === true },\n }),\n );\n}\n\n/**\n * Fills `{name}` placeholders in an announcement template from `values`.\n *\n * The same substitution the value-text templates use, so a consumer writes\n * `\"{percent}% complete\"` in one attribute and gets the same rules everywhere. A\n * placeholder with no matching entry is left as authored rather than blanked, which\n * keeps a typo visible instead of silently swallowing the word.\n */\nexport function fillTemplate(template: string, values: Record<string, string | number>): string {\n return template.replace(/\\{([a-zA-Z][a-zA-Z0-9]*)\\}/g, (match, name: string) => {\n const replacement = values[name];\n return replacement === undefined ? match : String(replacement);\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.\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/** Minimal `input` shape needed to tell a composition echo from a fresh edit. */\nexport interface ConfirmedInputSignal {\n readonly target: EventTarget | null;\n readonly inputType?: string;\n}\n\n/**\n * The `inputType` values an engine reports on an `input` that belongs to a\n * composition rather than to an edit the user just made.\n */\nconst COMPOSITION_INPUT_TYPES = new Set([\n \"insertCompositionText\",\n \"insertFromComposition\",\n \"deleteCompositionText\",\n \"deleteByComposition\",\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 * The tracker also owns the other half of that lifecycle: **the `input` some\n * engines send after `compositionend` to echo the text just confirmed.** A\n * consumer that ran `onEnd` and then handled the echo would commit the same\n * confirmation twice, so {@link CompositionTracker.consumesConfirmedInput} tells\n * the echo apart and the consumer returns early on it.\n *\n * **What the echo is not, is the harder half.** Not every engine sends one —\n * Chromium ends a confirmation at `compositionend` with no `input` after it — so\n * a window that waits for the echo and only closes on the next key would swallow\n * the first edit that arrives without one: dictation, autofill, a drop,\n * `insertText`. Two things keep that from happening. The window closes on the\n * next anything — a key, a new composition, any `input`, losing the field — and\n * an `input` that reports an `inputType` outside {@link COMPOSITION_INPUT_TYPES}\n * is an edit, so it is never folded. Only an engine that reports no `inputType`\n * at all is left relying on the window alone.\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 * onInput(event: InputEvent): void {\n * if (this.#composition.consumesConfirmedInput(event)) return;\n * if (this.#composition.isComposing(event)) return;\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 /** The field whose confirming `input` is still owed, while the window is open. */\n #confirmedTarget: EventTarget | null = null;\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 target.addEventListener(\"keydown\", this.#handleKeydown);\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 target.removeEventListener(\"keydown\", this.#handleKeydown);\n this.#activeTargets.delete(target);\n if (this.#confirmedTarget === target) this.#confirmedTarget = null;\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 target.removeEventListener(\"keydown\", this.#handleKeydown);\n }\n this.#observedTargets.clear();\n this.#activeTargets.clear();\n this.#confirmedTarget = null;\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 /**\n * Whether `event` is the `input` echoing the composition just confirmed.\n *\n * Asking closes the window either way, so one confirmation is folded at most\n * once and a consumer asks once per `input`.\n */\n consumesConfirmedInput(event: ConfirmedInputSignal): boolean {\n const confirmed = this.#confirmedTarget;\n this.#confirmedTarget = null;\n if (confirmed === null || confirmed !== event.target) return false;\n // An engine that reports no kind at all leaves `inputType` empty, and the\n // window is then the only signal there is.\n const inputType = event.inputType;\n return !inputType || COMPOSITION_INPUT_TYPES.has(inputType);\n }\n\n readonly #handleStart = (event: Event): void => {\n this.#confirmedTarget = null;\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.#confirmedTarget = event.target;\n this.#onEnd?.(event);\n };\n\n /** A key on an observed field opens an edit of its own, so no echo is owed. */\n readonly #handleKeydown = (): void => {\n this.#confirmedTarget = null;\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 * Largest delay a timer can hold: the platform stores it in a 32-bit signed\n * integer, and anything larger overflows to `1`, so a delay meant to be far in\n * the future fires almost immediately. A declared delay above this bound names\n * no delay at all, and a controller reading one falls back to its default.\n */\nexport const MAX_TIMER_DELAY_MS = 2_147_483_647;\n\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","import { Controller } from \"@hotwired/stimulus\";\nimport { announce, fillTemplate } from \"../utils/announce\";\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 { SafeTimeout } from \"../utils/safe_timeout\";\n\ntype CharacterCounterField = HTMLInputElement | HTMLTextAreaElement;\ntype DisplayMode = \"remaining\" | \"used\" | \"both\";\n\ninterface CharacterCountReading {\n readonly length: number;\n readonly remaining: number | null;\n readonly over: boolean;\n readonly max: number;\n readonly text: string;\n}\n\ntype CharacterCounterDetail = Pick<CharacterCountReading, \"length\" | \"remaining\" | \"over\">;\n\n/**\n * Headless character-counter behavior for a text field (no dedicated APG\n * pattern; follows the WCAG 2.2 \"status messages\" practice, 4.1.3).\n *\n * Markup contract (identifier: `stimeo--character-counter`):\n * <div data-controller=\"stimeo--character-counter\"\n * data-stimeo--character-counter-max-value=\"140\"\n * data-stimeo--character-counter-announce-text-value=\"{remaining} characters remaining\">\n * <textarea data-stimeo--character-counter-target=\"input\"\n * aria-describedby=\"cc\"></textarea>\n * <span id=\"cc\" data-stimeo--character-counter-target=\"output\"></span>\n * </div>\n *\n * Watches the field's UTF-16 code-unit length, writes the remaining/used count\n * into `output`, and toggles the `data-near-limit` / `data-over-limit` state\n * hooks. While over the limit it temporarily leases `aria-invalid=\"true\"` on\n * the field and returns the consumer's authored value on recovery or teardown.\n * The field is the first `input` target, or — when the controller is attached\n * straight onto an `<input>`/`<textarea>` — the controller element itself.\n *\n * `change` and `reconcile` dispatch\n * `{ length: number, remaining: number | null, over: boolean }`.\n *\n * @remarks\n * Behavior only — count text and state update synchronously, with no styling.\n * Confirmed user input dispatches `stimeo--character-counter:change` only when\n * the measured length actually changes. Its detail is `{ length, remaining,\n * over }`; `remaining` is `null` when `max` is disabled. IME intermediate input\n * is ignored, and `compositionend` commits the confirmed value exactly once.\n *\n * Assistive notification is opt-in and i18n-neutral. `announceText` accepts\n * `{count}`, `{length}`, `{remaining}`, `{max}`, and `{over}` placeholders and\n * sends the settled message to the page's shared `stimeo--announcer` after a\n * short debounce. The visible `output` is not itself required to be a live\n * region. Initial reflection and Turbo restoration never dispatch or announce.\n * Runtime target/Value reconciliation dispatches\n * `stimeo--character-counter:reconcile` only when the public derived state\n * changes, and never announces.\n */\nexport class CharacterCounterController extends Controller<HTMLElement> {\n static override targets = [\"input\", \"output\"];\n static override values = {\n max: { type: Number, default: 0 },\n warnAt: { type: Number, default: 0 },\n mode: { type: String, default: \"remaining\" },\n announceText: { type: String, default: \"\" },\n };\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly inputTarget: CharacterCounterField;\n declare readonly outputTarget: HTMLElement;\n declare readonly hasInputTarget: boolean;\n declare readonly hasOutputTarget: boolean;\n\n declare maxValue: number;\n declare warnAtValue: number;\n declare modeValue: string;\n declare announceTextValue: string;\n\n /** Delay (ms) before one settled count is sent to the shared announcer. */\n static readonly #announceDelay = 200;\n\n readonly #timeouts = new SafeTimeout();\n readonly #ariaInvalid = new AttributeLease<CharacterCounterField>(\"aria-invalid\");\n readonly #beforeCache = new BeforeCacheReset(() => this.#rewindForCache());\n readonly #repaint = new MicrotaskCoalescer(() => this.#reconcile(true));\n readonly #composition = new CompositionTracker({\n onEnd: (event) => this.#commitFrom(event.currentTarget),\n });\n #announceId: number | null = null;\n #boundField: CharacterCounterField | null = null;\n #lastLength: number | null = null;\n #lastDetail: CharacterCounterDetail | null = null;\n #reflectedOver: boolean | null = null;\n\n readonly #onInput = (event: Event): void => {\n const field = this.#boundField;\n if (!field || event.currentTarget !== field || this.#field !== field) return;\n // An engine may echo a confirmed composition with one more `input`;\n // committing it again would re-run the reading the commit already took.\n if (this.#composition.consumesConfirmedInput(event)) return;\n if (this.#composition.isComposing(event as InputEvent)) return;\n this.#commit(field);\n };\n\n /** Reflects the current DOM state and opens the mutation-reconciliation window. */\n override connect(): void {\n this.#repaint.activate();\n this.#beforeCache.activate();\n this.#reconcile(false);\n }\n\n /** Releases listeners, timers, borrowed ARIA, and controller-owned state hooks. */\n override disconnect(): void {\n this.#repaint.cancel();\n this.#beforeCache.deactivate();\n this.#cancelAnnouncement();\n this.#bindField(null);\n this.#composition.disconnect();\n this.#clearStateHooks();\n this.#lastLength = null;\n this.#lastDetail = null;\n }\n\n /** Rebinds and repaints after an input target is added or replaced at runtime. */\n inputTargetConnected(): void {\n this.#repaint.schedule();\n }\n\n /** Releases and repaints after an input target is removed or replaced at runtime. */\n inputTargetDisconnected(): void {\n this.#repaint.schedule();\n }\n\n /** Initializes a display target inserted after the controller connected. */\n outputTargetConnected(): void {\n this.#repaint.schedule();\n }\n\n /** Reconciles the optional display target set after a removal or replacement. */\n outputTargetDisconnected(): void {\n this.#repaint.schedule();\n }\n\n /** Repaints when application code or a Turbo morph changes `max`. */\n maxValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Repaints when application code or a Turbo morph changes `warnAt`. */\n warnAtValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Repaints when application code or a Turbo morph changes `mode`. */\n modeValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Rewords a pending announcement with the template the consumer changed it to. */\n announceTextValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Rebinds one mutation batch and reports a changed controller-derived state. */\n #reconcile(report: boolean): void {\n const previous = this.#lastDetail;\n // An edit inside the debounce window has already earned an announcement.\n // Reconciliation never originates one, but it must not swallow that one\n // either: the pending message is retargeted at the settled reading, so the\n // user hears the count that ends up displayed rather than nothing. A\n // replaced field is the exception — its pending message describes a field\n // the reader can no longer reach.\n const owedField = this.#announceId === null ? null : this.#boundField;\n this.#cancelAnnouncement();\n this.#bindField(this.#field);\n if (this.#composition.isComposing()) return;\n const field = this.#boundField;\n if (!field) {\n this.#renderEmpty();\n this.#lastLength = null;\n this.#lastDetail = null;\n return;\n }\n const reading = this.#render(field);\n const detail = this.#detail(reading);\n this.#lastLength = reading.length;\n this.#lastDetail = detail;\n if (owedField === field) this.#scheduleAnnouncement(reading);\n if (report && previous && this.#detailsDiffer(previous, detail)) {\n this.dispatch(\"reconcile\", { detail });\n }\n }\n\n /** Commits a composition only when it came from the field still owned here. */\n #commitFrom(target: EventTarget | null): void {\n const field = this.#boundField;\n if (!field || target !== field || this.#field !== field) return;\n this.#commit(field);\n }\n\n /** Reflects one confirmed user input and reports only a real length transition. */\n #commit(field: CharacterCounterField): void {\n const reading = this.#render(field);\n const previousLength = this.#lastLength;\n const previousDetail = this.#lastDetail;\n const detail = this.#detail(reading);\n this.#lastLength = reading.length;\n this.#lastDetail = detail;\n if (previousLength === reading.length) {\n if (previousDetail && this.#detailsDiffer(previousDetail, detail)) {\n this.dispatch(\"reconcile\", { detail });\n }\n return;\n }\n\n this.dispatch(\"change\", { detail });\n this.#scheduleAnnouncement(reading);\n }\n\n /** Selects the public event state from the richer internal reading. */\n #detail(reading: CharacterCountReading): CharacterCounterDetail {\n return {\n length: reading.length,\n remaining: reading.remaining,\n over: reading.over,\n };\n }\n\n /** Compares exactly the state carried by `change` and `reconcile`. */\n #detailsDiffer(left: CharacterCounterDetail, right: CharacterCounterDetail): boolean {\n return (\n left.length !== right.length || left.remaining !== right.remaining || left.over !== right.over\n );\n }\n\n /**\n * Synchronizes visible count, state hooks, and temporary validation ARIA.\n *\n * @stimeoRenderRoot\n */\n #render(field: CharacterCounterField): CharacterCountReading {\n const length = field.value.length;\n const max = this.#normalizeCount(this.maxValue);\n const warnAt = this.#normalizeCount(this.warnAtValue);\n const remaining = max > 0 ? max - length : null;\n const over = remaining !== null && remaining < 0;\n const near = remaining !== null && warnAt > 0 && !over && remaining <= warnAt;\n\n this.#toggle(\"data-over-limit\", over);\n this.#toggle(\"data-near-limit\", near);\n this.#reflectInvalid(field, over);\n\n const text = this.#format(length, remaining, max);\n this.#writeOutput(text);\n return { length, remaining, over, max, text };\n }\n\n /** Clears derived output when the declarative input set has no usable field. */\n #renderEmpty(): void {\n this.#ariaInvalid.returnAll();\n this.#reflectedOver = null;\n this.#clearStateHooks();\n this.#writeOutput(\"\");\n }\n\n /** Replaces the observed field symmetrically, returning state from the old one. */\n #bindField(field: CharacterCounterField | null): void {\n if (field === this.#boundField) return;\n\n const previous = this.#boundField;\n if (previous) {\n previous.removeEventListener(\"input\", this.#onInput);\n this.#composition.unobserve(previous);\n this.#ariaInvalid.return(previous);\n }\n\n this.#boundField = field;\n this.#lastLength = null;\n this.#reflectedOver = null;\n if (!field) return;\n\n field.addEventListener(\"input\", this.#onInput);\n this.#composition.observe(field);\n }\n\n /** Leases `aria-invalid` only on the edge into over-limit, then returns it. */\n #reflectInvalid(field: CharacterCounterField, over: boolean): void {\n if (this.#reflectedOver === over) return;\n this.#reflectedOver = over;\n if (over) this.#ariaInvalid.write(field, \"true\");\n else this.#ariaInvalid.return(field);\n }\n\n /** Builds the visible count for the normalized display mode. */\n #format(length: number, remaining: number | null, max: number): string {\n if (remaining === null) return String(length);\n switch (this.#mode) {\n case \"used\":\n return String(length);\n case \"both\":\n return `${length}/${max}`;\n default:\n return String(remaining);\n }\n }\n\n /**\n * Debounces one i18n-neutral message into the shared polite announcer.\n *\n * @stimeoRuntimeOnly `announceText` is the template of the one announcement this call schedules;\n * the count is painted by the marked renderer.\n */\n #scheduleAnnouncement(reading: CharacterCountReading): void {\n this.#cancelAnnouncement();\n const message = fillTemplate(this.announceTextValue, {\n count: reading.text,\n length: reading.length,\n remaining: reading.remaining ?? \"\",\n max: reading.max,\n over: String(reading.over),\n });\n if (message.trim().length === 0) return;\n\n this.#announceId = this.#timeouts.set(() => {\n announce(message);\n this.#announceId = null;\n }, CharacterCounterController.#announceDelay);\n }\n\n /** Cancels the one outstanding announcement without touching visible output. */\n #cancelAnnouncement(): void {\n if (this.#announceId !== null) this.#timeouts.clear(this.#announceId);\n this.#announceId = null;\n }\n\n /** Writes the optional display only when its text actually changed. */\n #writeOutput(text: string): void {\n if (!this.hasOutputTarget || this.outputTarget.textContent === text) return;\n this.outputTarget.textContent = text;\n }\n\n /** Reflects a presence-style state hook without redundant attribute writes. */\n #toggle(name: string, on: boolean): void {\n if (on) {\n if (this.element.getAttribute(name) !== \"true\") this.element.setAttribute(name, \"true\");\n } else if (this.element.hasAttribute(name)) {\n this.element.removeAttribute(name);\n }\n }\n\n /** Removes both state hooks owned by this controller. */\n #clearStateHooks(): void {\n this.#toggle(\"data-over-limit\", false);\n this.#toggle(\"data-near-limit\", false);\n }\n\n /** Returns borrowed ARIA and transient hooks before Turbo snapshots the page. */\n #rewindForCache(): void {\n this.#cancelAnnouncement();\n this.#ariaInvalid.returnAll();\n this.#reflectedOver = null;\n this.#clearStateHooks();\n }\n\n /** Converts a public count Value into a finite non-negative integer. */\n #normalizeCount(raw: number): number {\n if (!Number.isFinite(raw)) return 0;\n return Math.max(0, Math.trunc(raw));\n }\n\n /** Falls back to `remaining` when an authored display mode is unknown. */\n get #mode(): DisplayMode {\n if (this.modeValue === \"used\" || this.modeValue === \"both\") return this.modeValue;\n return \"remaining\";\n }\n\n /** The watched field: the first target, or a directly controlled form field. */\n get #field(): CharacterCounterField | null {\n if (this.hasInputTarget) return this.inputTarget;\n const element: HTMLElement = this.element;\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)\n return element;\n return null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/template.ts","../../src/utils/announce.ts","../../src/utils/attribute_write.ts","../../src/utils/shared_registry.ts","../../src/utils/attribute_lease.ts","../../src/utils/composition_tracker.ts","../../src/utils/listener_set.ts","../../src/utils/microtask_coalescer.ts","../../src/utils/morph_render_watcher.ts","../../src/utils/number_bounds.ts","../../src/utils/coerce.ts","../../src/utils/number_value.ts","../../src/utils/safe_timeout.ts","../../src/controllers/character_counter_controller.ts"],"names":["registry"],"mappings":"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","file":"character_counter_controller.js","sourcesContent":["/**\n * Fills `{name}` placeholders in a localized template from the own entries of `values`.\n *\n * Announcement and value-text templates share this one substitution, so a consumer writes\n * `\"{percent}% complete\"` in one attribute and gets the same rules everywhere. A\n * placeholder with no matching entry is left as authored rather than blanked, which\n * keeps a typo visible instead of silently swallowing the word.\n * Every occurrence is filled in one pass. Inserted strings stay literal, including\n * replacement-pattern characters and text that resembles another placeholder.\n */\nexport function fillTemplate(template: string, values: Record<string, string | number>): string {\n return template.replace(/\\{([a-zA-Z][a-zA-Z0-9]*)\\}/g, (match, name: string) => {\n const replacement = Object.hasOwn(values, name) ? values[name] : undefined;\n return replacement === undefined ? match : String(replacement);\n });\n}\n","export { fillTemplate } from \"./template\";\n\n/**\n * Sends one message to the page's shared `stimeo--announcer`.\n *\n * A message that has to reach assistive tech is not put into a live region created\n * or un-hidden along with it: a region only announces what changes *after* assistive\n * tech already knows about it, which such a region cannot satisfy. The announcer has\n * to be in the page before any message is handed to it — one sent while no announcer\n * is listening is not read — so state changes reach it as an event and it does the\n * reading.\n *\n * The event goes to `window` because the announcer is usually a sibling high in the\n * document rather than an ancestor of the component dispatching it.\n *\n * Wording comes from the consumer — this helper adds no text of its own — so an\n * empty message is silently dropped and nothing is announced.\n *\n * @example\n * ```ts\n * announce(this.announceTextValue, { assertive: false });\n * ```\n */\nexport function announce(message: string, options: { assertive?: boolean } = {}): void {\n const text = message.trim();\n if (text.length === 0) return;\n window.dispatchEvent(\n new CustomEvent(\"stimeo--announcer:announce\", {\n detail: { message: text, assertive: options.assertive === true },\n }),\n );\n}\n","/**\n * Reflects a serialized attribute value only when the current value differs.\n *\n * A same-value `setAttribute` still queues a mutation record for every observer, so an\n * unchanged value writes nothing.\n *\n * @param element - The element whose attribute is reflected.\n * @param name - The attribute name, using the non-namespaced DOM API.\n * @param value - The serialized value, or null to remove the attribute.\n * @param beforeWrite - Called only for a change, before the DOM mutation, so the\n * caller can record ownership or identify its own observer records.\n * @returns Whether an attribute was written or removed.\n */\nexport function setAttributeIfChanged(\n element: Element,\n name: string,\n value: string | null,\n beforeWrite?: () => void,\n): boolean {\n if (element.getAttribute(name) === value) return false;\n beforeWrite?.();\n if (value === null) element.removeAttribute(name);\n else element.setAttribute(name, value);\n return true;\n}\n","/**\n * One registry per page for every copy of the library.\n *\n * Each `stimeo-ui/controllers/*` file, and each opt-in entry, is built on its own and carries\n * its own copy of every utility it uses, so a page that imports controllers one by one, or one\n * of them next to the barrel, evaluates a utility several times. A registry that coordinates\n * instances of different controllers — the stacks of leased values, the loans of a\n * `tabindex`, the Escape layers, the focus traps — must not be split by that: a dialog inside\n * a drawer, or a character counter and a form field on one input, coordinate whichever files\n * they came from. So such a registry lives once on `globalThis`, under a `Symbol.for` key the\n * copies agree on, and the first copy to ask for it creates it.\n *\n * The key names the registry and the version of its shape\n * (`stimeo-ui.<utility>.registry.v<n>`). Copies whose registries have the same shape share\n * one; a release that changes the shape changes the version, so a copy of another release\n * keeps a registry of its own instead of reading entries it does not understand — the two\n * then coordinate within each release only. An entry another copy put in a registry is read\n * through its fields alone, never through `#private` members, which belong to the class of\n * the copy that created it.\n */\n\n/**\n * The registry stored under `key`, created by `create` on first use.\n *\n * @param key - `stimeo-ui.<utility>.registry.v<n>`: the version is that of the shape `create`\n * returns.\n * @param create - Builds the empty registry.\n */\nexport function sharedRegistry<T extends object>(key: string, create: () => T): T {\n const symbol = Symbol.for(key);\n const scope = globalThis as unknown as Record<symbol, T | undefined>;\n const existing = scope[symbol];\n if (existing !== undefined) return existing;\n const registry = create();\n Object.defineProperty(globalThis, symbol, { value: registry });\n return registry;\n}\n","import { setAttributeIfChanged } from \"./attribute_write\";\nimport { sharedRegistry } from \"./shared_registry\";\n\n/** What a lease's record says: the author's value, its last write, the leases beneath. */\ninterface AttributeLeaseRecord {\n readonly original: string | null;\n readonly written: string | null;\n /** Whether it hands back what the lease right beneath it wrote last. */\n readonly linked: boolean;\n /** The records of the other owners' leases beneath it, nearest first. */\n readonly beneath: readonly string[];\n}\n\n/** One lease's hold on one element's attribute, in the stack every lease of it shares. */\ninterface AttributeHold {\n /** The lease holding it; `null` for a hold read from a copy's record until its lease takes it. */\n lease: object | null;\n readonly record: string;\n written: string | null;\n /** What it hands back with nothing beneath it: the author's value. */\n readonly original: string | null;\n /** Whether it hands back what the hold beneath it wrote last instead. */\n linked: boolean;\n}\n\n/** The holds on each element by attribute, and every lease's record name by attribute. */\ninterface AttributeLeaseRegistry {\n readonly stacks: WeakMap<Element, Map<string, AttributeHold[]>>;\n readonly names: Map<string, Set<string>>;\n}\n\n/** Holds and record names coordinate across separately built package entries. */\nconst registry = sharedRegistry(\n \"stimeo-ui.attribute-lease.registry.v1\",\n (): AttributeLeaseRegistry => ({ stacks: new WeakMap(), names: new Map() }),\n);\n\n/** Whether a parsed record entry is an attribute value: a string, or `null` for absence. */\nfunction isAttributeValue(value: unknown): value is string | null {\n return value === null || typeof value === \"string\";\n}\n\n/**\n * Reads the record a lease left on `element`: the author's value, the value the lease wrote\n * last, whether it hands back the value beneath it (`false` before the names when it does not)\n * and the records beneath it. `undefined` when the record is missing or holds anything else.\n */\nfunction readLeaseRecord(element: Element, record: string): AttributeLeaseRecord | undefined {\n try {\n const parsed: unknown = JSON.parse(element.getAttribute(record) ?? \"null\");\n if (!Array.isArray(parsed)) return undefined;\n const [original, written, ...rest] = parsed as unknown[];\n const linked = rest[0] !== false;\n const beneath = linked ? rest : rest.slice(1);\n if (!beneath.every((under): under is string => typeof under === \"string\")) return undefined;\n return isAttributeValue(original) && isAttributeValue(written)\n ? { original, written, linked, beneath }\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The element's stack, seeded from complete ownership records once. */\nfunction attributeStack(element: Element, attribute: string): AttributeHold[] {\n const byAttribute = registry.stacks.get(element) ?? new Map<string, AttributeHold[]>();\n registry.stacks.set(element, byAttribute);\n const known = byAttribute.get(attribute);\n if (known) return known;\n const found: (AttributeLeaseRecord & { readonly record: string })[] = [];\n for (const record of registry.names.get(attribute) ?? []) {\n const read = readLeaseRecord(element, record);\n if (read) found.push({ ...read, record });\n }\n const depth = ({ beneath }: (typeof found)[number]) =>\n beneath.filter((name) => found.some((other) => other.record === name)).length;\n const stack = found\n .sort((one, other) => depth(one) - depth(other))\n .map(({ record, written, original, linked }, index) => ({\n lease: null,\n record,\n written,\n original,\n linked: linked && index > 0,\n }));\n byAttribute.set(attribute, stack);\n return stack;\n}\n\n/** The lease's live hold or the unclaimed hold described by its owner's record. */\nfunction findHold(\n stack: readonly AttributeHold[],\n lease: object,\n record: string,\n): AttributeHold | undefined {\n return (\n stack.find((held) => held.lease === lease) ??\n stack.find((held) => held.lease === null && held.record === record)\n );\n}\n\n/**\n * Inspects a derived writer's continuation without acquiring or returning a hold.\n * A covered hold may update beneath its cover. Without a hold, the expected authored\n * value is compared with the original beneath any temporary cover. The original\n * distinguishes an absent attribute from an empty one.\n */\nexport function readAttributeLease(\n element: Element,\n attribute: string,\n owner: string,\n lease: object,\n expected: string | null,\n): { readonly allowed: boolean; readonly original: string | null } {\n const stack = attributeStack(element, attribute);\n const hold = findHold(stack, lease, `data-${owner}-${attribute}-lease`);\n const current = element.getAttribute(attribute);\n const covering = [...stack].reverse().find((other) => other.written === current);\n const original = (hold ?? covering)?.original;\n const authored = original === undefined ? current : original;\n return {\n original: authored,\n allowed: hold\n ? current === hold.written ||\n stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current)\n : authored === expected,\n };\n}\n\n/**\n * The value `element`'s author wrote for `attribute`, as the record a lease of any owner leaves\n * on the element carries it; `undefined` while no lease leaves one, as when nothing has moved\n * the attribute off the author's value. A field a reveal turned from `password` into `text`\n * still reads `\"password\"` here.\n */\nexport function leasedAuthorValue(element: Element, attribute: string): string | null | undefined {\n const suffix = `-${attribute}-lease`;\n for (const name of element.getAttributeNames()) {\n if (!name.startsWith(\"data-\") || !name.endsWith(suffix)) continue;\n const record = readLeaseRecord(element, name);\n if (record) return record.original;\n }\n return undefined;\n}\n\n/**\n * Temporarily controls one attribute across a changing set of elements.\n *\n * The first write remembers the authored value, including the distinction between\n * an absent attribute and an authored empty string. Returning a lease restores that\n * value only while the attribute still matches the controller's last write. If a\n * consumer changed it in the meantime, the consumer owns the new value and teardown\n * leaves it alone.\n *\n * A `null` write deliberately removes the attribute while retaining the lease. This\n * is useful for derived ARIA whose valid absence is itself controller state, such as\n * an unbounded `aria-valuemin` or a blank spinbutton's `aria-valuenow`.\n *\n * **Every lease of an attribute shares one stack of holds per element**, whatever its owner\n * and whichever file of the package constructed it (the stacks are one per page): the holds\n * sit in the order their leases first wrote the element, each with the value it wrote last.\n * The element's value is the highest hold's that carries it, and the page's when none does.\n * A write reaches the element unless a hold above the writer carries the element's value: the\n * top hold always shows its writes, a hold beneath it shows nothing while a hold above keeps\n * its value on the element, and once the page has put a value there that no hold carries, the\n * next write of any hold replaces it. A return gives a value back only from the hold the\n * element's value is: the value the hold beneath it wrote last, or the author's once nothing\n * is beneath it; any other return only leaves the stack, and the page's value stays. Holds\n * that wrote the same value are told apart by the stack, never by the value: the higher one\n * keeps it. A first write over a top hold whose value the page has replaced takes the\n * element's value as the author's. Two instances of one controller on one element — an\n * element outside their scope — stack the same way.\n *\n * A **base lease** (`{ base: true }`) holds the element's own state rather than a value over\n * it — a form field's ARIA on its control is one — so its first write goes to the bottom of\n * the stack, beneath the leases of other owners already there: a temporary value another\n * owner leased stays shown and returns to the base lease's latest value.\n *\n * **The stack travels with the element.** While a hold shows a value other than the author's,\n * lies on another hold or is covered by one, the element carries its owner's record\n * `data-<owner>-<attribute>-lease`: JSON of the author's value and the value the hold wrote\n * last (each a string, or `null` for an absent attribute), `false` where the hold hands back\n * the author's value rather than the latest value of the hold beneath it, and the records of\n * every hold beneath it, nearest first. Returning the last lease of an owner removes its\n * record. A copy of the element — a page Turbo restores from its cache is one — therefore\n * carries the stack, and the first lease to touch the copy reads it back under the record\n * names of the leases constructed so far, which include every lease that wrote a record the\n * cache holds, and orders the holds by the records each one lists beneath it. Each lease takes\n * the hold its owner's record describes over in place. Complete records for distinct owners\n * preserve their order across a copy. The records describe holds by owner, not by instance:\n * one owner holding the element more than once leaves only its topmost hold's record, which\n * the first of its leases to write or return on the copy takes. Lower holds of that owner and\n * their positions are absent; mutually listed owners cannot express their full live order.\n * A hold that showed the author's value alone carries no record and is taken by its first\n * write on the copy. Missing or unreadable records also leave their holds unknown, so copying\n * the DOM does not promise identical decisions for every live stack. Without a record it can\n * read, a new stack takes the current value as the author's. A Turbo morph removes records\n * absent from the server HTML; existing holds remain in memory until their leases return.\n *\n * The lease has no lifecycle of its own, so it never subscribes to document events,\n * and nothing rewinds a live page before Turbo caches it: `turbo:before-cache` also\n * fires on pages that stay.\n */\nexport class AttributeLease<T extends Element = Element> {\n readonly #attribute: string;\n readonly #record: string;\n readonly #base: boolean;\n readonly #preserveAuthor: boolean;\n readonly #held = new Set<T>();\n\n /**\n * @param attribute - The attribute whose temporary values this lease owns.\n * @param owner - Names the record on the element; the controller's identifier.\n * @param options - `base`: written beneath the other owners' leases;\n * `preserveAuthor`: a new base hold keeps a current value that no hold carries as authored.\n */\n constructor(\n attribute: string,\n owner: string,\n options: { readonly base?: boolean; readonly preserveAuthor?: boolean } = {},\n ) {\n this.#attribute = attribute;\n this.#record = `data-${owner}-${attribute}-lease`;\n this.#base = options.base === true;\n this.#preserveAuthor = options.preserveAuthor === true;\n const names = registry.names;\n names.set(attribute, (names.get(attribute) ?? new Set<string>()).add(this.#record));\n }\n\n /** Writes or removes the leased attribute while preserving its authored value. */\n write(element: T, value: string | null): void {\n const stack = attributeStack(element, this.#attribute);\n const hold = this.#take(stack) ?? this.#acquire(element, stack);\n this.#held.add(element);\n const shows = !this.#covered(element, stack, hold);\n hold.written = value;\n this.#mark(element, stack);\n if (shows) this.#reflect(element, value);\n }\n\n /**\n * Returns one lease, also on a restored copy, to the value the hold beneath it wrote last or\n * the author's, without overwriting a value a consumer wrote since. Says whether there was a\n * lease to return: a hold this lease has, or the hold a copy's record describes while no live\n * lease of the owner has taken it — a copy of a page an earlier connection wrote carries one.\n */\n return(element: T): boolean {\n const held = this.#held.delete(element);\n const known = registry.stacks.get(element)?.has(this.#attribute);\n const stack =\n held || known || element.hasAttribute(this.#record)\n ? attributeStack(element, this.#attribute)\n : [];\n const hold = this.#take(stack);\n if (!hold) return false;\n const carries = element.getAttribute(this.#attribute) === hold.written;\n const owns = carries && !this.#covered(element, stack, hold);\n const index = stack.indexOf(hold);\n stack.splice(index, 1);\n const above = stack[index];\n if (above) above.linked &&= hold.linked;\n this.#mark(element, stack);\n if (!owns) return true;\n const below = hold.linked ? stack[index - 1] : undefined;\n this.#reflect(element, below ? below.written : hold.original);\n return true;\n }\n\n /** Returns every lease it holds, with the same ownership check as {@link return}. */\n returnAll(): void {\n for (const element of Array.from(this.#held)) this.return(element);\n }\n\n /** Its hold in `stack`, taking over one read from its record. */\n #take(stack: AttributeHold[]): AttributeHold | undefined {\n const hold = findHold(stack, this, this.#record);\n if (hold) hold.lease = this;\n return hold;\n }\n\n /** A new hold: on top, over the top hold while the element shows it; a base one at the bottom. */\n #acquire(element: T, stack: AttributeHold[]): AttributeHold {\n const current = element.getAttribute(this.#attribute);\n const top = stack.at(-1);\n const bottom = stack[0];\n const over = top?.written === current ? top : undefined;\n const from = this.#base\n ? this.#preserveAuthor && !stack.some((held) => held.written === current)\n ? undefined\n : bottom\n : over;\n const hold: AttributeHold = {\n lease: this,\n record: this.#record,\n written: current,\n original: from ? from.original : current,\n linked: !this.#base && over !== undefined,\n };\n if (this.#base && bottom) {\n bottom.linked = true;\n stack.unshift(hold);\n } else stack.push(hold);\n return hold;\n }\n\n /** Whether a hold above `hold` carries the element's value, which is then that hold's. */\n #covered(element: T, stack: readonly AttributeHold[], hold: AttributeHold): boolean {\n const current = element.getAttribute(this.#attribute);\n return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);\n }\n\n /** Leaves each owner's record of its topmost hold, or none where nothing needs one. */\n #mark(element: T, stack: readonly AttributeHold[]): void {\n const records = new Map<string, string | null>([[this.#record, null]]);\n stack.forEach((hold, index) => {\n const names = stack.slice(0, index).map((under) => under.record);\n const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);\n const marker = hold.linked || beneath.length === 0 ? [] : [false];\n records.set(\n hold.record,\n hold.written === hold.original && beneath.length === 0 && index === stack.length - 1\n ? null\n : JSON.stringify([hold.original, hold.written, ...marker, ...beneath]),\n );\n });\n for (const [name, recorded] of records) {\n setAttributeIfChanged(element, name, recorded);\n }\n }\n\n /** Reflects only a real value transition, avoiding self-triggered mutation work. */\n #reflect(element: T, value: string | null): void {\n setAttributeIfChanged(element, this.#attribute, value);\n }\n}\n","/** Minimal event shape carrying the platform's per-event composition signal. */\nexport interface CompositionSignal {\n readonly isComposing?: boolean;\n}\n\n/** Minimal `input` shape needed to tell a composition echo from a fresh edit. */\nexport interface ConfirmedInputSignal {\n readonly target: EventTarget | null;\n readonly inputType?: string;\n}\n\n/**\n * The `inputType` values an engine reports on an `input` that belongs to a\n * composition rather than to an edit the user just made.\n */\nconst COMPOSITION_INPUT_TYPES = new Set([\n \"insertCompositionText\",\n \"insertFromComposition\",\n \"deleteCompositionText\",\n \"deleteByComposition\",\n]);\n\n/** Whether a platform input kind belongs to composition rather than ordinary editing. */\nexport function isCompositionInputType(inputType: string | undefined): boolean {\n return inputType !== undefined && COMPOSITION_INPUT_TYPES.has(inputType);\n}\n\n/** The cancelable notice Turbo dispatches before a morph writes one attribute. */\nconst BEFORE_MORPH_ATTRIBUTE = \"turbo:before-morph-attribute\";\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 * Runs once lifecycle state is cleared for a composition that ended without\n * `compositionend`, with the `element` it ran in. Nothing was confirmed: the\n * element holds what a write left (`inPlace` false), or still holds the text the\n * composition left, which the engine stopped composing (`inPlace` true) — text\n * typed against whatever the page declared while it ran.\n *\n * A hook applies the work the composition held back — and only that — at once,\n * keeping the caret where it was. The event that showed the end is then handled as\n * it would be with no composition: the text the element holds is read by whatever\n * reads it next, as the user's edit if an edit reads it. A consumer whose contract\n * judges what an interrupted conversion leaves may also settle that text here, as\n * `stimeo--otp` returns a residual its `pattern` rejects to the prior character: it reports\n * that as a reconciliation, never as the user's edit, and keeps the selection.\n *\n * When the tracker sees the end in an event it hears — a key, an edit, a focus\n * change, the next `compositionstart` — the hook runs there, in the capture phase,\n * ahead of that event's own handlers and of the edit it announces, whoever\n * dispatched it. When a question ({@link CompositionTracker.isComposing},\n * {@link CompositionTracker.composingElement}) or a Turbo morph's notice for one\n * attribute shows the end, the hook runs in a microtask after them, never inside\n * its caller or a half-applied morph, unless an event the tracker hears comes\n * first. On `compositionstart` it runs after the new composition is set and before\n * `onStart`: {@link CompositionTracker.isComposing} is true again, so work held for\n * the old composition stays held for the new.\n */\n readonly onAbandon?: (element: EventTarget, inPlace: boolean) => void;\n}\n\n/** One composition in progress. */\ninterface Composition {\n /** The observed target the composition was heard on. */\n readonly target: EventTarget;\n /** The element composing: the observed field itself, or a field inside an observed ancestor. */\n readonly element: EventTarget;\n /** The value the composition last left in the element; `undefined` for an element with none. */\n text: unknown;\n}\n\n/**\n * The element's live value; `undefined` for an element without one, which a write never\n * changes.\n */\nconst textOf = (element: EventTarget): unknown => (element as { value?: unknown }).value;\n\n/** Whether `element` is the focused element of the document or shadow root it is in. */\nconst holdsFocus = (element: EventTarget): boolean =>\n element instanceof Node &&\n (element.getRootNode() as Partial<DocumentOrShadowRoot>).activeElement === element;\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 * The tracker also owns the other half of that lifecycle: **the `input` some\n * engines send after `compositionend` to echo the text just confirmed.** A\n * consumer that ran `onEnd` and then handled the echo would commit the same\n * confirmation twice, so {@link CompositionTracker.consumesConfirmedInput} tells\n * the echo apart and the consumer returns early on it.\n *\n * **What the echo is not, is the harder half.** Not every engine sends one —\n * Chromium ends a confirmation at `compositionend` with no `input` after it — so\n * a window that waits for the echo and only closes on the next key would swallow\n * the first edit that arrives without one: dictation, autofill, a drop,\n * `insertText`. Two things keep that from happening. The window closes on the\n * next anything — a key, a new composition, any `input`, losing the field — and\n * an `input` that reports an `inputType` outside {@link COMPOSITION_INPUT_TYPES}\n * is an edit, so it is never folded. Only an engine that reports no `inputType`\n * at all is left relying on the window alone.\n *\n * **A composition can also end without `compositionend`.** Chromium drops the\n * conversion silently when something other than the IME writes a different value\n * into its field — a Turbo morph, a form reset, a script — and when the field\n * moves or leaves the page, leaving the text it composed. The tracker reads the end\n * from what the engine and the field still say:\n *\n * - **The field holds other text than the composition left.** The IME's edits, and\n * the user's own between them, arrive as an `input` the engine dispatched\n * (`isTrusted`) or one that reports the composition, and the tracker takes the\n * field's text from those. A write by anything else changes the text with no such\n * `input` — at most a synthetic one — so the composition is over, ended with\n * {@link CompositionTrackerOptions.onAbandon}, before anyone acts on the field.\n * Writing the same text keeps the conversion, and the match.\n * - **The engine edits outside a composition.** A `beforeinput` reporting\n * `isComposing: false` with an `inputType` outside {@link COMPOSITION_INPUT_TYPES}\n * is an edit the engine no longer counts as composition — unless the `keydown`\n * right before it reported `isComposing: true`: a key the IME lets through, such\n * as Backspace, edits the field while the conversion goes on. This is what shows\n * a composition that ended with its text in place. Only one field composes at a\n * time, so such an edit on any observed target ends the composition held, with\n * `onAbandon`. A `keydown` can hold this back but never starts it: the keydown\n * that confirms a conversion may carry no `isComposing`, and dictation and\n * autofill edit with no key at all.\n * - **The field stays where it was heard.** A field the consumer observes itself is\n * the consumer's to release when it moves or leaves, which reads what it holds;\n * one that keeps focus through the move keeps composing\n * ({@link CompositionTracker.disconnect}). A field inside an observed ancestor\n * that leaves the ancestor, or loses focus within its document, ends its\n * composition quietly; one that stays the document's active element — the window\n * lost focus — keeps composing.\n * - **No other field composes**: a `compositionstart` ends any composition the\n * tracker still holds, with `onAbandon`, before the new one starts.\n *\n * The tracker checks this before it answers {@link CompositionTracker.isComposing}\n * or {@link CompositionTracker.composingElement}, and at every key, edit, blur,\n * `compositionstart` and morph it hears — keys, edits and blurs in the capture\n * phase, ahead of the consumer's own handlers. While\n * a composition is live, a Turbo morph leaves its field's value alone: Idiomorph\n * asks through `turbo:before-morph-attribute` before it writes `value`, as an\n * attribute or as the live text, and the tracker cancels that one notice for the\n * element composing, so the morph keeps the conversion, as it keeps focus. Every\n * other attribute, and every other element, still morphs.\n *\n * A consumer that observes several fields tells the conversion's own events from\n * edits in the other fields with {@link CompositionTracker.owns}, which holds even\n * while the tracker keeps a composition whose end no event has shown yet.\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 * onInput(event: InputEvent): void {\n * if (this.#composition.consumesConfirmedInput(event)) return;\n * if (this.#composition.isComposing(event)) return;\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 /** The composition in progress, if any: only one field composes at a time. */\n #composition: Composition | null = null;\n readonly #onStart: ((event: Event) => void) | undefined;\n readonly #onEnd: ((event: Event) => void) | undefined;\n readonly #onAbandon: ((element: EventTarget, inPlace: boolean) => void) | undefined;\n /** The field whose confirming `input` is still owed, while the window is open. */\n #confirmedTarget: EventTarget | null = null;\n /**\n * Whether the last `keydown` reported a composition, until the `beforeinput`\n * after it: the edit that key announces lands inside the composition.\n */\n #keyComposing = false;\n /** Whether the consumer is connected: from `observe()` until `disconnect()`. */\n #connected = false;\n /** A composition that ended without `compositionend` and whose `onAbandon` has not run yet. */\n #abandoned: { readonly element: EventTarget; readonly inPlace: boolean } | null = null;\n\n constructor(options: CompositionTrackerOptions = {}) {\n this.#onStart = options.onStart;\n this.#onEnd = options.onEnd;\n this.#onAbandon = options.onAbandon;\n }\n\n /**\n * Starts lifecycle tracking for `target`; repeated calls are idempotent. The\n * targets one tracker observes do not contain one another: a composition event\n * reaching two of them would be counted as two.\n */\n observe(target: EventTarget): void {\n this.#connected = true;\n if (this.#observedTargets.has(target)) return;\n target.addEventListener(\"compositionstart\", this.#handleStart);\n target.addEventListener(\"compositionend\", this.#handleEnd);\n target.addEventListener(\"keydown\", this.#handleKeydown, true);\n target.addEventListener(\"beforeinput\", this.#handleBeforeInput, true);\n target.addEventListener(\"input\", this.#handleInput, true);\n target.addEventListener(\"blur\", this.#handleBlur, true);\n target.addEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);\n this.#observedTargets.add(target);\n }\n\n /**\n * Stops tracking one target. A composition it held ends quietly, unless its element\n * still holds focus — see {@link CompositionTracker.disconnect}.\n */\n unobserve(target: EventTarget): void {\n if (!this.#observedTargets.delete(target)) return;\n this.#release(target);\n if (this.#composition?.target === target) this.#letGo();\n if (this.#confirmedTarget === target) this.#confirmedTarget = null;\n }\n\n /**\n * Releases every listener and clears state so reconnect starts cleanly.\n *\n * A composition whose element still holds focus is the exception. A move that\n * keeps focus — `moveBefore`, which Turbo's morph uses where the browser provides\n * it — can leave the conversion running, and Stimulus releases the moved target, or\n * the controller around it, and observes it again within the one mutation batch. So\n * the composition waits for its target to be observed again before the turn ends,\n * and goes on; otherwise it ends then — quietly once disconnected, and with\n * {@link CompositionTrackerOptions.onAbandon} for a consumer that only let that one\n * target go. A move without `moveBefore`, or a removal, takes focus away.\n */\n disconnect(): void {\n this.#connected = false;\n for (const target of this.#observedTargets) this.#release(target);\n this.#observedTargets.clear();\n this.#letGo();\n this.#confirmedTarget = null;\n this.#keyComposing = false;\n this.#abandoned = null;\n }\n\n /**\n * True when a composition is live or the current event reports one. A\n * composition that ended without `compositionend` ends here first.\n */\n isComposing(event?: CompositionSignal): boolean {\n this.#settle();\n return event?.isComposing === true || this.#composition !== null;\n }\n\n /**\n * The element a live composition is running in, or `null`. A composition that\n * ended without `compositionend` ends here first.\n */\n composingElement(): EventTarget | null {\n this.#settle();\n return this.#composition?.element ?? null;\n }\n\n /**\n * Whether `event` belongs to a composition: it reports one, or it is in the element a\n * live composition runs in. An event in another element — a key there, or a script's\n * write reported with a bare `input` — is an edit outside the composition, even while\n * the tracker holds one whose end it has not seen: only one element composes at a\n * time, and the IME edits nothing else. The composition held stays, since such an\n * event does not show its end. A consumer that observes several fields asks this of\n * each event; {@link CompositionTracker.isComposing} asks of the targets as a whole.\n * A composition that ended without `compositionend` ends here first.\n */\n owns(event: CompositionSignal & { readonly target: EventTarget | null }): boolean {\n const element = this.composingElement();\n return event.isComposing === true || (element !== null && element === event.target);\n }\n\n /**\n * Whether `event` is the `input` echoing the composition just confirmed.\n *\n * Asking closes the window either way, so one confirmation is folded at most\n * once and a consumer asks once per `input`.\n */\n consumesConfirmedInput(event: ConfirmedInputSignal): boolean {\n const confirmed = this.#confirmedTarget;\n this.#confirmedTarget = null;\n if (confirmed === null || confirmed !== event.target) return false;\n // An engine that reports no kind at all leaves `inputType` empty, and the\n // window is then the only signal there is.\n const inputType = event.inputType;\n return !inputType || isCompositionInputType(inputType);\n }\n\n /** Removes every listener {@link CompositionTracker.observe} added to `target`. */\n #release(target: EventTarget): void {\n target.removeEventListener(\"compositionstart\", this.#handleStart);\n target.removeEventListener(\"compositionend\", this.#handleEnd);\n target.removeEventListener(\"keydown\", this.#handleKeydown, true);\n target.removeEventListener(\"beforeinput\", this.#handleBeforeInput, true);\n target.removeEventListener(\"input\", this.#handleInput, true);\n target.removeEventListener(\"blur\", this.#handleBlur, true);\n target.removeEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);\n }\n\n /**\n * Lets go of the composition held once its target is no longer observed: it is over\n * unless its element kept focus and its target is observed again this turn.\n */\n #letGo(): void {\n const composition = this.#composition;\n if (composition === null) return;\n if (!holdsFocus(composition.element)) {\n this.#composition = null;\n return;\n }\n queueMicrotask(() => {\n if (this.#composition !== composition || this.#observedTargets.has(composition.target)) {\n return;\n }\n this.#composition = null;\n if (!this.#connected) return;\n this.#abandoned = { element: composition.element, inPlace: true };\n this.#runAbandon();\n });\n }\n\n /**\n * Ends the composition held if its field left the observed target, taking the\n * composition's text along, or holds text a write left.\n */\n #settle(): void {\n const composition = this.#composition;\n if (composition === null) return;\n const { target, element, text } = composition;\n if (target instanceof Node && element instanceof Node && !target.contains(element)) {\n this.#composition = null;\n } else if (textOf(element) !== text) {\n this.#abandon(false);\n }\n }\n\n /**\n * Ends the composition held, unconfirmed. Its `onAbandon` runs in a microtask,\n * unless an event the tracker hears runs it first.\n */\n #abandon(inPlace: boolean): void {\n this.#owe(inPlace);\n this.#composition = null;\n queueMicrotask(this.#runAbandon);\n }\n\n /** Records the `onAbandon` the composition held owes. */\n #owe(inPlace: boolean): void {\n const composition = this.#composition;\n if (composition !== null) this.#abandoned = { element: composition.element, inPlace };\n }\n\n /** Runs the `onAbandon` an ended composition owes, once. */\n readonly #runAbandon = (): void => {\n const abandoned = this.#abandoned;\n if (abandoned === null) return;\n this.#abandoned = null;\n this.#onAbandon?.(abandoned.element, abandoned.inPlace);\n };\n\n /** A composition starting while one is held ends the held one, unconfirmed. */\n readonly #handleStart = (event: Event): void => {\n this.#confirmedTarget = null;\n this.#settle();\n this.#owe(true);\n // A listener runs while the event is dispatched, so both targets are set.\n const target = event.currentTarget as EventTarget;\n const element = event.target as EventTarget;\n this.#composition = { target, element, text: textOf(element) };\n this.#runAbandon();\n this.#onStart?.(event);\n };\n\n readonly #handleEnd = (event: Event): void => {\n this.#runAbandon();\n if (this.#composition?.target === event.currentTarget) this.#composition = null;\n this.#confirmedTarget = event.target;\n this.#onEnd?.(event);\n };\n\n /**\n * A key on an observed field opens an edit of its own, so no echo is owed; it\n * also says whether the edit it announces lands inside a composition.\n */\n readonly #handleKeydown = (event: Event): void => {\n this.#settle();\n this.#runAbandon();\n this.#confirmedTarget = null;\n this.#keyComposing = (event as KeyboardEvent).isComposing === true;\n };\n\n /** An edit is about to land: a composition the engine no longer runs ends first. */\n readonly #handleBeforeInput = (event: Event): void => {\n const keyComposing = this.#keyComposing;\n this.#keyComposing = false;\n this.#settle();\n const { isComposing, inputType } = event as InputEvent;\n if (\n this.#composition !== null &&\n !keyComposing &&\n !isComposing &&\n inputType &&\n !isCompositionInputType(inputType)\n ) {\n this.#abandon(true);\n }\n this.#runAbandon();\n };\n\n /**\n * Takes the composing field's text from an `input` the engine dispatched or one\n * that reports the composition; any other `input` follows a write the\n * composition did not make.\n */\n readonly #handleInput = (event: Event): void => {\n const composition = this.#composition;\n const { isTrusted, isComposing, inputType } = event as InputEvent;\n if (\n composition !== null &&\n event.target === composition.element &&\n (isTrusted || isComposing || isCompositionInputType(inputType))\n ) {\n composition.text = textOf(composition.element);\n } else {\n this.#settle();\n }\n this.#runAbandon();\n };\n\n /**\n * Checks the composition as a field loses focus, ahead of the consumer's own blur\n * handlers. A field inside an observed ancestor that loses focus within its\n * document keeps its text and composes no more.\n */\n readonly #handleBlur = (event: Event): void => {\n this.#settle();\n this.#runAbandon();\n const composition = this.#composition;\n if (composition === null || composition.target === composition.element) return;\n const { element } = composition;\n if (!(element instanceof Node) || event.target !== element) return;\n const root = element.getRootNode() as Document | ShadowRoot;\n if (root.activeElement !== element) this.#composition = null;\n };\n\n /** Keeps a Turbo morph from writing the value of the element composing. */\n readonly #handleBeforeMorphAttribute = (event: Event): void => {\n this.#settle();\n const composition = this.#composition;\n if (composition?.target !== event.currentTarget || event.target !== composition.element) return;\n const detail: { readonly attributeName?: unknown } | null = (event as CustomEvent).detail;\n if (detail?.attributeName === \"value\") event.preventDefault();\n };\n}\n","/** What {@link ListenerSet.add} passes on besides the signal it supplies itself. */\nexport type ListenerOptions = Omit<AddEventListenerOptions, \"signal\">;\n\n/**\n * The event map a target's own `addEventListener` types its handlers with: the\n * window's, a document's, an HTML or SVG element's, any other element's, or a\n * media query list's. Other targets name none.\n */\ntype EventMapOf<T extends EventTarget> = T extends Window\n ? WindowEventMap\n : T extends Document\n ? DocumentEventMap\n : T extends HTMLElement\n ? HTMLElementEventMap\n : T extends SVGElement\n ? SVGElementEventMap\n : T extends Element\n ? ElementEventMap\n : T extends MediaQueryList\n ? MediaQueryListEventMap\n : Record<never, never>;\n\n/**\n * Owns every listener a controller attaches for one connected lifetime and\n * releases them together, so an event name is spelled once and the release\n * cannot drift from the registration.\n *\n * Detaching by hand repeats three things at the release site — the type, the\n * handler reference and the capture flag — and any one of them drifting leaves\n * a listener alive on an element the controller no longer drives. Aborting the\n * signal a registration was created with releases it whatever it was made of,\n * so the release site names nothing.\n *\n * One set per lifetime, held as a field and never rebuilt.\n * {@link ListenerSet.dispose} is the only thing that closes a generation, and it opens\n * the next one in the same step, so the lifecycle hooks can call `add` and\n * `dispose` in any order any number of times, and no `add` ever meets an\n * already aborted signal — a DOM that registers a listener on such a signal\n * would keep it forever. Rebuilding the set instead would leak:\n * `addEventListener` matches an existing registration on target, type, callback\n * and capture alone, so re-adding the same handler while the first registration\n * is live is discarded, and that live registration keeps the signal it was\n * attached with — a set built by a second `connect()` can never release what it\n * appears to own.\n *\n * Scope is the registration only. Timers, observers, leases and the order they\n * are unwound in stay with the controller, which places `dispose()` in its\n * cleanup sequence. A receiver that changes at runtime (a\n * swapped target) is rebound by calling `dispose()` and then `add()` again from\n * the rebind, not by a second set.\n *\n * A lifetime shorter than the connection — while a Value holds, until a first\n * load, while a subscription is open — gets a set of its own, which the end of\n * that lifetime disposes. A controller therefore holds one set per lifetime: the\n * connection's, and one for each swapped receiver or shorter span.\n *\n * The set must own every registration of a tuple it holds: a listener the same\n * target already carries for the same type, callback and capture flag keeps the\n * right to remove it, and this set's `add` for that tuple is discarded. A\n * subscription shared between instances behind a participant count, listeners of\n * several elements that come and go one at a time, and those one gesture holds\n * keep their own pair of calls or a signal of their own.\n *\n * @example\n * ```ts\n * readonly #listeners = new ListenerSet();\n *\n * connect(): void {\n * this.#listeners.add(this.element, \"submit\", this.#onNativeSubmit, { capture: true });\n * this.#listeners.add(this.element, \"turbo:submit-start\", this.#onSubmitStart);\n * this.#listeners.add(this.element, \"turbo:submit-end\", this.#onSubmitEnd);\n * }\n *\n * disconnect(): void {\n * this.#listeners.dispose();\n * }\n * ```\n */\nexport class ListenerSet {\n /** The generation every `add` joins until the next `dispose()`. */\n #abort = new AbortController();\n\n /**\n * Attaches `handler` to the open generation, exactly as the caller spelled it.\n *\n * The set supplies the signal, so `options` carries everything else the DOM\n * accepts — `capture` included. A removal by hand would have to repeat that\n * flag; aborting the signal releases the listener without it.\n *\n * A `type` the target's own event map names types `handler` with that event,\n * as the target's `addEventListener` does, so a handler written for a\n * `KeyboardEvent` is passed as it is; any other `type` takes an\n * `EventListener`.\n */\n add<T extends EventTarget, K extends keyof EventMapOf<T> & string>(\n target: T,\n type: K,\n handler: (event: EventMapOf<T>[K]) => void,\n options?: ListenerOptions,\n ): void;\n add(target: EventTarget, type: string, handler: EventListener, options?: ListenerOptions): void;\n add(target: EventTarget, type: string, handler: EventListener, options?: ListenerOptions): void {\n target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });\n }\n\n /**\n * Releases every listener of the open generation, synchronously, and opens the\n * next one. Idempotent, and safe before anything has been added.\n */\n dispose(): void {\n this.#abort.abort();\n this.#abort = new AbortController();\n }\n}\n","/**\n * Collapses many Stimulus lifecycle callbacks from one DOM mutation into a\n * single pass.\n *\n * Stimulus fires `<name>TargetConnected` / `Disconnected` once per element and\n * `<name>ValueChanged` once per changed attribute. Replacing a list of N options\n * or morphing several render Values therefore delivers N callbacks — but the\n * useful unit of work is \"reconcile against the resulting declarative input\",\n * once, after the batch has settled. Every controller with reconcilable targets\n * or render Values needs the same shape: a `queued` flag plus `queueMicrotask`.\n *\n * **A microtask is the right horizon, and the reason is specific.** Stimulus\n * drives these callbacks from a `MutationObserver`, whose own callback already\n * runs as a microtask with the whole batch in hand; scheduling one more lands\n * after the last sibling callback of that batch and still before paint or any\n * event handler. A timer would be later than it needs to be, and reconciling\n * synchronously would run once per element against a half-applied DOM.\n *\n * **The two guards are not the same guard.** Scheduling is refused before the\n * controller connects, and running is refused after it disconnects:\n *\n * - **Before `connect()`** — Stimulus delivers initial target and Value callbacks\n * ahead of `connect()`. Reconciling there would compute output against a\n * controller whose own state has not been initialised, and `connect()` is\n * about to do a full pass anyway.\n * - **After `disconnect()`** — Stimulus fires a callback for **every** target\n * during teardown, and a microtask queued just before it would otherwise run\n * against a detached tree. {@link MicrotaskCoalescer.cancel} exists for the\n * teardown path to drop the pending pass outright.\n *\n * Both guards are part of one contract here rather than something each consumer\n * has to remember separately.\n *\n * Scope is the scheduling only. *What* to reconcile — keep the surviving active\n * option, fall back to the next / previous / first visible one, rebuild derived\n * chips or hidden fields — stays in the controller, because no two consumers\n * answer it the same way.\n *\n * @example\n * ```ts\n * readonly #reconcile = new MicrotaskCoalescer(() => this.#reconcileOptions());\n *\n * connect() { this.#reconcile.activate(); }\n * disconnect() { this.#reconcile.cancel(); }\n *\n * optionTargetConnected() { this.#reconcile.schedule(); }\n * optionTargetDisconnected() { this.#reconcile.schedule(); }\n * ```\n */\nexport class MicrotaskCoalescer {\n readonly #run: () => void;\n #queued = false;\n #active = false;\n #generation = 0;\n\n /** @param run - the single reconciliation pass, invoked at most once per batch. */\n constructor(run: () => void) {\n this.#run = run;\n }\n\n /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */\n activate(): void {\n this.#active = true;\n }\n\n /** Closes the window and drops any pending pass; call from `disconnect()`. */\n cancel(): void {\n this.#active = false;\n this.#queued = false;\n this.#generation += 1;\n }\n\n /** Whether a requested pass has yet to run. */\n get pending(): boolean {\n return this.#queued;\n }\n\n /** Requests one pass after the batch settles. Idempotent; inert outside the window. */\n schedule(): void {\n if (!this.#active || this.#queued) return;\n this.#queued = true;\n const generation = this.#generation;\n queueMicrotask(() => {\n // A cancelled callback must not consume a pass queued after reconnect.\n if (generation !== this.#generation || !this.#queued || !this.#active) return;\n this.#queued = false;\n this.#run();\n });\n }\n}\n","import { ListenerSet } from \"./listener_set\";\nimport { MicrotaskCoalescer } from \"./microtask_coalescer\";\n\n/**\n * Coalesces retained-element morphs and explicit lifecycle requests into one pass.\n *\n * Observe the controller's element after its initial state is settled. Morphs on\n * that element and bubbling morphs on its descendants share the same microtask\n * as {@link schedule}. The callback repairs derived output; the controller owns\n * any logical transition reporting. {@link disconnect} releases the listener and\n * cancels pending work, including work from an earlier connected lifetime.\n */\nexport class MorphRenderWatcher {\n readonly #listeners = new ListenerSet();\n readonly #pass: MicrotaskCoalescer;\n #element: Element | null = null;\n readonly #onMorph = (): void => this.#pass.schedule();\n\n /** @param run - the single pass that repairs the settled controller's output. */\n constructor(run: () => void) {\n this.#pass = new MicrotaskCoalescer(run);\n }\n\n /** Opens observation; observing the same element again preserves queued work. */\n observe(element: Element): void {\n if (this.#element === element) return;\n this.disconnect();\n this.#element = element;\n this.#pass.activate();\n this.#listeners.add(element, \"turbo:morph-element\", this.#onMorph);\n }\n\n /** Requests one pass; requests outside an observed lifetime are ignored. */\n schedule(): void {\n this.#pass.schedule();\n }\n\n /** Whether a pass requested by a morph or {@link schedule} has yet to run. */\n get pending(): boolean {\n return this.#pass.pending;\n }\n\n /** Releases observation and pending work synchronously; safe to repeat. */\n disconnect(): void {\n this.#listeners.dispose();\n this.#pass.cancel();\n this.#element = null;\n }\n}\n","import { MAX_TIMER_DELAY_MS } from \"./timer_bounds\";\n\n/** Semantic constraints on an already decoded number, independent of the DOM. */\nexport interface NumberBounds {\n /** Finite numbers are required, including when this field is omitted. */\n readonly finite?: true;\n /** Inclusive lower endpoint. */\n readonly min?: number;\n /** Inclusive upper endpoint. */\n readonly max?: number;\n /** Exclusive lower endpoint. */\n readonly exclusiveMin?: number;\n /** Require a number without a fractional part. */\n readonly integer?: boolean;\n /** Exact decoded numbers accepted by a discrete contract. */\n readonly allowedValues?: readonly number[];\n /** JSON-safe exceptions to finite-number checking for unbounded endpoints. */\n readonly allowInfinity?: \"negative\" | \"positive\" | \"both\";\n}\n\n/** One constraint for each Number Value, including shorthand declarations. */\nexport type NumberValueConstraints<Values> = {\n readonly [Key in keyof Values as Values[Key] extends\n | NumberConstructor\n | { type: NumberConstructor }\n ? Key\n : never]: NumberBounds;\n};\n\n/** Reusable semantic domains; fractional inputs remain fractional unless excluded. */\nexport const NUMBER_BOUNDS = {\n finite: { finite: true },\n nonNegative: { finite: true, min: 0 },\n positive: { finite: true, exclusiveMin: 0 },\n nonNegativeInteger: { finite: true, min: 0, integer: true },\n positiveInteger: { finite: true, exclusiveMin: 0, integer: true },\n lowerBound: { finite: true, allowInfinity: \"negative\" },\n upperBound: { finite: true, allowInfinity: \"positive\" },\n timer: { finite: true, min: 0, max: MAX_TIMER_DELAY_MS },\n positiveTimer: { finite: true, exclusiveMin: 0, max: MAX_TIMER_DELAY_MS },\n} as const satisfies Record<string, NumberBounds>;\n\n/**\n * Checks all declared bounds without rounding, clamping, or coercing the input.\n * Infinity exceptions relax only finite checking; every other bound still applies.\n */\nexport function matchesNumberBounds(value: number, bounds: NumberBounds): boolean {\n if (!Number.isFinite(value)) {\n const direction = value === Infinity ? \"positive\" : value === -Infinity ? \"negative\" : null;\n if (direction === null) return false;\n if (bounds.allowInfinity !== \"both\" && bounds.allowInfinity !== direction) return false;\n }\n if (bounds.min !== undefined && value < bounds.min) return false;\n if (bounds.max !== undefined && value > bounds.max) return false;\n if (bounds.exclusiveMin !== undefined && value <= bounds.exclusiveMin) return false;\n if (bounds.integer && !Number.isInteger(value)) return false;\n if (bounds.allowedValues !== undefined && !bounds.allowedValues.includes(value)) return false;\n return true;\n}\n\n/** Decodes a Number Value literal; action params use their own JSON decoder. */\nexport function decodeNumberValue(raw: string): number {\n return Number(raw.replace(/_/g, \"\"));\n}\n","/**\n * Numeric coercion for controllers that accept a number through a Value, an action\n * param, or an event detail.\n *\n * Stimulus decodes action params as JSON when possible and leaves other text\n * untouched. CustomEvent detail can also supply a number or numeric string.\n * The reader accepts those two types while rejecting blank and non-finite input.\n */\n\nimport { matchesNumberBounds, type NumberBounds } from \"./number_bounds\";\n\n/** Numeric update input, accepting decoded action params before CustomEvent detail. */\nexport type NumericValueEvent = Event & {\n params?: { amount?: unknown };\n detail?: { value?: unknown };\n};\n\n/** Reads the nullish action-param/detail precedence without falling back from invalid input. */\nexport function eventNumber(event: NumericValueEvent): number | null {\n return toFiniteNumber(event.params?.amount ?? event.detail?.value);\n}\n\n/**\n * Reads a finite number or nonblank numeric string; other input returns `null`.\n * Blank strings cannot silently reset a value to zero.\n */\nexport function toFiniteNumber(raw: unknown): number | null {\n if (typeof raw !== \"number\" && typeof raw !== \"string\") return null;\n if (typeof raw === \"string\" && raw.trim().length === 0) return null;\n const value = Number(raw);\n return Number.isFinite(value) ? value : null;\n}\n\n/**\n * Returns an accepted decoded Number Value or the caller's fallback unchanged.\n * The caller owns the fallback contract; this reader does not parse or write a Value.\n */\nexport function readNumber(raw: number, fallback: number, bounds: NumberBounds): number {\n return matchesNumberBounds(raw, bounds) ? raw : fallback;\n}\n","import { readNumber } from \"./coerce\";\nimport { matchesNumberBounds, type NumberBounds } from \"./number_bounds\";\n\n/** The instance identity carried by a Number Value read. */\nexport interface NumberValueOwner {\n readonly identifier: string;\n readonly element: Element;\n}\n\n/** Reads current declarations at the point of use without rewriting their attributes. */\nexport class NumberValueReader {\n /** The last rejected literal per Value; no history grows for an unchanged instance. */\n readonly #lastRejected = new Map<string, string>();\n\n /** Resolves the declared number using its own fallback and shared class contract. */\n read(\n owner: NumberValueOwner,\n name: string,\n raw: number,\n fallback: number,\n bounds: NumberBounds,\n ): number {\n const resolved = readNumber(raw, fallback, bounds);\n if (matchesNumberBounds(raw, bounds)) {\n this.#lastRejected.delete(name);\n return resolved;\n }\n const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;\n const literal = owner.element.getAttribute(attribute);\n if (literal === null) {\n this.#lastRejected.delete(name);\n return resolved;\n }\n if (this.#lastRejected.get(name) !== literal) {\n this.#lastRejected.set(name, literal);\n console.warn(\n `Stimeo UI: \"${owner.identifier}\" has an invalid number Value \"${name}\" declaration ${JSON.stringify(literal)}; using ${fallback}.`,\n );\n }\n return resolved;\n }\n}\n","/**\n * Self-cleaning timer registries shared by Stimeo controllers.\n *\n * Stimulus controllers frequently schedule `setTimeout` / `setInterval` work\n * (auto-dismiss, debouncing, polling). When the element leaves the DOM — a\n * Turbo Drive navigation, a Turbo Stream replacement, or any `disconnect()` —\n * orphaned timers keep firing against a detached controller, leaking memory and\n * mutating stale state. {@link SafeTimeout} and {@link SafeInterval} track every\n * timer they create so a single {@link TimerRegistry.clearAll | clearAll()} call\n * in `disconnect()` tears them all down.\n *\n * These are intentionally low-level primitives: they own *registration and\n * cleanup only*. One pending timer per key is `KeyedTimers`\n * (`keyed_timers.ts`), and a timer a person can hold open, with its remaining-time\n * accounting, is `PausableTimers` (`pausable_timers.ts`).\n */\n\nexport { MAX_TIMER_DELAY_MS } from \"./timer_bounds\";\n\n/**\n * Shared registry bookkeeping for the timeout/interval variants.\n *\n * Subclasses provide the scheduling primitive ({@link schedule}) and its matching\n * canceller ({@link cancel}); this base owns the set of live ids plus the\n * per-id and bulk teardown shared by both.\n */\nabstract class TimerRegistry {\n /** Live timer ids that have not yet been cleared (or, for timeouts, fired). */\n protected readonly ids = new Set<number>();\n\n /** Schedules the underlying platform timer and returns its id. */\n protected abstract schedule(callback: () => void, delay: number): number;\n\n /** Cancels the underlying platform timer for `id`. */\n protected abstract cancel(id: number): void;\n\n /**\n * Cancels a single tracked timer.\n *\n * No-ops if the id is unknown (already cleared, fired, or never owned by this\n * registry), so callers can clear defensively without guarding.\n */\n clear(id: number): void {\n if (this.ids.delete(id)) {\n this.cancel(id);\n }\n }\n\n /**\n * Cancels every tracked timer. Call this from a controller's `disconnect()`\n * to guarantee no timer outlives the element.\n */\n clearAll(): void {\n for (const id of this.ids) {\n this.cancel(id);\n }\n this.ids.clear();\n }\n\n /** Number of timers currently tracked (pending). */\n get size(): number {\n return this.ids.size;\n }\n}\n\n/**\n * `setTimeout` wrapper that auto-forgets each timer once it fires and supports\n * bulk teardown on disconnect.\n *\n * @example\n * ```ts\n * #timers = new SafeTimeout();\n *\n * connect() {\n * this.#timers.set(() => this.dismiss(), 5000);\n * }\n *\n * disconnect() {\n * this.#timers.clearAll();\n * }\n * ```\n */\nexport class SafeTimeout extends TimerRegistry {\n /**\n * Schedules `callback` after `delay` ms and returns the timer id.\n *\n * The id is removed from the registry automatically when the timeout fires,\n * so {@link TimerRegistry.size | size} reflects only still-pending timers.\n */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(() => {\n this.ids.delete(id);\n callback();\n }, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setTimeout(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearTimeout(id);\n }\n}\n\n/**\n * `setInterval` wrapper that tracks every interval for bulk teardown on\n * disconnect. Unlike {@link SafeTimeout}, intervals are retained until they are\n * explicitly cleared because they fire repeatedly.\n *\n * @example\n * ```ts\n * #intervals = new SafeInterval();\n *\n * connect() {\n * this.#intervals.set(() => this.tick(), 1000);\n * }\n *\n * disconnect() {\n * this.#intervals.clearAll();\n * }\n * ```\n */\nexport class SafeInterval extends TimerRegistry {\n /** Schedules a repeating `callback` every `delay` ms and returns the timer id. */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(callback, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setInterval(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearInterval(id);\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { announce, fillTemplate } from \"../utils/announce\";\nimport { AttributeLease } from \"../utils/attribute_lease\";\nimport { setAttributeIfChanged } from \"../utils/attribute_write\";\nimport { CompositionTracker } from \"../utils/composition_tracker\";\nimport { ListenerSet } from \"../utils/listener_set\";\nimport { MorphRenderWatcher } from \"../utils/morph_render_watcher\";\nimport { NUMBER_BOUNDS, type NumberValueConstraints } from \"../utils/number_bounds\";\nimport { NumberValueReader } from \"../utils/number_value\";\nimport { SafeTimeout } from \"../utils/safe_timeout\";\n\ntype CharacterCounterField = HTMLInputElement | HTMLTextAreaElement;\ntype DisplayMode = \"remaining\" | \"used\" | \"both\";\n\ninterface CharacterCountReading {\n readonly length: number;\n readonly remaining: number | null;\n readonly over: boolean;\n readonly max: number;\n readonly text: string;\n}\n\ntype CharacterCounterDetail = Pick<CharacterCountReading, \"length\" | \"remaining\" | \"over\">;\n\n/**\n * Headless character-counter behavior for a text field (no dedicated APG\n * pattern; follows the WCAG 2.2 \"status messages\" practice, 4.1.3).\n *\n * Markup contract (identifier: `stimeo--character-counter`):\n * <div data-controller=\"stimeo--character-counter\"\n * data-stimeo--character-counter-max-value=\"140\"\n * data-stimeo--character-counter-announce-text-value=\"{remaining} characters remaining\">\n * <textarea data-stimeo--character-counter-target=\"input\"\n * aria-describedby=\"cc\"></textarea>\n * <span id=\"cc\" data-stimeo--character-counter-target=\"output\"></span>\n * </div>\n *\n * Watches the field's UTF-16 code-unit length, writes the remaining/used count\n * into `output`, and toggles the `data-near-limit` / `data-over-limit` state\n * hooks. While over the limit it temporarily leases `aria-invalid=\"true\"` on\n * the field and, on recovery or teardown, gives the field back the value beneath\n * it: the consumer's authored value, or the latest value of a `stimeo--form-field`\n * whose control is the same field. The lease records the authored value on the\n * field, so the connection that adopts a copy of the page Turbo restores from its\n * cache gives it back once the field is within the limit — a password field comes\n * back empty. Nothing is undone on `turbo:before-cache`, which Turbo also\n * dispatches on pages that stay: an over-limit field stays invalid there.\n * The field is the first `input` target, or — when the controller is attached\n * straight onto an `<input>`/`<textarea>` — the controller element itself.\n *\n * `change` and `reconcile` dispatch\n * `{ length: number, remaining: number | null, over: boolean }`.\n *\n * @remarks\n * Behavior only — count text and state update synchronously, with no styling.\n * Confirmed user input dispatches `stimeo--character-counter:change` only when\n * the measured length actually changes. Its detail is `{ length, remaining,\n * over }`; `remaining` is `null` when `max` is disabled. IME intermediate input\n * is ignored, and `compositionend` commits the confirmed value exactly once.\n *\n * Assistive notification is opt-in and i18n-neutral. `announceText` accepts\n * `{count}`, `{length}`, `{remaining}`, `{max}`, and `{over}` placeholders and\n * sends the settled message to the page's shared `stimeo--announcer` after a\n * short debounce. The visible `output` is not itself required to be a live\n * region. Initial reflection and Turbo restoration never dispatch or announce.\n * Runtime target/Value reconciliation dispatches\n * `stimeo--character-counter:reconcile` only when the public derived state\n * changes, and never announces.\n * All input targets keep composition tracking even while another one is first,\n * and only the first field's own conversion holds back its `input`.\n * A composing field that returns first restores its own accepted count silently;\n * its confirmation is compared with that field's accepted length, never another's,\n * and a confirmation or cancellation at that length dispatches `reconcile` once when\n * the state reported last differs from it. A conversion there that ends without\n * `compositionend` reconciles that accepted count the same way, without reading the\n * field; the next edit counts what the field holds.\n */\nexport class CharacterCounterController extends Controller<HTMLElement> {\n /** Numeric read boundaries share one reader for this controller instance. */\n readonly #numbers = new NumberValueReader();\n\n static override targets = [\"input\", \"output\"];\n static override values = {\n max: { type: Number, default: 0 },\n warnAt: { type: Number, default: 0 },\n mode: { type: String, default: \"remaining\" },\n announceText: { type: String, default: \"\" },\n };\n\n static valueConstraints = {\n max: NUMBER_BOUNDS.nonNegative,\n warnAt: NUMBER_BOUNDS.nonNegative,\n } satisfies NumberValueConstraints<typeof CharacterCounterController.values>;\n static events = [\"change\", \"reconcile\"] as const;\n\n declare readonly inputTarget: CharacterCounterField;\n declare readonly inputTargets: CharacterCounterField[];\n declare readonly outputTarget: HTMLElement;\n declare readonly hasInputTarget: boolean;\n declare readonly hasOutputTarget: boolean;\n\n declare maxValue: number;\n declare warnAtValue: number;\n declare modeValue: string;\n declare announceTextValue: string;\n\n /** Delay (ms) before one settled count is sent to the shared announcer. */\n static readonly #announceDelay = 200;\n\n readonly #timeouts = new SafeTimeout();\n readonly #ariaInvalid = new AttributeLease<CharacterCounterField>(\n \"aria-invalid\",\n this.identifier,\n );\n readonly #repaint = new MorphRenderWatcher(() => this.#reconcile(true));\n /**\n * Commits a confirmed composition. One that ends without `compositionend`\n * confirmed nothing: a reconciliation it held reads what the field holds; with none\n * held the field's text waits for the next edit, and the state reported last is\n * reconciled with the field's accepted count. With a resync pass queued, or another\n * field first meanwhile, that is left to the pass, which counts the field it binds; the\n * end queues one, as it does for a reconciliation held, since a field put first and\n * taken away within one task is never reported. A field still bound that composes again\n * is not counted, so its accepted count is reconciled by a new conversion starting in it\n * while it is first, or else by the pass that finds it composing.\n */\n readonly #composition = new CompositionTracker({\n onStart: (event) => {\n if (event.target === this.#acceptedOwed && this.#field === this.#boundField) {\n this.#reconcileAccepted();\n }\n },\n onEnd: (event) => this.#commitFrom(event.currentTarget),\n onAbandon: () => {\n const first = this.#field === this.#boundField;\n if (this.#reconcileHeld && first) this.#recount(true, this.#owedField);\n else if (first && !this.#repaint.pending) this.#reconcileAccepted();\n else {\n if (!this.#reconcileHeld) this.#acceptedOwed = this.#boundField;\n // A field put first and taken away within the task is never reported: queue a pass.\n this.#repaint.schedule();\n }\n },\n });\n /** The field bound when its accepted-count reconciliation was left to a pass, until one runs. */\n #acceptedOwed: CharacterCounterField | null = null;\n /** A reconciliation owed once the composition ends: the declarations changed while it ran. */\n #reconcileHeld = false;\n /** Each field's accepted count and rendering, independent of the field in charge. */\n readonly #accepted = new WeakMap<\n CharacterCounterField,\n {\n readonly text: string;\n readonly over: boolean;\n readonly near: boolean;\n readonly length: number;\n readonly detail: CharacterCounterDetail;\n readonly declared: string;\n }\n >();\n #announceId: number | null = null;\n #boundField: CharacterCounterField | null = null;\n /** The input listener on the bound field; binding another field releases it first. */\n readonly #fieldListeners = new ListenerSet();\n #lastDetail: CharacterCounterDetail | null = null;\n #reflectedOver: boolean | null = null;\n\n readonly #onInput = (event: Event): void => {\n const field = this.#boundField;\n if (!field || event.currentTarget !== field || this.#field !== field) return;\n // An engine may echo a confirmed composition with one more `input`;\n // committing it again would re-run the reading the commit already took.\n if (this.#composition.consumesConfirmedInput(event)) return;\n // Only the field's own conversion holds its edit back, never one in another target.\n const composing = this.#composition.composingElement() === field;\n if (composing || (event as InputEvent).isComposing === true) return;\n this.#commit(field);\n };\n\n /**\n * Reflects the current DOM state and opens the mutation-reconciliation window. A\n * field that moved here with its conversion has nothing new to read; the pass waits\n * for the conversion only if the declarations changed with the move.\n */\n override connect(): void {\n this.#observeFields();\n this.#repaint.observe(this.element);\n this.#reconcile(false);\n }\n\n /** Releases listeners, timers, borrowed ARIA, and controller-owned state hooks. */\n override disconnect(): void {\n this.#repaint.disconnect();\n this.#bindField(null);\n this.#composition.disconnect();\n this.#clearStateHooks();\n this.#lastDetail = null;\n }\n\n /**\n * Rebinds and repaints after an input target is added or replaced at runtime. A\n * field that moved here keeping its conversion is the same field: the pass shows what\n * it showed and holds nothing.\n */\n inputTargetConnected(): void {\n this.#observeFields();\n this.#repaint.schedule();\n }\n\n /**\n * Releases and repaints after an input target is removed or replaced at runtime.\n * A field that moves or leaves mid-composition hears no `compositionend`, so its\n * composition ends here — unless it kept focus through the move, which keeps the\n * conversion; a field that stays bound is observed again at once. The pass counts\n * the field that is first now, and waits only for a conversion in that field.\n */\n inputTargetDisconnected(element: CharacterCounterField): void {\n this.#composition.unobserve(element);\n if (element === this.#boundField) this.#composition.observe(element);\n this.#repaint.schedule();\n }\n\n /** Initializes a display target inserted after the controller connected. */\n outputTargetConnected(): void {\n this.#repaint.schedule();\n }\n\n /** Reconciles the optional display target set after a removal or replacement. */\n outputTargetDisconnected(): void {\n this.#repaint.schedule();\n }\n\n /** Repaints when application code or a Turbo morph changes `max`. */\n maxValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Repaints when application code or a Turbo morph changes `warnAt`. */\n warnAtValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Repaints when application code or a Turbo morph changes `mode`. */\n modeValueChanged(): void {\n this.#repaint.schedule();\n }\n\n /** Rebinds one mutation batch, then counts the field bound now. */\n #reconcile(report: boolean): void {\n const owedField = this.#owedField;\n this.#bindField(this.#field);\n this.#recount(report, owedField);\n }\n\n /**\n * The field a pending announcement was earned for, if any. An edit inside the\n * debounce window has already earned an announcement. Reconciliation never\n * originates one, but it must not swallow that one either: a pass that counts again\n * retargets the pending message at the settled reading, so the user hears the count\n * that ends up displayed rather than nothing; a pass that only shows the count again\n * leaves it on the count shown, and the commit that applies a pass the composition\n * held retargets it. A replaced field is the exception — its pending message\n * describes a field the reader can no longer reach.\n */\n get #owedField(): CharacterCounterField | null {\n return this.#announceId === null ? null : this.#boundField;\n }\n\n /**\n * Counts the bound field and reports a changed controller-derived state. While the\n * field is composing, the pass shows what it showed and is owed when the composition\n * ends only if the declarations it counts against changed; a pass with nothing new\n * to count against — a morph that changes nothing, a target swapped — holds\n * nothing. A conversion going on in a field the counter no longer watches holds\n * nothing either.\n */\n #recount(report: boolean, owedField: CharacterCounterField | null): void {\n const owed = this.#acceptedOwed;\n this.#acceptedOwed = null;\n const previous = this.#lastDetail;\n const field = this.#boundField;\n if (field !== null && this.#composition.composingElement() === field) {\n this.#reconcileHeld = this.#accepted.get(field)?.declared !== this.#declared;\n // The IME owns the text: a morph that wiped the count gets back what it showed.\n this.#showAgain(field);\n // Composing again, the field is not counted for the reconciliation it was left.\n if (owed === field) this.#reconcileAccepted();\n return;\n }\n this.#reconcileHeld = false;\n if (!field) {\n this.#renderEmpty();\n this.#lastDetail = null;\n return;\n }\n const reading = this.#render(field);\n const detail = this.#detail(reading);\n this.#lastDetail = detail;\n if (owedField === field) this.#scheduleAnnouncement(reading);\n if (report && previous && this.#detailsDiffer(previous, detail)) {\n this.dispatch(\"reconcile\", { detail });\n }\n }\n\n /** Commits a composition only when it came from the field still owned here. */\n #commitFrom(target: EventTarget | null): void {\n const field = this.#boundField;\n if (!field || target !== field || this.#field !== field) return;\n this.#commit(field);\n }\n\n /** Reflects one confirmed user input and reports only a real length transition. */\n #commit(field: CharacterCounterField): void {\n const held = this.#reconcileHeld;\n this.#reconcileHeld = false;\n const previousLength = this.#accepted.get(field)?.length ?? null;\n const reading = this.#render(field);\n const previousDetail = this.#lastDetail;\n const detail = this.#detail(reading);\n this.#lastDetail = detail;\n if (previousLength === reading.length) {\n if (previousDetail && this.#detailsDiffer(previousDetail, detail)) {\n this.dispatch(\"reconcile\", { detail });\n }\n // The pass the composition held counts again here, and takes the message along.\n if (held && this.#owedField === field) this.#scheduleAnnouncement(reading);\n return;\n }\n\n this.dispatch(\"change\", { detail });\n if (this.#boundField === field && this.#field === field) this.#scheduleAnnouncement(reading);\n }\n\n /** Selects the public event state from the richer internal reading. */\n #detail(reading: CharacterCountReading): CharacterCounterDetail {\n return {\n length: reading.length,\n remaining: reading.remaining,\n over: reading.over,\n };\n }\n\n /** Compares exactly the state carried by `change` and `reconcile`. */\n #detailsDiffer(left: CharacterCounterDetail, right: CharacterCounterDetail): boolean {\n return (\n left.length !== right.length || left.remaining !== right.remaining || left.over !== right.over\n );\n }\n\n /**\n * Synchronizes visible count, state hooks, and temporary validation ARIA.\n *\n * @stimeoRenderRoot\n */\n #render(field: CharacterCounterField): CharacterCountReading {\n const length = field.value.length;\n const max = this.#normalizeCount(this.#safeMax);\n const warnAt = this.#normalizeCount(this.#safeWarnAt);\n const remaining = max > 0 ? max - length : null;\n const over = remaining !== null && remaining < 0;\n const near = remaining !== null && warnAt > 0 && !over && remaining <= warnAt;\n\n this.#toggle(\"data-over-limit\", over);\n this.#toggle(\"data-near-limit\", near);\n this.#reflectInvalid(field, over);\n\n const text = this.#format(length, remaining, max);\n this.#writeOutput(text);\n this.#accepted.set(field, {\n text,\n over,\n near,\n length,\n detail: { length, remaining, over },\n declared: this.#declared,\n });\n return { length, remaining, over, max, text };\n }\n\n /**\n * Restores this field's accepted rendering without reading its composition draft.\n * Its accepted count remains the baseline even while another field is counted.\n * Nothing is reported here: the state reported last stays the one the commit that\n * ends the conversion compares with, so a commit at the accepted length reconciles\n * a state another field published meanwhile.\n */\n #showAgain(field: CharacterCounterField): void {\n const shown = this.#accepted.get(field);\n if (shown === undefined) return;\n this.#lastDetail ??= shown.detail;\n this.#toggle(\"data-over-limit\", shown.over);\n this.#toggle(\"data-near-limit\", shown.near);\n this.#reflectInvalid(field, shown.over);\n this.#writeOutput(shown.text);\n }\n\n /**\n * Reports the bound field's accepted count as `reconcile` when the state reported\n * last differs from it, without reading the field or announcing. Only that field's\n * own conversion, shown again silently, leaves the two apart.\n */\n #reconcileAccepted(): void {\n const previous = this.#lastDetail;\n const field = this.#boundField;\n const accepted = field && this.#accepted.get(field)?.detail;\n if (!previous || !accepted || !this.#detailsDiffer(previous, accepted)) return;\n this.#lastDetail = accepted;\n this.dispatch(\"reconcile\", { detail: accepted });\n }\n\n /** Clears derived output when the declarative input set has no usable field. */\n #renderEmpty(): void {\n this.#reflectedOver = null;\n this.#clearStateHooks();\n this.#writeOutput(\"\");\n }\n\n /** Tracks every target while only the field in charge supplies accepted input. */\n #observeFields(): void {\n for (const input of this.inputTargets) this.#composition.observe(input);\n }\n\n /** Replaces the input listener symmetrically, returning state from the old field. */\n #bindField(field: CharacterCounterField | null): void {\n if (field === this.#boundField) return;\n\n const previous = this.#boundField;\n if (previous) {\n this.#fieldListeners.dispose();\n if (previous !== this.element && !this.inputTargets.includes(previous)) {\n this.#composition.unobserve(previous);\n }\n this.#ariaInvalid.return(previous);\n }\n\n this.#cancelAnnouncement();\n this.#boundField = field;\n this.#reflectedOver = null;\n if (!field) return;\n\n this.#fieldListeners.add(field, \"input\", this.#onInput);\n this.#composition.observe(field);\n }\n\n /** Leases invalid state on an over-limit edge or missing output, preserving authored values. */\n #reflectInvalid(field: CharacterCounterField, over: boolean): void {\n if (this.#reflectedOver === over && (!over || field.hasAttribute(\"aria-invalid\"))) return;\n this.#reflectedOver = over;\n if (over) this.#ariaInvalid.write(field, \"true\");\n else this.#ariaInvalid.return(field);\n }\n\n /** Builds the visible count for the normalized display mode. */\n #format(length: number, remaining: number | null, max: number): string {\n if (remaining === null) return String(length);\n switch (this.#mode) {\n case \"used\":\n return String(length);\n case \"both\":\n return `${length}/${max}`;\n default:\n return String(remaining);\n }\n }\n\n /**\n * Debounces one i18n-neutral message into the shared polite announcer. The message\n * is worded when it is spoken, so a template the consumer changes meanwhile rewords\n * it; a template empty now schedules nothing.\n *\n * @stimeoRuntimeOnly `announceText` words the one announcement this call schedules;\n * the count is painted by the marked renderer.\n */\n #scheduleAnnouncement(reading: CharacterCountReading): void {\n this.#cancelAnnouncement();\n const message = (): string =>\n fillTemplate(this.announceTextValue, {\n count: reading.text,\n length: reading.length,\n remaining: reading.remaining ?? \"\",\n max: reading.max,\n over: String(reading.over),\n });\n if (message().trim().length === 0) return;\n\n this.#announceId = this.#timeouts.set(() => {\n announce(message());\n this.#announceId = null;\n }, CharacterCounterController.#announceDelay);\n }\n\n /** Cancels the one outstanding announcement without touching visible output. */\n #cancelAnnouncement(): void {\n if (this.#announceId !== null) this.#timeouts.clear(this.#announceId);\n this.#announceId = null;\n }\n\n /** Writes the optional display only when its text actually changed. */\n #writeOutput(text: string): void {\n if (!this.hasOutputTarget || this.outputTarget.textContent === text) return;\n this.outputTarget.textContent = text;\n }\n\n /** Reflects a presence-style state hook without redundant attribute writes. */\n #toggle(name: string, on: boolean): void {\n setAttributeIfChanged(this.element, name, on ? \"true\" : null);\n }\n\n /** Removes both state hooks owned by this controller. */\n #clearStateHooks(): void {\n this.#toggle(\"data-over-limit\", false);\n this.#toggle(\"data-near-limit\", false);\n }\n\n /** Normalizes a finite count into a non-negative integer. */\n #normalizeCount(raw: number): number {\n return Math.max(0, Math.trunc(raw));\n }\n\n /** Falls back to `remaining` when an authored display mode is unknown. */\n get #mode(): DisplayMode {\n if (this.modeValue === \"used\" || this.modeValue === \"both\") return this.modeValue;\n return \"remaining\";\n }\n\n /** The declarations a rendering counts against, as it reads them. */\n get #declared(): string {\n return [\n this.#normalizeCount(this.#safeMax),\n this.#normalizeCount(this.#safeWarnAt),\n this.#mode,\n ].join();\n }\n\n /** The watched field: the first target, or a directly controlled form field. */\n get #field(): CharacterCounterField | null {\n if (this.hasInputTarget) return this.inputTarget;\n const element: HTMLElement = this.element;\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)\n return element;\n return null;\n }\n /** Current `max` declaration resolved against its numeric contract. */\n get #safeMax(): number {\n return this.#numbers.read(\n this,\n \"max\",\n this.maxValue,\n CharacterCounterController.values.max.default,\n CharacterCounterController.valueConstraints.max,\n );\n }\n\n /** Current `warnAt` declaration resolved against its numeric contract. */\n get #safeWarnAt(): number {\n return this.#numbers.read(\n this,\n \"warnAt\",\n this.warnAtValue,\n CharacterCounterController.values.warnAt.default,\n CharacterCounterController.valueConstraints.warnAt,\n );\n }\n}\n"]}
|
|
@@ -37,7 +37,7 @@ import { Controller } from '@hotwired/stimulus';
|
|
|
37
37
|
* - Parent toggle checks/unchecks every child and clears its own `indeterminate`.
|
|
38
38
|
* All child targets, including disabled ones, participate; omit the target to
|
|
39
39
|
* exclude an input. The cascade does not synthesize native child `change`
|
|
40
|
-
* events — one aggregate custom event
|
|
40
|
+
* events — one aggregate custom event reports a changed aggregate.
|
|
41
41
|
* - A child change recomputes the parent: all → checked, none → unchecked,
|
|
42
42
|
* some → `indeterminate`.
|
|
43
43
|
* - The aggregate (`all` / `partial` / `none`) is mirrored to `data-state` on the
|
|
@@ -45,7 +45,12 @@ import { Controller } from '@hotwired/stimulus';
|
|
|
45
45
|
* form resets are reconciled from the children. Callers that assign the live
|
|
46
46
|
* `checked` property directly must dispatch `change`, because property writes
|
|
47
47
|
* are not observable by a `MutationObserver`.
|
|
48
|
-
* - `stimeo--checkbox:change` is dispatched
|
|
48
|
+
* - `stimeo--checkbox:change` is dispatched by the two public change actions only
|
|
49
|
+
* when the aggregate differs from the last published one. Pending page writes
|
|
50
|
+
* are included in that confirmation; returning to the published aggregate is
|
|
51
|
+
* silent. Browser-dispatched listeners can reconcile a page write before the
|
|
52
|
+
* action runs, while script dispatch and consecutive Stimulus actions in one
|
|
53
|
+
* listener include it in the action's `change`.
|
|
49
54
|
* `stimeo--checkbox:reconcile` is dispatched instead when a reconciliation —
|
|
50
55
|
* not the user — moves the aggregate. Both carry `{ checked: boolean,
|
|
51
56
|
* indeterminate: boolean, state: "all" | "partial" | "none" }` and describe
|