stimeo-ui 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/controllers/alert_dialog_controller.js +32 -5
  3. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  4. package/dist/controllers/announcer_controller.d.ts +32 -6
  5. package/dist/controllers/announcer_controller.js +255 -20
  6. package/dist/controllers/announcer_controller.js.map +1 -1
  7. package/dist/controllers/color_picker_controller.d.ts +2 -1
  8. package/dist/controllers/color_picker_controller.js +46 -0
  9. package/dist/controllers/color_picker_controller.js.map +1 -1
  10. package/dist/controllers/command_palette_controller.js +32 -5
  11. package/dist/controllers/command_palette_controller.js.map +1 -1
  12. package/dist/controllers/confirm_controller.js +32 -5
  13. package/dist/controllers/confirm_controller.js.map +1 -1
  14. package/dist/controllers/countdown_controller.d.ts +19 -5
  15. package/dist/controllers/countdown_controller.js +112 -12
  16. package/dist/controllers/countdown_controller.js.map +1 -1
  17. package/dist/controllers/date_range_picker_controller.d.ts +4 -1
  18. package/dist/controllers/date_range_picker_controller.js +50 -0
  19. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  20. package/dist/controllers/dialog_controller.js +32 -5
  21. package/dist/controllers/dialog_controller.js.map +1 -1
  22. package/dist/controllers/dismissible_controller.js.map +1 -1
  23. package/dist/controllers/drawer_controller.js +32 -5
  24. package/dist/controllers/drawer_controller.js.map +1 -1
  25. package/dist/controllers/empty_state_controller.d.ts +9 -4
  26. package/dist/controllers/empty_state_controller.js +24 -10
  27. package/dist/controllers/empty_state_controller.js.map +1 -1
  28. package/dist/controllers/focus_controller.js +32 -5
  29. package/dist/controllers/focus_controller.js.map +1 -1
  30. package/dist/controllers/form_validation_controller.js.map +1 -1
  31. package/dist/controllers/frame_loading_controller.d.ts +14 -3
  32. package/dist/controllers/frame_loading_controller.js +177 -15
  33. package/dist/controllers/frame_loading_controller.js.map +1 -1
  34. package/dist/controllers/local_time_controller.d.ts +19 -3
  35. package/dist/controllers/local_time_controller.js +100 -6
  36. package/dist/controllers/local_time_controller.js.map +1 -1
  37. package/dist/controllers/meter_controller.d.ts +22 -2
  38. package/dist/controllers/meter_controller.js +145 -26
  39. package/dist/controllers/meter_controller.js.map +1 -1
  40. package/dist/controllers/network_status_controller.d.ts +13 -1
  41. package/dist/controllers/network_status_controller.js +28 -8
  42. package/dist/controllers/network_status_controller.js.map +1 -1
  43. package/dist/controllers/overflow_menu_controller.js +33 -6
  44. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  45. package/dist/controllers/progress_controller.d.ts +16 -1
  46. package/dist/controllers/progress_controller.js +116 -9
  47. package/dist/controllers/progress_controller.js.map +1 -1
  48. package/dist/controllers/range_slider_controller.d.ts +4 -1
  49. package/dist/controllers/range_slider_controller.js +68 -3
  50. package/dist/controllers/range_slider_controller.js.map +1 -1
  51. package/dist/controllers/rating_controller.d.ts +4 -1
  52. package/dist/controllers/rating_controller.js +53 -0
  53. package/dist/controllers/rating_controller.js.map +1 -1
  54. package/dist/controllers/relative_time_controller.d.ts +13 -0
  55. package/dist/controllers/relative_time_controller.js +133 -12
  56. package/dist/controllers/relative_time_controller.js.map +1 -1
  57. package/dist/controllers/sidebar_controller.d.ts +1 -11
  58. package/dist/controllers/sidebar_controller.js +37 -8
  59. package/dist/controllers/sidebar_controller.js.map +1 -1
  60. package/dist/controllers/skeleton_controller.d.ts +7 -2
  61. package/dist/controllers/skeleton_controller.js +73 -20
  62. package/dist/controllers/skeleton_controller.js.map +1 -1
  63. package/dist/controllers/slider_controller.js +17 -2
  64. package/dist/controllers/slider_controller.js.map +1 -1
  65. package/dist/controllers/spinner_controller.d.ts +37 -4
  66. package/dist/controllers/spinner_controller.js +228 -27
  67. package/dist/controllers/spinner_controller.js.map +1 -1
  68. package/dist/controllers/step_indicator_controller.d.ts +12 -1
  69. package/dist/controllers/step_indicator_controller.js +82 -5
  70. package/dist/controllers/step_indicator_controller.js.map +1 -1
  71. package/dist/controllers/stick_to_bottom_controller.d.ts +26 -2
  72. package/dist/controllers/stick_to_bottom_controller.js +60 -10
  73. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  74. package/dist/index.js +1056 -281
  75. package/dist/index.js.map +1 -1
  76. package/dist/inspector/cli.js +785 -76
  77. package/dist/inspector/cli.js.map +1 -1
  78. package/dist/inspector/cli_bin.js +785 -76
  79. package/dist/inspector/cli_bin.js.map +1 -1
  80. package/dist/inspector/examples.json +5 -5
  81. package/dist/inspector/manifest.json +21 -8
  82. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/focus_candidate.ts","../../src/utils/layout_observer.ts","../../src/utils/safe_timeout.ts","../../src/utils/tabindex_loan.ts","../../src/controllers/overflow_menu_controller.ts"],"names":[],"mappings":"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","file":"overflow_menu_controller.js","sourcesContent":["/**\n * Whether a disabled `<fieldset>` ancestor actually reaches `control`.\n *\n * HTML exempts the contents of a fieldset's **first direct-child `<legend>`**, and\n * the exemption is per fieldset — a control legal in one legend can still be\n * disabled by a second, outer fieldset, so the walk continues upward.\n *\n * Exported for the consumer that needs this rule *without* the rest of\n * {@link canTakeFocus}: `toolbar` bounds its own `hidden` walk at the toolbar\n * root, which is a different rule, so it composes the two itself.\n */\nexport function inheritsFieldsetDisabled(control: HTMLElement): boolean {\n let fieldset: Element | null = control.closest(\"fieldset[disabled]\");\n while (fieldset) {\n const legend = Array.from(fieldset.children).find((child) => child.tagName === \"LEGEND\");\n if (!legend?.contains(control)) return true;\n fieldset = fieldset.parentElement?.closest(\"fieldset[disabled]\") ?? null;\n }\n return false;\n}\n\n/**\n * Whether an element can actually take focus, checked **before** `focus()` runs.\n *\n * A controller that must move focus off a control it is about to disable or hide\n * picks a destination and calls `focus()` on it. If that destination cannot take\n * focus, the call **fails silently**: `hidden` and natively `disabled` elements\n * swallow it, so the caret stays in the subtree that is disappearing and lands on\n * `<body>` a frame later — the exact outcome the rescue exists to prevent, minus\n * any signal that it happened.\n *\n * Testing after the fact is the obvious alternative and is deliberately not the\n * rule. Reading `document.activeElement` back only works in a real browser, and\n * looping over candidates that way performs a real focus move per failure —\n * observable to assistive technology. Checking first costs nothing and catches\n * the cases that actually occur.\n *\n * **`aria-disabled` is not disqualifying.** It is the attribute an author uses\n * for a control that must stay *discoverable*, and the roving contract keeps\n * such items reachable. Only the three conditions that make the platform refuse\n * focus are checked: `hidden` (an ancestor's counts), the native `disabled`\n * property, and `disabled` inherited from an ancestor `fieldset`. CSS-only\n * invisibility is not detectable here and stays the consumer's problem.\n *\n * Reading `:disabled` instead of walking the fieldset chain would be shorter, but\n * that pseudo-class is not evaluated consistently outside real browsers and this\n * has to be right headlessly too. happy-dom in particular focuses a `<button>`\n * inside a disabled fieldset where a real engine refuses, so the inheritance is\n * spelled out rather than delegated.\n *\n * What a consumer does when nothing survives is its own call: some fall back to\n * their landmark, while a widget whose caret already sits somewhere legitimate\n * refuses the move outright rather than relocating it.\n *\n * @example\n * ```ts\n * const target = candidates.find(canTakeFocus);\n * if (target) target.focus();\n * else {\n * this.#tabindex.lend(this.element); // nothing left: fall back to the landmark\n * this.element.focus();\n * }\n * ```\n *\n * @param element - the candidate destination\n */\nexport function canTakeFocus(element: HTMLElement): boolean {\n if (element.closest(\"[hidden]\")) return false;\n if (!(\"disabled\" in element)) return true;\n if ((element as HTMLElement & { disabled: boolean }).disabled) return false;\n return !inheritsFieldsetDisabled(element);\n}\n","/**\n * Unified element-size and viewport observation for Stimeo controllers.\n *\n * Layout-sensitive widgets (sliders, resizable panes, scroll spies, popovers)\n * need to react both to their *own* box changing — via {@link ResizeObserver} —\n * and to the *viewport* changing — via the `window` `resize` event. Wiring those\n * two sources by hand in every controller risks leaked listeners on\n * `disconnect()`. {@link LayoutObserver} owns both behind one callback and one\n * {@link LayoutObserver.disconnect | disconnect()} that releases everything.\n *\n * Behavior only: the helper reports *that* layout changed; it never reads or\n * writes styles. Consumers decide what to recompute.\n */\n\n/** Invoked whenever an observed element or the viewport changes size. */\nexport type LayoutCallback = () => void;\n\n/** Constructs a {@link ResizeObserver}; injectable so tests stay deterministic. */\nexport type ResizeObserverFactory = (callback: ResizeObserverCallback) => ResizeObserver;\n\n/** Options for {@link LayoutObserver}. */\nexport interface LayoutObserverOptions {\n /**\n * Factory for the {@link ResizeObserver} used by {@link LayoutObserver.observe}.\n * Defaults to the global constructor; override it in tests, or to no-op in\n * environments where `ResizeObserver` is unavailable.\n */\n resizeObserverFactory?: ResizeObserverFactory;\n}\n\n/**\n * Observes element resizes and/or viewport resizes through a single callback,\n * with guaranteed teardown.\n *\n * @example\n * ```ts\n * #layout = new LayoutObserver(() => this.#reposition());\n *\n * connect() {\n * this.#layout.observe(this.panelTarget);\n * this.#layout.observeViewport();\n * }\n *\n * disconnect() {\n * this.#layout.disconnect();\n * }\n * ```\n */\nexport class LayoutObserver {\n readonly #callback: LayoutCallback;\n readonly #resizeObserverFactory: ResizeObserverFactory | null;\n #resizeObserver: ResizeObserver | null = null;\n #observingViewport = false;\n\n /** Stable bound handler so add/removeEventListener target the same reference. */\n readonly #handleViewportResize = (): void => {\n this.#callback();\n };\n\n constructor(callback: LayoutCallback, options: LayoutObserverOptions = {}) {\n this.#callback = callback;\n this.#resizeObserverFactory =\n options.resizeObserverFactory ??\n (typeof ResizeObserver === \"undefined\" ? null : (cb) => new ResizeObserver(cb));\n }\n\n /**\n * Starts observing an element's size. Repeated calls observe additional\n * elements through the same shared observer. No-ops when no\n * `ResizeObserver` implementation is available.\n */\n observe(element: Element): void {\n if (!this.#resizeObserverFactory) return;\n if (!this.#resizeObserver) {\n this.#resizeObserver = this.#resizeObserverFactory(() => {\n this.#callback();\n });\n }\n this.#resizeObserver.observe(element);\n }\n\n /** Stops observing a single element while leaving any others in place. */\n unobserve(element: Element): void {\n this.#resizeObserver?.unobserve(element);\n }\n\n /** Starts observing viewport resizes. Idempotent: the listener is added once. */\n observeViewport(): void {\n if (this.#observingViewport) return;\n this.#observingViewport = true;\n window.addEventListener(\"resize\", this.#handleViewportResize);\n }\n\n /** Stops observing viewport resizes without affecting element observation. */\n unobserveViewport(): void {\n if (!this.#observingViewport) return;\n this.#observingViewport = false;\n window.removeEventListener(\"resize\", this.#handleViewportResize);\n }\n\n /**\n * Releases every observation: disconnects the {@link ResizeObserver} and\n * removes the viewport listener. Safe to call multiple times. Call this from a\n * controller's `disconnect()`.\n */\n disconnect(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n this.unobserveViewport();\n }\n}\n","/**\n * Self-cleaning timer registries shared by Stimeo controllers.\n *\n * Stimulus controllers frequently schedule `setTimeout` / `setInterval` work\n * (auto-dismiss, debouncing, polling). When the element leaves the DOM — a\n * Turbo Drive navigation, a Turbo Stream replacement, or any `disconnect()` —\n * orphaned timers keep firing against a detached controller, leaking memory and\n * mutating stale state. {@link SafeTimeout} and {@link SafeInterval} track every\n * timer they create so a single {@link TimerRegistry.clearAll | clearAll()} call\n * in `disconnect()` tears them all down.\n *\n * These are intentionally low-level primitives: they own *registration and\n * cleanup only*. Higher-level policy (pause/resume, remaining-time accounting)\n * stays in the individual controllers so per-widget semantics are not flattened\n * into a lowest-common-denominator helper.\n */\n\n/**\n * Shared registry bookkeeping for the timeout/interval variants.\n *\n * Subclasses provide the scheduling primitive ({@link schedule}) and its matching\n * canceller ({@link cancel}); this base owns the set of live ids plus the\n * per-id and bulk teardown shared by both.\n */\nabstract class TimerRegistry {\n /** Live timer ids that have not yet been cleared (or, for timeouts, fired). */\n protected readonly ids = new Set<number>();\n\n /** Schedules the underlying platform timer and returns its id. */\n protected abstract schedule(callback: () => void, delay: number): number;\n\n /** Cancels the underlying platform timer for `id`. */\n protected abstract cancel(id: number): void;\n\n /**\n * Cancels a single tracked timer.\n *\n * No-ops if the id is unknown (already cleared, fired, or never owned by this\n * registry), so callers can clear defensively without guarding.\n */\n clear(id: number): void {\n if (this.ids.delete(id)) {\n this.cancel(id);\n }\n }\n\n /**\n * Cancels every tracked timer. Call this from a controller's `disconnect()`\n * to guarantee no timer outlives the element.\n */\n clearAll(): void {\n for (const id of this.ids) {\n this.cancel(id);\n }\n this.ids.clear();\n }\n\n /** Number of timers currently tracked (pending). */\n get size(): number {\n return this.ids.size;\n }\n}\n\n/**\n * `setTimeout` wrapper that auto-forgets each timer once it fires and supports\n * bulk teardown on disconnect.\n *\n * @example\n * ```ts\n * #timers = new SafeTimeout();\n *\n * connect() {\n * this.#timers.set(() => this.dismiss(), 5000);\n * }\n *\n * disconnect() {\n * this.#timers.clearAll();\n * }\n * ```\n */\nexport class SafeTimeout extends TimerRegistry {\n /**\n * Schedules `callback` after `delay` ms and returns the timer id.\n *\n * The id is removed from the registry automatically when the timeout fires,\n * so {@link TimerRegistry.size | size} reflects only still-pending timers.\n */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(() => {\n this.ids.delete(id);\n callback();\n }, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setTimeout(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearTimeout(id);\n }\n}\n\n/**\n * `setInterval` wrapper that tracks every interval for bulk teardown on\n * disconnect. Unlike {@link SafeTimeout}, intervals are retained until they are\n * explicitly cleared because they fire repeatedly.\n *\n * @example\n * ```ts\n * #intervals = new SafeInterval();\n *\n * connect() {\n * this.#intervals.set(() => this.tick(), 1000);\n * }\n *\n * disconnect() {\n * this.#intervals.clearAll();\n * }\n * ```\n */\nexport class SafeInterval extends TimerRegistry {\n /** Schedules a repeating `callback` every `delay` ms and returns the timer id. */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(callback, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setInterval(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearInterval(id);\n }\n}\n","/**\n * Shared bookkeeping for a `tabindex` a controller lends an element temporarily.\n *\n * A controller that must move focus somewhere the author never made focusable\n * (a landmark root, a scroll destination) reaches for the same trick: add a\n * `tabindex` just-in-time and hand it back once it is no longer needed. The\n * borrow is the easy half; the return is what the two conditions below are for.\n *\n * **Returning needs two conditions, not one.** Owning the borrow is not enough:\n * the attribute must also still hold the value this instance wrote. A consumer\n * that changed it afterwards — `tabindex=\"0\"` to make the root its own Tab stop\n * — owns it now, and removing it there silently discards authored markup. The\n * bookkeeping is dropped either way, since the loan is over regardless of who\n * ends up owning the value.\n *\n * **Never borrow over an existing value.** An element that already carries a\n * `tabindex` is the author's to control, so there is nothing to lend and nothing\n * to return.\n *\n * The registry is keyed by element, so a controller borrowing on a single\n * element (`this.element`) and one borrowing across a changing set of targets\n * use the same API — the single-element case is a set of one. It holds no\n * opinion about *when* to borrow or where focus goes next; that stays in the\n * controller.\n *\n * **The API is deliberately two methods.** This file's own doc block is dropped\n * from `dist`, but every member comment is inlined into **each** consumer entry\n * (`tsup` builds with `splitting: false`), so rationale belongs here, only the\n * contract belongs on the members, and every method no consumer calls is still\n * paid for once per consumer entry.\n *\n * @example\n * ```ts\n * readonly #tabindex = new TabindexLoan();\n *\n * #rescueFocus() {\n * this.#tabindex.lend(this.element);\n * this.element.focus();\n * }\n *\n * disconnect() {\n * this.#tabindex.returnAll();\n * }\n * ```\n */\nexport class TabindexLoan<T extends HTMLElement = HTMLElement> {\n readonly #value: string;\n readonly #lent = new Set<T>();\n\n /**\n * @param value - the `tabindex` to lend. `\"-1\"` (the default) is\n * programmatically focusable but not a Tab stop; `\"0\"` is a real Tab stop,\n * which a scroll region with no focusable content of its own needs.\n */\n constructor(value: string = \"-1\") {\n this.#value = value;\n }\n\n /** Lends `element` the value; no-ops when it already carries a `tabindex`. */\n lend(element: T): void {\n if (element.hasAttribute(\"tabindex\")) return;\n element.setAttribute(\"tabindex\", this.#value);\n this.#lent.add(element);\n }\n\n /** Takes back every loan whose value is still the one that was lent. */\n returnAll(): void {\n for (const element of this.#lent) {\n if (element.getAttribute(\"tabindex\") === this.#value) element.removeAttribute(\"tabindex\");\n }\n this.#lent.clear();\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { canTakeFocus } from \"../utils/focus_candidate\";\nimport { LayoutObserver } from \"../utils/layout_observer\";\nimport { SafeTimeout } from \"../utils/safe_timeout\";\nimport { TabindexLoan } from \"../utils/tabindex_loan\";\nimport type { MenuController } from \"./menu_controller\";\n\n/** Marks an item that currently lives in the More menu (survives a DOM snapshot). */\nconst BANKED = \"data-stimeo--overflow-menu-banked\";\n/** Canonical index persisted while anything is banked, so a fresh instance can re-adopt. */\nconst INDEX = \"data-stimeo--overflow-menu-index\";\n/** Inert split point retained only while every managed item is banked. */\nconst BOUNDARY = \"data-stimeo--overflow-menu-boundary\";\n/** Authored values saved while an item wears menu semantics (\"\" = attribute was absent). */\nconst SAVED_ROLE = \"data-stimeo--overflow-menu-role\";\nconst SAVED_TABINDEX = \"data-stimeo--overflow-menu-tabindex\";\nconst SAVED_MENU_TARGET = \"data-stimeo--overflow-menu-menu-target\";\n/** Menu's target attribute — set to `item` while banked so Menu drives the item. */\nconst MENU_TARGET = \"data-stimeo--menu-target\";\n/** Everything this controller writes on an item; all removed on the way back to the bar. */\nconst BOOKKEEPING = [BANKED, INDEX, SAVED_ROLE, SAVED_TABINDEX, SAVED_MENU_TARGET] as const;\n\n/** `ParentNode.moveBefore` (Chromium 133+): relocates a node without removing it first. */\ninterface MovableParent {\n moveBefore?: (node: Node, child: Node | null) => void;\n}\n\n/**\n * Headless **overflow / priority menu**: items that no longer fit their container are\n * moved into a \"More\" dropdown (lowest `data-priority` first) and moved back as space\n * returns, watched with a {@link ResizeObserver} (no dedicated APG pattern — a\n * composition; the menu's a11y is delegated to Menu, so it is not re-implemented).\n *\n * Markup contract (identifier: `stimeo--overflow-menu`):\n * <nav data-controller=\"stimeo--overflow-menu\" aria-label=\"Actions\">\n * <div data-stimeo--overflow-menu-target=\"items\">\n * <button data-priority=\"1\">Save</button>\n * <button>Delete</button>\n * </div>\n * <div data-controller=\"stimeo--menu\" data-stimeo--overflow-menu-target=\"more\" hidden>\n * <button id=\"more-trigger\" data-stimeo--menu-target=\"trigger\"\n * aria-haspopup=\"menu\" aria-expanded=\"false\"\n * data-action=\"click->stimeo--menu#toggle\n * keydown->stimeo--menu#onTriggerKeydown\">More</button>\n * <div role=\"menu\" aria-labelledby=\"more-trigger\"\n * data-stimeo--menu-target=\"menu\" hidden></div>\n * </div>\n * </div>\n *\n * This controller does not own the root's role. It ships none: a navigation bar is\n * a named `<nav>` whose items stay in the normal Tab order. A consumer may add\n * `role=\"toolbar\"`, but that alone is not an APG Toolbar — the single-tab-stop\n * roving is {@link ToolbarController}'s behavior, not this one's — and a named\n * role still needs `aria-label` / `aria-labelledby`.\n *\n * Two parts of that contract are load-bearing and easy to drop. The banked-items\n * container is a permissive single `role=\"menu\"` element this controller appends to\n * directly; use a `<div>`, since a `<ul>` cannot directly own the moved controls. And the\n * trigger's `data-action` is **required, not decoration**: without it the More button\n * never opens, and `keydown->stimeo--menu#onTriggerKeydown` is what makes it reachable\n * by keyboard at all (`Enter` / `Space` / `ArrowDown`). It is spelled out above rather\n * than referenced, because the keyboard half of this contract lives *only* in the\n * consumer's markup — nothing in this controller's source would reveal its absence.\n * Items need no bindings of their own — Menu delegates their handling from its own\n * element, so a control that only becomes a menu item at runtime is operable the\n * moment it lands.\n *\n * On connect (and every debounced resize) it measures the items against the container's\n * content width and, when they overflow, banks the lowest-priority ones into the More\n * menu — giving each `role=\"menuitem\"` / `tabindex=\"-1\"` and the menu's `item` target so\n * Menu drives it — until the rest fit beside the More button. When nothing overflows the\n * More wrapper (button *and* menu) is `hidden`. The controller element carries\n * `data-overflowing` / `data-overflow-count`, and a `change` event fires on connect and\n * on every later transition.\n *\n * @remarks\n * **Measuring.** The container's width must not be derived from its content (give the bar\n * an explicit width, `flex: 1`, or plain block layout): the More button is revealed before\n * measuring, so a shrink-to-fit container always reports \"items + gap + More\" and nothing\n * ever overflows. The budget is the container's *content box* (`clientWidth` minus its\n * horizontal padding); the gap between items comes from the items container, the gap\n * reserved for the More button from the bar itself. Item widths are cached (a natural\n * width is location-independent) so a pass reads only the items in the bar — one reflow,\n * not two. The trade-off: an item whose content changes *while banked* (a locale switch, a\n * badge update) keeps its stale width until it is back in the bar, so it may return one\n * pass late; re-measuring it in place would cost a second reflow every pass. An item the\n * author marked `hidden` is out of the budget, out of the drop order, and never banked; it\n * holds its canonical slot and rejoins as soon as the attribute goes away. Toggling\n * `hidden` is an attribute change, not a resize, so call `update` after it.\n *\n * **Moving.** Items are moved (never cloned), and only the nodes that are actually out of\n * place — a pass that changes nothing touches no node, because re-inserting a node removes\n * it first and the browser then drops focus to `<body>`. Where `moveBefore` is supported\n * the move preserves focus and transient element state outright.\n *\n * **Focus.** When the focused item (or a descendant of it) *starts* retreating into a\n * collapsed menu it would be hidden and lose focus, so focus is redirected to the More\n * trigger (falling back to the More wrapper when the markup has no trigger — give it one,\n * or focus is left to the browser). While the menu is expanded the item stays visible, so\n * focus is left alone — unless the focused item is the one returning to the bar, which\n * takes focus out of the wrapper and leaves the expanded menu with nothing that owns it;\n * the menu is then closed and focus stays on the returned item. When the last banked item\n * returns, the wrapper is about to be hidden: the menu is closed and focus is moved out of\n * it to the last item that can actually hold it (`hidden` and disabled ones cannot), or to\n * the root when none can.\n *\n * **Priority.** Lower `data-priority` is kept longer; a value that is absent, empty, or\n * not a number ranks lowest and drops first.\n *\n * **Turbo.** The managed set and the canonical order are rebuilt *from the DOM* every\n * pass, so a fresh `connect()` onto markup that already holds banked items (cache restore,\n * a morph, a clone, server-rendered overflow) re-adopts them instead of orphaning them\n * inside a wrapper it would then hide. Symmetrically, `disconnect()` and\n * `turbo:before-cache` return every item to the bar, collapse the composed menu (so it\n * releases its dismissal-stack membership rather than being snapshotted mid-gesture), and\n * strip this controller's bookkeeping attributes, so a cached snapshot is always the\n * pristine authored DOM. The `ResizeObserver` and debounce timer are released on\n * `disconnect()` too.\n *\n * Behavior only — no styling.\n */\nexport class OverflowMenuController extends Controller<HTMLElement> {\n static override targets = [\"items\", \"more\"];\n static override values = {\n moreLabel: { type: String, default: \"More\" },\n debounce: { type: Number, default: 100 },\n };\n static actions = [\"update\"] as const;\n static events = [\"change\"] as const;\n\n declare readonly itemsTarget: HTMLElement;\n declare readonly moreTarget: HTMLElement;\n declare readonly hasItemsTarget: boolean;\n declare readonly hasMoreTarget: boolean;\n\n declare moreLabelValue: string;\n declare debounceValue: number;\n\n readonly #layout = new LayoutObserver(() => this.#scheduleUpdate());\n readonly #timers = new SafeTimeout();\n /** The managed items in canonical (authored) order, rebuilt from the DOM each pass. */\n #items: HTMLElement[] = [];\n #index = new WeakMap<HTMLElement, number>();\n /** Cached bar-context width per item; see the class remarks for the staleness caveat. */\n #widths = new WeakMap<HTMLElement, number>();\n /** Last reported overflow count, so `change` fires only on transitions. */\n #lastHidden: number | null = null;\n /** The `tabindex` this instance lends the root for the focus fallback. */\n readonly #tabindex = new TabindexLoan();\n\n /** Hands Turbo a pristine snapshot: the cache is written after this event. */\n readonly #onBeforeCache = (): void => {\n this.#restoreAll();\n };\n\n override connect(): void {\n if (!this.hasItemsTarget || !this.hasMoreTarget) return;\n\n const trigger = this.#trigger();\n if (trigger !== null && this.#isBareTrigger(trigger)) {\n trigger.textContent = this.moreLabelValue;\n }\n\n document.addEventListener(\"turbo:before-cache\", this.#onBeforeCache);\n this.#layout.observe(this.element);\n this.#layout.observeViewport();\n this.update();\n }\n\n override disconnect(): void {\n this.#layout.disconnect();\n this.#timers.clearAll();\n document.removeEventListener(\"turbo:before-cache\", this.#onBeforeCache);\n this.#restoreAll();\n this.#lastHidden = null;\n }\n\n /** Re-measures and rebalances items between the bar and the More menu. */\n update(): void {\n if (!this.hasItemsTarget || !this.hasMoreTarget) return;\n this.#syncItems();\n\n // Reveal More so its trigger is measurable, then refresh the widths of the items\n // currently in the bar (menu items keep their location-independent last value).\n this.moreTarget.hidden = false;\n // Server-rendered overflow arrives with items already in the menu, which is\n // hidden, so they measure zero and the budget would read as \"everything fits\".\n // Bring the set back to the bar once, unbanked, so the first balance works from\n // real widths taken in the context the items are actually laid out in — a\n // banked item can carry consumer styling of its own.\n if (\n this.#items.some((item) => item.parentElement !== this.itemsTarget && !this.#widths.has(item))\n ) {\n this.#removeBoundary();\n for (const item of this.#items) this.#unbank(item);\n this.#reorder(this.itemsTarget, this.#items);\n }\n for (const item of this.#items) {\n if (item.parentElement === this.itemsTarget) this.#widths.set(item, item.offsetWidth);\n }\n const moreWidth = (this.#trigger() ?? this.moreTarget).offsetWidth;\n const itemGap = this.#gap(this.itemsTarget); // between the items themselves\n const barGap = this.#gap(this.element); // between the items row and the More button\n\n const widthOf = (el: HTMLElement): number => this.#widths.get(el) ?? el.offsetWidth;\n const containerWidth = this.element.clientWidth - this.#paddingX(this.element);\n // An authored `hidden` item occupies no width, but a naive count would still\n // charge a gap for it and could bank a sibling that in fact fits — or raise a\n // More button whose menu has nothing operable in it. It keeps its canonical\n // slot; it just does not take part in the budget or in the drop order.\n const rendered = this.#items.filter((item) => this.#rendered(item));\n const itemsWidth = rendered.reduce((sum, el) => sum + widthOf(el), 0);\n let visibleWidth = itemsWidth + Math.max(0, rendered.length - 1) * itemGap;\n\n const hidden = new Set<HTMLElement>();\n if (visibleWidth > containerWidth) {\n const budget = containerWidth - moreWidth - barGap; // reserve the More button + its gap\n // Drop lowest-retention first: no usable `data-priority` (rank ∞), then highest\n // number; ties broken right-to-left so leading items survive.\n const dropOrder = [...rendered].sort(\n (a, b) => this.#rank(b) - this.#rank(a) || this.#indexOf(b) - this.#indexOf(a),\n );\n for (const item of dropOrder) {\n if (visibleWidth <= budget) break;\n hidden.add(item);\n visibleWidth -= widthOf(item) + itemGap; // dropping an item frees its width and a gap\n }\n }\n\n // Decided before any node moves, so it cannot race the browser's blur.\n const active = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const focused = active === null ? null : this.#ownerOf(active);\n const retreating =\n focused !== null &&\n hidden.has(focused) &&\n focused.parentElement === this.itemsTarget && // i.e. *starting* to retreat\n !this.#menuExpanded();\n // The mirror image: the item holding focus is on its way *out* of an expanded\n // menu. Focus rides along with the node, but once it sits outside the More\n // wrapper the menu owns nothing that reaches it — the shared dismissal\n // resolver stops claiming for this layer, and the item's own menu bindings\n // fall out of Stimulus scope. Leaving the menu open would strand it with no\n // owner, so it is collapsed after the move (see below).\n const returning =\n focused !== null &&\n !hidden.has(focused) &&\n focused.parentElement !== this.itemsTarget && // i.e. *leaving* the menu\n this.#menuExpanded();\n\n // A fully-banked snapshot retains an inert split point so a fresh controller can\n // tell prepend from append. Once a real item remains in the bar, its saved index is\n // the stronger anchor and the boundary must not participate in DOM reordering.\n if (hidden.size === 0 || hidden.size !== this.#items.length) this.#removeBoundary();\n\n // The menu pass runs first, so retreating items leave the bar before it is reordered\n // (otherwise every trailing item would be shuffled needlessly).\n for (const item of this.#items) {\n if (hidden.has(item)) this.#bank(item);\n else this.#unbank(item);\n }\n this.#reorder(\n this.#menuList(),\n this.#items.filter((item) => hidden.has(item)),\n );\n this.#reorder(\n this.itemsTarget,\n this.#items.filter((item) => !hidden.has(item)),\n );\n\n if (retreating) (this.#trigger() ?? this.moreTarget).focus();\n else if (active !== null && this.#lostFocus(active)) active.focus();\n\n const count = hidden.size;\n // Keep the canonical positions on both sides while overflow exists. If the bar is\n // emptied, also retain an inert split point: a later prepend lands before it and an\n // append after it, preserving intent when a fresh controller adopts the snapshot.\n for (const item of this.#items) {\n if (count > 0) item.setAttribute(INDEX, String(this.#indexOf(item)));\n else item.removeAttribute(INDEX);\n }\n if (count > 0 && count === this.#items.length) this.#ensureBoundary();\n else this.#removeBoundary();\n const inMore =\n document.activeElement instanceof HTMLElement &&\n this.moreTarget.contains(document.activeElement);\n if (count === 0 || returning) {\n // Either the wrapper is about to be hidden — collapse the menu so it cannot\n // reappear expanded without a gesture, and move focus out before it\n // disappears — or the item that held focus just carried it out of the menu.\n // `close()` rather than the dismissal path, so the trigger does not take\n // back focus the user is now holding on the returned item; `inMore` is false\n // in that case, so the rescue below stays out of the way. Items still banked\n // remain reachable by reopening from the trigger.\n this.#closeMenu();\n if (inMore) this.#rescueFocus();\n }\n this.moreTarget.hidden = count === 0;\n if (count > 0) this.element.setAttribute(\"data-overflowing\", \"true\");\n else this.element.removeAttribute(\"data-overflowing\");\n this.element.setAttribute(\"data-overflow-count\", String(count));\n\n if (this.#lastHidden !== count) {\n this.#lastHidden = count;\n this.dispatch(\"change\", { detail: { visible: this.#items.length - count, hidden: count } });\n }\n }\n\n /** The flex `column-gap` on `el` in px (0 when none / unsupported). */\n #gap(el: HTMLElement): number {\n const style = this.#styleOf(el);\n return style === null ? 0 : this.#px(style.columnGap || style.gap);\n }\n\n /** Horizontal padding on `el` in px — `clientWidth` counts it, the content box cannot. */\n #paddingX(el: HTMLElement): number {\n const style = this.#styleOf(el);\n return style === null ? 0 : this.#px(style.paddingLeft) + this.#px(style.paddingRight);\n }\n\n #styleOf(el: HTMLElement): CSSStyleDeclaration | null {\n return typeof window.getComputedStyle === \"function\" ? window.getComputedStyle(el) : null;\n }\n\n #px(value: string | undefined): number {\n const parsed = Number.parseFloat(value ?? \"\");\n return Number.isNaN(parsed) ? 0 : parsed;\n }\n\n /**\n * Rebuilds the managed set and the canonical order from the DOM. The bar's children\n * give the order of everything inline (so a leading insert is not silently appended)\n * and {@link #merge} weaves the banked items back among them.\n */\n #syncItems(): void {\n const previous = this.#items;\n const bar: HTMLElement[] = [];\n let boundaryAt: number | undefined;\n for (const el of this.itemsTarget.children) {\n if (el instanceof HTMLTemplateElement && el.hasAttribute(BOUNDARY)) {\n boundaryAt ??= bar.length;\n continue;\n }\n if (el instanceof HTMLElement) bar.push(el);\n }\n\n const banked: HTMLElement[] = [];\n for (const el of this.#menuList().children) {\n if (el instanceof HTMLElement && el.hasAttribute(BANKED)) banked.push(el);\n }\n banked.sort((a, b) => this.#bankedIndex(a) - this.#bankedIndex(b));\n\n const items = this.#merge(bar, banked, boundaryAt);\n\n // An item re-homed elsewhere is no longer ours, but it would keep the menu\n // semantics we gave it — strip them before dropping it from the set.\n for (const el of previous) {\n if (!items.includes(el)) {\n this.#unbank(el);\n el.removeAttribute(INDEX);\n }\n }\n\n this.#items = items;\n this.#index = new WeakMap();\n items.forEach((el, i) => {\n this.#index.set(el, i);\n });\n }\n\n /**\n * Interleaves the banked items back among the bar's children.\n *\n * A saved index is a position in the *canonical* order, so it can only be compared\n * against another canonical position — never used as an offset into the current bar,\n * which is a shorter and differently-indexed list. (Doing so survives an untouched\n * round trip and silently scrambles the order as soon as the consumer inserts into a\n * bar that is already short, and `#bank()` then burns the scrambled index back into\n * the attribute, so widening never heals it.) Each bar child the controller already\n * knows carries its canonical index from the previous pass; a banked item goes in\n * front of the first known child whose index is higher.\n *\n * Children never seen before — inserted by the consumer since the last pass — have no\n * canonical position yet, so they keep their DOM neighbours. The exception is a\n * *trailing* run of them: appending to the bar means appending to the toolbar, so\n * everything banked is emitted before it.\n *\n * With no known child at all (a fresh instance connecting to markup that already\n * holds banked items), a fully-banked snapshot's inert boundary preserves whether an\n * unindexed run was prepended or appended before connect. Older or server-rendered\n * markup has no boundary; for that compatibility path the saved index is used as the\n * offset, the inverse of the move that banked it.\n */\n #merge(\n bar: readonly HTMLElement[],\n banked: readonly HTMLElement[],\n boundaryAt?: number,\n ): HTMLElement[] {\n const canonical = bar.map((el) => this.#index.get(el) ?? this.#savedIndex(el));\n let lastKnown = -1;\n canonical.forEach((index, i) => {\n if (index !== undefined) lastKnown = i;\n });\n\n if (lastKnown === -1) {\n if (boundaryAt !== undefined) {\n return [...bar.slice(0, boundaryAt), ...banked, ...bar.slice(boundaryAt)];\n }\n const restored = [...bar];\n for (const item of banked) {\n restored.splice(Math.min(this.#bankedIndex(item), restored.length), 0, item);\n }\n return restored;\n }\n\n const items: HTMLElement[] = [];\n let next = 0;\n const drainWhile = (accept: (saved: number) => boolean): void => {\n while (next < banked.length) {\n const item = banked[next];\n if (item === undefined || !accept(this.#bankedIndex(item))) break;\n items.push(item);\n next++;\n }\n };\n\n bar.forEach((el, i) => {\n const index = canonical[i];\n if (index !== undefined) drainWhile((saved) => saved < index);\n else if (i > lastKnown) drainWhile(() => true);\n items.push(el);\n });\n drainWhile(() => true);\n return items;\n }\n\n /** The canonical index a banked item saved, or ∞ (append) when it carries none. */\n #bankedIndex(item: HTMLElement): number {\n return this.#savedIndex(item) ?? Number.POSITIVE_INFINITY;\n }\n\n /** A finite canonical index stored on either side of the overflow split. */\n #savedIndex(item: HTMLElement): number | undefined {\n const raw = item.getAttribute(INDEX);\n if (raw === null) return undefined;\n const value = Number(raw);\n return Number.isFinite(value) ? value : undefined;\n }\n\n /** The inert split point written only when every managed item lives in More. */\n #boundary(): HTMLTemplateElement | null {\n for (const el of this.itemsTarget.children) {\n if (el instanceof HTMLTemplateElement && el.hasAttribute(BOUNDARY)) return el;\n }\n return null;\n }\n\n #ensureBoundary(): void {\n if (this.#boundary() !== null) return;\n const boundary = document.createElement(\"template\");\n boundary.setAttribute(BOUNDARY, \"\");\n this.itemsTarget.appendChild(boundary);\n }\n\n #removeBoundary(): void {\n this.#boundary()?.remove();\n }\n\n /** Debounced re-measure for resize-driven churn. */\n #scheduleUpdate(): void {\n this.#timers.clearAll();\n this.#timers.set(() => this.update(), this.debounceValue);\n }\n\n /** Returns the menu list the items are banked into (falls back to the More wrapper). */\n #menuList(): HTMLElement {\n return (\n this.moreTarget.querySelector<HTMLElement>('[data-stimeo--menu-target=\"menu\"]') ??\n this.moreTarget\n );\n }\n\n #trigger(): HTMLElement | null {\n return this.moreTarget.querySelector<HTMLElement>('[data-stimeo--menu-target=\"trigger\"]');\n }\n\n /**\n * Whether the More trigger is bare enough for the label to be safe to write.\n * Assigning `textContent` replaces *every* child node, so a trigger holding an\n * icon would silently lose it — and the loss is permanent, since the restore\n * pass returns items but not authored trigger content. A trigger that already\n * carries an accessible name is left alone too: injecting visible text under a\n * different `aria-label` would make the label and the name disagree. A trigger\n * with neither text, nor children, nor a name has nothing to lose and gets the\n * fallback; one that is empty *and* unnamed is the only case the label rescues.\n */\n #isBareTrigger(trigger: HTMLElement): boolean {\n return (\n (trigger.textContent ?? \"\").trim() === \"\" &&\n trigger.firstElementChild === null &&\n !trigger.hasAttribute(\"aria-label\") &&\n !trigger.hasAttribute(\"aria-labelledby\")\n );\n }\n\n /**\n * Whether the More menu is expanded. Menu owns that state and reflects it on the\n * trigger's `aria-expanded`, so read the contract rather than guess from `hidden`\n * (which is absent until Menu connects).\n */\n #menuExpanded(): boolean {\n return this.#trigger()?.getAttribute(\"aria-expanded\") === \"true\";\n }\n\n /**\n * Collapses the More menu before its wrapper is hidden. Menu owns the state (and the\n * Escape-stack membership that goes with it), so ask it; the DOM fallback covers markup\n * that reached an expanded state with no Menu mounted.\n */\n #closeMenu(): void {\n if (!this.#menuExpanded()) return;\n const menu = this.application.getControllerForElementAndIdentifier(\n this.moreTarget,\n \"stimeo--menu\",\n ) as MenuController | null;\n if (menu) {\n menu.close();\n return;\n }\n this.#trigger()?.setAttribute(\"aria-expanded\", \"false\");\n const list = this.#menuList();\n if (list !== this.moreTarget) list.hidden = true;\n }\n\n /** The managed item that is, or contains, `el` — focus rescue works on either. */\n #ownerOf(el: HTMLElement): HTMLElement | null {\n return this.#items.find((item) => item === el || item.contains(el)) ?? null;\n }\n\n /** Whether the item takes up room in the bar; an authored `hidden` one does not. */\n #rendered(item: HTMLElement): boolean {\n return !item.hasAttribute(\"hidden\");\n }\n\n /**\n * Moves focus out of the More wrapper just before it is hidden, to the last\n * item in canonical order that can hold it. When every item refuses, the root\n * takes focus instead of letting the browser drop it to `<body>`, borrowing a\n * `tabindex=\"-1\"` just-in-time — not a Tab stop, and handed back on restore\n * when this controller was the one that added it.\n */\n #rescueFocus(): void {\n for (let i = this.#items.length - 1; i >= 0; i--) {\n const item = this.#items[i];\n // The shared pre-check, not `#rendered`: that one answers \"does this item\n // take up room in the bar\", which reads only the item's own `hidden`. Focus\n // eligibility has to see an ancestor's too — the same rule `#lostFocus`\n // applies below.\n if (item !== undefined && canTakeFocus(item)) {\n item.focus();\n return;\n }\n }\n this.#tabindex.lend(this.element);\n this.element.focus();\n }\n\n /**\n * Whether `el` held focus, is still in a visible part of this controller, and lost it —\n * what a re-insert does in a real browser. An item that retreated into a collapsed menu\n * is excluded: it sits in a `hidden` subtree and must not be focused back.\n */\n #lostFocus(el: HTMLElement): boolean {\n return (\n el.isConnected &&\n document.activeElement !== el &&\n this.element.contains(el) &&\n el.closest(\"[hidden]\") === null\n );\n }\n\n /** Returns every item to the bar and removes all traces of this controller. */\n #restoreAll(): void {\n if (!this.hasItemsTarget || !this.hasMoreTarget) return;\n this.#syncItems();\n this.#removeBoundary();\n this.#reorder(this.itemsTarget, this.#items);\n for (const item of this.#items) {\n this.#unbank(item);\n item.removeAttribute(INDEX);\n }\n // The wrapper is being hidden for good, so the composed menu must not stay\n // expanded behind it: an unclosed menu keeps its dismissal-stack membership\n // and would be written into a Turbo snapshot mid-gesture. Focus is left\n // exactly where it is — this path runs at teardown, where moving it would be\n // the surprise.\n this.#closeMenu();\n this.moreTarget.hidden = true;\n this.element.removeAttribute(\"data-overflowing\");\n this.element.removeAttribute(\"data-overflow-count\");\n this.#tabindex.returnAll();\n }\n\n /**\n * Makes `parent`'s managed children match `sequence`, moving only what is out of place.\n * Walking backwards lets each item be compared against the element that should follow\n * it, so an unchanged run costs zero DOM mutations — the point of the exercise, since\n * every re-insert blurs the focused node.\n */\n #reorder(parent: HTMLElement, sequence: readonly HTMLElement[]): void {\n let next: HTMLElement | null = null;\n for (let i = sequence.length - 1; i >= 0; i--) {\n const item = sequence[i];\n if (item === undefined) continue;\n if (item.parentElement !== parent || item.nextElementSibling !== next) {\n this.#insert(parent, item, next);\n }\n next = item;\n }\n }\n\n /** Relocates `item`, preferring `moveBefore` (keeps focus and element state). */\n #insert(parent: HTMLElement, item: HTMLElement, before: HTMLElement | null): void {\n const move = (parent as HTMLElement & MovableParent).moveBefore;\n if (typeof move === \"function\") {\n try {\n move.call(parent, item, before);\n return;\n } catch {\n // Not movable in place (e.g. a disconnected node) — fall through.\n }\n }\n parent.insertBefore(item, before);\n }\n\n /**\n * Gives an item menuitem semantics for Menu to drive and records its canonical index,\n * saving every authored value it overwrites (\"\" means the attribute was absent).\n */\n #bank(item: HTMLElement): void {\n if (!item.hasAttribute(BANKED)) {\n item.setAttribute(BANKED, \"true\");\n item.setAttribute(SAVED_ROLE, item.getAttribute(\"role\") ?? \"\");\n item.setAttribute(SAVED_TABINDEX, item.getAttribute(\"tabindex\") ?? \"\");\n item.setAttribute(SAVED_MENU_TARGET, item.getAttribute(MENU_TARGET) ?? \"\");\n item.setAttribute(\"role\", \"menuitem\");\n item.setAttribute(\"tabindex\", \"-1\");\n item.setAttribute(MENU_TARGET, \"item\");\n }\n item.setAttribute(INDEX, String(this.#indexOf(item)));\n }\n\n /** Undoes the banking: restores every authored value and drops the bookkeeping. */\n #unbank(item: HTMLElement): void {\n if (!item.hasAttribute(BANKED)) return;\n this.#restoreAttr(item, \"role\", item.getAttribute(SAVED_ROLE));\n this.#restoreAttr(item, \"tabindex\", item.getAttribute(SAVED_TABINDEX));\n this.#restoreAttr(item, MENU_TARGET, item.getAttribute(SAVED_MENU_TARGET));\n for (const name of BOOKKEEPING) item.removeAttribute(name);\n }\n\n /** Re-applies a saved attribute value, or removes the attribute when it was absent. */\n #restoreAttr(item: HTMLElement, name: string, original: string | null): void {\n if (original === null || original === \"\") item.removeAttribute(name);\n else item.setAttribute(name, original);\n }\n\n #indexOf(item: HTMLElement): number {\n return this.#index.get(item) ?? 0;\n }\n\n /**\n * Retention rank: lower keeps longer. An absent, empty, or non-numeric `data-priority`\n * ranks lowest (drops first) — empty is the common ERB accident\n * (`data-priority=\"<%= maybe_nil %>\"`), and `Number(\"\")` is 0, which would otherwise\n * read as the *highest* retention.\n */\n #rank(item: HTMLElement): number {\n const raw = item.getAttribute(\"data-priority\");\n if (raw === null || raw.trim() === \"\") return Number.POSITIVE_INFINITY;\n const value = Number(raw);\n return Number.isNaN(value) ? Number.POSITIVE_INFINITY : value;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/before_cache_reset.ts","../../src/utils/focus_candidate.ts","../../src/utils/layout_observer.ts","../../src/utils/safe_timeout.ts","../../src/utils/tabindex_loan.ts","../../src/controllers/overflow_menu_controller.ts"],"names":[],"mappings":"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","file":"overflow_menu_controller.js","sourcesContent":["/**\n * Runs a controller's \"return to the initial state\" pass just before Turbo\n * caches the page.\n *\n * **`disconnect()` cannot do this job, for two independent reasons.** Turbo\n * queues the clone from this event rather than taking it here, and the body swap\n * that runs the controller's `disconnect()` is queued separately — so which of\n * the two lands first is not something a controller can rely on, and a rewind\n * written in `disconnect()` may reach only the DOM being thrown away. In the\n * other direction, `disconnect()` also fires on an in-page move (Stimulus tears\n * down and reconnects the same element), where rewinding would wipe a\n * legitimately in-progress interaction — a spinner mid-load would vanish. One\n * timing is unreliable, the other is too eager; `turbo:before-cache` is the only\n * point that is exactly \"the page is about to be frozen\".\n *\n * Scope is the subscription only: registering on `activate()`, unregistering on\n * `deactivate()`, and one shared document listener no matter how many instances\n * are live. *What* to return to its initial state — which `data-state`, which\n * `hidden`, which `aria-busy` — stays in the controller, because no two\n * consumers answer it the same way (the `MicrotaskCoalescer` split).\n *\n * **Rewind state, not appearance.** The pass writes attributes the controller\n * itself owns; the visual result of those attributes is the consumer's CSS, and\n * a library that reached for style or class names would be guessing at markup\n * it does not own.\n *\n * Both entry points are idempotent, so the lifecycle hooks can call them\n * unconditionally: a second `activate()` does not double-subscribe and does not\n * make the callback run twice, and `deactivate()` on an instance that never\n * subscribed is a no-op.\n *\n * This file's own doc block is dropped from `dist`, but every member comment is\n * inlined into each consumer entry (`tsup` builds with `splitting: false`), so\n * rationale belongs here and only the contract belongs on the members.\n *\n * @example\n * ```ts\n * readonly #beforeCache = new BeforeCacheReset(() => this.#rewind());\n *\n * connect() { this.#beforeCache.activate(); }\n * disconnect() { this.#beforeCache.deactivate(); }\n * ```\n */\nexport class BeforeCacheReset {\n /** Every subscribed instance, iterated by the one shared document listener. */\n static readonly #subscribers = new Set<BeforeCacheReset>();\n\n /** The shared listener; installed while at least one instance is subscribed. */\n static readonly #onBeforeCache = (): void => {\n for (const subscriber of BeforeCacheReset.#subscribers) subscriber.#rewind();\n };\n\n readonly #rewind: () => void;\n\n /** @param rewind - the pass that returns this controller's state to its initial form. */\n constructor(rewind: () => void) {\n this.#rewind = rewind;\n }\n\n /** Subscribes to `turbo:before-cache`; call from `connect()`. Idempotent. */\n activate(): void {\n const first = BeforeCacheReset.#subscribers.size === 0;\n BeforeCacheReset.#subscribers.add(this);\n if (first) {\n document.addEventListener(\"turbo:before-cache\", BeforeCacheReset.#onBeforeCache);\n }\n }\n\n /** Unsubscribes; call from `disconnect()`. Safe when never subscribed. */\n deactivate(): void {\n BeforeCacheReset.#subscribers.delete(this);\n if (BeforeCacheReset.#subscribers.size > 0) return;\n document.removeEventListener(\"turbo:before-cache\", BeforeCacheReset.#onBeforeCache);\n }\n}\n","/**\n * Whether a disabled `<fieldset>` ancestor actually reaches `control`.\n *\n * HTML exempts the contents of a fieldset's **first direct-child `<legend>`**, and\n * the exemption is per fieldset — a control legal in one legend can still be\n * disabled by a second, outer fieldset, so the walk continues upward.\n *\n * Exported for the consumer that needs this rule *without* the rest of\n * {@link canTakeFocus}: `toolbar` bounds its own `hidden` walk at the toolbar\n * root, which is a different rule, so it composes the two itself.\n */\nexport function inheritsFieldsetDisabled(control: HTMLElement): boolean {\n let fieldset: Element | null = control.closest(\"fieldset[disabled]\");\n while (fieldset) {\n const legend = Array.from(fieldset.children).find((child) => child.tagName === \"LEGEND\");\n if (!legend?.contains(control)) return true;\n fieldset = fieldset.parentElement?.closest(\"fieldset[disabled]\") ?? null;\n }\n return false;\n}\n\n/**\n * Whether an element can actually take focus, checked **before** `focus()` runs.\n *\n * A controller that must move focus off a control it is about to disable or hide\n * picks a destination and calls `focus()` on it. If that destination cannot take\n * focus, the call **fails silently**: `hidden` and natively `disabled` elements\n * swallow it, so the caret stays in the subtree that is disappearing and lands on\n * `<body>` a frame later — the exact outcome the rescue exists to prevent, minus\n * any signal that it happened.\n *\n * Testing after the fact is the obvious alternative and is deliberately not the\n * rule. Reading `document.activeElement` back only works in a real browser, and\n * looping over candidates that way performs a real focus move per failure —\n * observable to assistive technology. Checking first costs nothing and catches\n * the cases that actually occur.\n *\n * **`aria-disabled` is not disqualifying.** It is the attribute an author uses\n * for a control that must stay *discoverable*, and the roving contract keeps\n * such items reachable. Only the three conditions that make the platform refuse\n * focus are checked: `hidden` (an ancestor's counts), the native `disabled`\n * property, and `disabled` inherited from an ancestor `fieldset`. CSS-only\n * invisibility is not detectable here and stays the consumer's problem.\n *\n * Reading `:disabled` instead of walking the fieldset chain would be shorter, but\n * that pseudo-class is not evaluated consistently outside real browsers and this\n * has to be right headlessly too. happy-dom in particular focuses a `<button>`\n * inside a disabled fieldset where a real engine refuses, so the inheritance is\n * spelled out rather than delegated.\n *\n * What a consumer does when nothing survives is its own call: some fall back to\n * their landmark, while a widget whose caret already sits somewhere legitimate\n * refuses the move outright rather than relocating it.\n *\n * @example\n * ```ts\n * const target = candidates.find(canTakeFocus);\n * if (target) target.focus();\n * else {\n * this.#tabindex.lend(this.element); // nothing left: fall back to the landmark\n * this.element.focus();\n * }\n * ```\n *\n * @param element - the candidate destination\n */\nexport function canTakeFocus(element: HTMLElement): boolean {\n if (element.closest(\"[hidden]\")) return false;\n if (!(\"disabled\" in element)) return true;\n if ((element as HTMLElement & { disabled: boolean }).disabled) return false;\n return !inheritsFieldsetDisabled(element);\n}\n","/**\n * Unified element-size and viewport observation for Stimeo controllers.\n *\n * Layout-sensitive widgets (sliders, resizable panes, scroll spies, popovers)\n * need to react both to their *own* box changing — via {@link ResizeObserver} —\n * and to the *viewport* changing — via the `window` `resize` event. Wiring those\n * two sources by hand in every controller risks leaked listeners on\n * `disconnect()`. {@link LayoutObserver} owns both behind one callback and one\n * {@link LayoutObserver.disconnect | disconnect()} that releases everything.\n *\n * Behavior only: the helper reports *that* layout changed; it never reads or\n * writes styles. Consumers decide what to recompute.\n */\n\n/** Invoked whenever an observed element or the viewport changes size. */\nexport type LayoutCallback = () => void;\n\n/** Constructs a {@link ResizeObserver}; injectable so tests stay deterministic. */\nexport type ResizeObserverFactory = (callback: ResizeObserverCallback) => ResizeObserver;\n\n/** Options for {@link LayoutObserver}. */\nexport interface LayoutObserverOptions {\n /**\n * Factory for the {@link ResizeObserver} used by {@link LayoutObserver.observe}.\n * Defaults to the global constructor; override it in tests, or to no-op in\n * environments where `ResizeObserver` is unavailable.\n */\n resizeObserverFactory?: ResizeObserverFactory;\n}\n\n/**\n * Observes element resizes and/or viewport resizes through a single callback,\n * with guaranteed teardown.\n *\n * @example\n * ```ts\n * #layout = new LayoutObserver(() => this.#reposition());\n *\n * connect() {\n * this.#layout.observe(this.panelTarget);\n * this.#layout.observeViewport();\n * }\n *\n * disconnect() {\n * this.#layout.disconnect();\n * }\n * ```\n */\nexport class LayoutObserver {\n readonly #callback: LayoutCallback;\n readonly #resizeObserverFactory: ResizeObserverFactory | null;\n #resizeObserver: ResizeObserver | null = null;\n #observingViewport = false;\n\n /** Stable bound handler so add/removeEventListener target the same reference. */\n readonly #handleViewportResize = (): void => {\n this.#callback();\n };\n\n constructor(callback: LayoutCallback, options: LayoutObserverOptions = {}) {\n this.#callback = callback;\n this.#resizeObserverFactory =\n options.resizeObserverFactory ??\n (typeof ResizeObserver === \"undefined\" ? null : (cb) => new ResizeObserver(cb));\n }\n\n /**\n * Starts observing an element's size. Repeated calls observe additional\n * elements through the same shared observer. No-ops when no\n * `ResizeObserver` implementation is available.\n */\n observe(element: Element): void {\n if (!this.#resizeObserverFactory) return;\n if (!this.#resizeObserver) {\n this.#resizeObserver = this.#resizeObserverFactory(() => {\n this.#callback();\n });\n }\n this.#resizeObserver.observe(element);\n }\n\n /** Stops observing a single element while leaving any others in place. */\n unobserve(element: Element): void {\n this.#resizeObserver?.unobserve(element);\n }\n\n /** Starts observing viewport resizes. Idempotent: the listener is added once. */\n observeViewport(): void {\n if (this.#observingViewport) return;\n this.#observingViewport = true;\n window.addEventListener(\"resize\", this.#handleViewportResize);\n }\n\n /** Stops observing viewport resizes without affecting element observation. */\n unobserveViewport(): void {\n if (!this.#observingViewport) return;\n this.#observingViewport = false;\n window.removeEventListener(\"resize\", this.#handleViewportResize);\n }\n\n /**\n * Releases every observation: disconnects the {@link ResizeObserver} and\n * removes the viewport listener. Safe to call multiple times. Call this from a\n * controller's `disconnect()`.\n */\n disconnect(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n this.unobserveViewport();\n }\n}\n","/**\n * Self-cleaning timer registries shared by Stimeo controllers.\n *\n * Stimulus controllers frequently schedule `setTimeout` / `setInterval` work\n * (auto-dismiss, debouncing, polling). When the element leaves the DOM — a\n * Turbo Drive navigation, a Turbo Stream replacement, or any `disconnect()` —\n * orphaned timers keep firing against a detached controller, leaking memory and\n * mutating stale state. {@link SafeTimeout} and {@link SafeInterval} track every\n * timer they create so a single {@link TimerRegistry.clearAll | clearAll()} call\n * in `disconnect()` tears them all down.\n *\n * These are intentionally low-level primitives: they own *registration and\n * cleanup only*. Higher-level policy (pause/resume, remaining-time accounting)\n * stays in the individual controllers so per-widget semantics are not flattened\n * into a lowest-common-denominator helper.\n */\n\n/**\n * Shared registry bookkeeping for the timeout/interval variants.\n *\n * Subclasses provide the scheduling primitive ({@link schedule}) and its matching\n * canceller ({@link cancel}); this base owns the set of live ids plus the\n * per-id and bulk teardown shared by both.\n */\nabstract class TimerRegistry {\n /** Live timer ids that have not yet been cleared (or, for timeouts, fired). */\n protected readonly ids = new Set<number>();\n\n /** Schedules the underlying platform timer and returns its id. */\n protected abstract schedule(callback: () => void, delay: number): number;\n\n /** Cancels the underlying platform timer for `id`. */\n protected abstract cancel(id: number): void;\n\n /**\n * Cancels a single tracked timer.\n *\n * No-ops if the id is unknown (already cleared, fired, or never owned by this\n * registry), so callers can clear defensively without guarding.\n */\n clear(id: number): void {\n if (this.ids.delete(id)) {\n this.cancel(id);\n }\n }\n\n /**\n * Cancels every tracked timer. Call this from a controller's `disconnect()`\n * to guarantee no timer outlives the element.\n */\n clearAll(): void {\n for (const id of this.ids) {\n this.cancel(id);\n }\n this.ids.clear();\n }\n\n /** Number of timers currently tracked (pending). */\n get size(): number {\n return this.ids.size;\n }\n}\n\n/**\n * `setTimeout` wrapper that auto-forgets each timer once it fires and supports\n * bulk teardown on disconnect.\n *\n * @example\n * ```ts\n * #timers = new SafeTimeout();\n *\n * connect() {\n * this.#timers.set(() => this.dismiss(), 5000);\n * }\n *\n * disconnect() {\n * this.#timers.clearAll();\n * }\n * ```\n */\nexport class SafeTimeout extends TimerRegistry {\n /**\n * Schedules `callback` after `delay` ms and returns the timer id.\n *\n * The id is removed from the registry automatically when the timeout fires,\n * so {@link TimerRegistry.size | size} reflects only still-pending timers.\n */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(() => {\n this.ids.delete(id);\n callback();\n }, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setTimeout(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearTimeout(id);\n }\n}\n\n/**\n * `setInterval` wrapper that tracks every interval for bulk teardown on\n * disconnect. Unlike {@link SafeTimeout}, intervals are retained until they are\n * explicitly cleared because they fire repeatedly.\n *\n * @example\n * ```ts\n * #intervals = new SafeInterval();\n *\n * connect() {\n * this.#intervals.set(() => this.tick(), 1000);\n * }\n *\n * disconnect() {\n * this.#intervals.clearAll();\n * }\n * ```\n */\nexport class SafeInterval extends TimerRegistry {\n /** Schedules a repeating `callback` every `delay` ms and returns the timer id. */\n set(callback: () => void, delay: number): number {\n const id = this.schedule(callback, delay);\n this.ids.add(id);\n return id;\n }\n\n protected schedule(callback: () => void, delay: number): number {\n return window.setInterval(callback, delay);\n }\n\n protected cancel(id: number): void {\n window.clearInterval(id);\n }\n}\n","/**\n * Shared bookkeeping for a `tabindex` a controller lends an element temporarily.\n *\n * A controller that must move focus somewhere the author never made focusable\n * (a landmark root, a scroll destination) reaches for the same trick: add a\n * `tabindex` just-in-time and hand it back once it is no longer needed. The\n * borrow is the easy half; the return is what the two conditions below are for.\n *\n * **Returning needs two conditions, not one.** Owning the borrow is not enough:\n * the attribute must also still hold the value this instance wrote. A consumer\n * that changed it afterwards — `tabindex=\"0\"` to make the root its own Tab stop\n * — owns it now, and removing it there silently discards authored markup. The\n * bookkeeping is dropped either way, since the loan is over regardless of who\n * ends up owning the value.\n *\n * **Never borrow over an existing value.** An element that already carries a\n * `tabindex` is the author's to control, so there is nothing to lend and nothing\n * to return.\n *\n * The registry is keyed by element, so a controller borrowing on a single\n * element (`this.element`) and one borrowing across a changing set of targets\n * use the same API — the single-element case is a set of one. It holds no\n * opinion about *when* to borrow or where focus goes next; that stays in the\n * controller.\n *\n * **The API is deliberately two methods.** This file's own doc block is dropped\n * from `dist`, but every member comment is inlined into **each** consumer entry\n * (`tsup` builds with `splitting: false`), so rationale belongs here, only the\n * contract belongs on the members, and every method no consumer calls is still\n * paid for once per consumer entry.\n *\n * @example\n * ```ts\n * readonly #tabindex = new TabindexLoan();\n *\n * #rescueFocus() {\n * this.#tabindex.lend(this.element);\n * this.element.focus();\n * }\n *\n * disconnect() {\n * this.#tabindex.returnAll();\n * }\n * ```\n */\nexport class TabindexLoan<T extends HTMLElement = HTMLElement> {\n readonly #value: string;\n readonly #lent = new Set<T>();\n\n /**\n * @param value - the `tabindex` to lend. `\"-1\"` (the default) is\n * programmatically focusable but not a Tab stop; `\"0\"` is a real Tab stop,\n * which a scroll region with no focusable content of its own needs.\n */\n constructor(value: string = \"-1\") {\n this.#value = value;\n }\n\n /** Lends `element` the value; no-ops when it already carries a `tabindex`. */\n lend(element: T): void {\n if (element.hasAttribute(\"tabindex\")) return;\n element.setAttribute(\"tabindex\", this.#value);\n this.#lent.add(element);\n }\n\n /** Takes back every loan whose value is still the one that was lent. */\n returnAll(): void {\n for (const element of this.#lent) {\n if (element.getAttribute(\"tabindex\") === this.#value) element.removeAttribute(\"tabindex\");\n }\n this.#lent.clear();\n }\n}\n","import { Controller } from \"@hotwired/stimulus\";\nimport { BeforeCacheReset } from \"../utils/before_cache_reset\";\nimport { canTakeFocus } from \"../utils/focus_candidate\";\nimport { LayoutObserver } from \"../utils/layout_observer\";\nimport { SafeTimeout } from \"../utils/safe_timeout\";\nimport { TabindexLoan } from \"../utils/tabindex_loan\";\nimport type { MenuController } from \"./menu_controller\";\n\n/** Marks an item that currently lives in the More menu (survives a DOM snapshot). */\nconst BANKED = \"data-stimeo--overflow-menu-banked\";\n/** Canonical index persisted while anything is banked, so a fresh instance can re-adopt. */\nconst INDEX = \"data-stimeo--overflow-menu-index\";\n/** Inert split point retained only while every managed item is banked. */\nconst BOUNDARY = \"data-stimeo--overflow-menu-boundary\";\n/** Authored values saved while an item wears menu semantics (\"\" = attribute was absent). */\nconst SAVED_ROLE = \"data-stimeo--overflow-menu-role\";\nconst SAVED_TABINDEX = \"data-stimeo--overflow-menu-tabindex\";\nconst SAVED_MENU_TARGET = \"data-stimeo--overflow-menu-menu-target\";\n/** Menu's target attribute — set to `item` while banked so Menu drives the item. */\nconst MENU_TARGET = \"data-stimeo--menu-target\";\n/** Everything this controller writes on an item; all removed on the way back to the bar. */\nconst BOOKKEEPING = [BANKED, INDEX, SAVED_ROLE, SAVED_TABINDEX, SAVED_MENU_TARGET] as const;\n\n/** `ParentNode.moveBefore` (Chromium 133+): relocates a node without removing it first. */\ninterface MovableParent {\n moveBefore?: (node: Node, child: Node | null) => void;\n}\n\n/**\n * Headless **overflow / priority menu**: items that no longer fit their container are\n * moved into a \"More\" dropdown (lowest `data-priority` first) and moved back as space\n * returns, watched with a {@link ResizeObserver} (no dedicated APG pattern — a\n * composition; the menu's a11y is delegated to Menu, so it is not re-implemented).\n *\n * Markup contract (identifier: `stimeo--overflow-menu`):\n * <nav data-controller=\"stimeo--overflow-menu\" aria-label=\"Actions\">\n * <div data-stimeo--overflow-menu-target=\"items\">\n * <button data-priority=\"1\">Save</button>\n * <button>Delete</button>\n * </div>\n * <div data-controller=\"stimeo--menu\" data-stimeo--overflow-menu-target=\"more\" hidden>\n * <button id=\"more-trigger\" data-stimeo--menu-target=\"trigger\"\n * aria-haspopup=\"menu\" aria-expanded=\"false\"\n * data-action=\"click->stimeo--menu#toggle\n * keydown->stimeo--menu#onTriggerKeydown\">More</button>\n * <div role=\"menu\" aria-labelledby=\"more-trigger\"\n * data-stimeo--menu-target=\"menu\" hidden></div>\n * </div>\n * </div>\n *\n * This controller does not own the root's role. It ships none: a navigation bar is\n * a named `<nav>` whose items stay in the normal Tab order. A consumer may add\n * `role=\"toolbar\"`, but that alone is not an APG Toolbar — the single-tab-stop\n * roving is {@link ToolbarController}'s behavior, not this one's — and a named\n * role still needs `aria-label` / `aria-labelledby`.\n *\n * Two parts of that contract are load-bearing and easy to drop. The banked-items\n * container is a permissive single `role=\"menu\"` element this controller appends to\n * directly; use a `<div>`, since a `<ul>` cannot directly own the moved controls. And the\n * trigger's `data-action` is **required, not decoration**: without it the More button\n * never opens, and `keydown->stimeo--menu#onTriggerKeydown` is what makes it reachable\n * by keyboard at all (`Enter` / `Space` / `ArrowDown`). It is spelled out above rather\n * than referenced, because the keyboard half of this contract lives *only* in the\n * consumer's markup — nothing in this controller's source would reveal its absence.\n * Items need no bindings of their own — Menu delegates their handling from its own\n * element, so a control that only becomes a menu item at runtime is operable the\n * moment it lands.\n *\n * On connect (and every debounced resize) it measures the items against the container's\n * content width and, when they overflow, banks the lowest-priority ones into the More\n * menu — giving each `role=\"menuitem\"` / `tabindex=\"-1\"` and the menu's `item` target so\n * Menu drives it — until the rest fit beside the More button. When nothing overflows the\n * More wrapper (button *and* menu) is `hidden`. The controller element carries\n * `data-overflowing` / `data-overflow-count`, and a `change` event fires on connect and\n * on every later transition.\n *\n * @remarks\n * **Measuring.** The container's width must not be derived from its content (give the bar\n * an explicit width, `flex: 1`, or plain block layout): the More button is revealed before\n * measuring, so a shrink-to-fit container always reports \"items + gap + More\" and nothing\n * ever overflows. The budget is the container's *content box* (`clientWidth` minus its\n * horizontal padding); the gap between items comes from the items container, the gap\n * reserved for the More button from the bar itself. Item widths are cached (a natural\n * width is location-independent) so a pass reads only the items in the bar — one reflow,\n * not two. The trade-off: an item whose content changes *while banked* (a locale switch, a\n * badge update) keeps its stale width until it is back in the bar, so it may return one\n * pass late; re-measuring it in place would cost a second reflow every pass. An item the\n * author marked `hidden` is out of the budget, out of the drop order, and never banked; it\n * holds its canonical slot and rejoins as soon as the attribute goes away. Toggling\n * `hidden` is an attribute change, not a resize, so call `update` after it.\n *\n * **Moving.** Items are moved (never cloned), and only the nodes that are actually out of\n * place — a pass that changes nothing touches no node, because re-inserting a node removes\n * it first and the browser then drops focus to `<body>`. Where `moveBefore` is supported\n * the move preserves focus and transient element state outright.\n *\n * **Focus.** When the focused item (or a descendant of it) *starts* retreating into a\n * collapsed menu it would be hidden and lose focus, so focus is redirected to the More\n * trigger (falling back to the More wrapper when the markup has no trigger — give it one,\n * or focus is left to the browser). While the menu is expanded the item stays visible, so\n * focus is left alone — unless the focused item is the one returning to the bar, which\n * takes focus out of the wrapper and leaves the expanded menu with nothing that owns it;\n * the menu is then closed and focus stays on the returned item. When the last banked item\n * returns, the wrapper is about to be hidden: the menu is closed and focus is moved out of\n * it to the last item that can actually hold it (`hidden` and disabled ones cannot), or to\n * the root when none can.\n *\n * **Priority.** Lower `data-priority` is kept longer; a value that is absent, empty, or\n * not a number ranks lowest and drops first.\n *\n * **Turbo.** The managed set and the canonical order are rebuilt *from the DOM* every\n * pass, so a fresh `connect()` onto markup that already holds banked items (cache restore,\n * a morph, a clone, server-rendered overflow) re-adopts them instead of orphaning them\n * inside a wrapper it would then hide. Symmetrically, `disconnect()` and\n * `turbo:before-cache` return every item to the bar, collapse the composed menu (so it\n * releases its dismissal-stack membership rather than being snapshotted mid-gesture), and\n * strip this controller's bookkeeping attributes, so a cached snapshot is always the\n * pristine authored DOM. The `ResizeObserver` and debounce timer are released on\n * `disconnect()` too.\n *\n * Behavior only — no styling.\n */\nexport class OverflowMenuController extends Controller<HTMLElement> {\n static override targets = [\"items\", \"more\"];\n static override values = {\n moreLabel: { type: String, default: \"More\" },\n debounce: { type: Number, default: 100 },\n };\n static actions = [\"update\"] as const;\n static events = [\"change\"] as const;\n\n declare readonly itemsTarget: HTMLElement;\n declare readonly moreTarget: HTMLElement;\n declare readonly hasItemsTarget: boolean;\n declare readonly hasMoreTarget: boolean;\n\n declare moreLabelValue: string;\n declare debounceValue: number;\n\n readonly #layout = new LayoutObserver(() => this.#scheduleUpdate());\n readonly #timers = new SafeTimeout();\n /** The managed items in canonical (authored) order, rebuilt from the DOM each pass. */\n #items: HTMLElement[] = [];\n #index = new WeakMap<HTMLElement, number>();\n /** Cached bar-context width per item; see the class remarks for the staleness caveat. */\n #widths = new WeakMap<HTMLElement, number>();\n /** Last reported overflow count, so `change` fires only on transitions. */\n #lastHidden: number | null = null;\n /** The `tabindex` this instance lends the root for the focus fallback. */\n readonly #tabindex = new TabindexLoan();\n\n /** Hands Turbo a pristine snapshot of the bar, with every item back in place. */\n readonly #beforeCache = new BeforeCacheReset(() => this.#restoreAll());\n\n override connect(): void {\n if (!this.hasItemsTarget || !this.hasMoreTarget) return;\n\n const trigger = this.#trigger();\n if (trigger !== null && this.#isBareTrigger(trigger)) {\n trigger.textContent = this.moreLabelValue;\n }\n\n this.#beforeCache.activate();\n this.#layout.observe(this.element);\n this.#layout.observeViewport();\n this.update();\n }\n\n override disconnect(): void {\n this.#layout.disconnect();\n this.#timers.clearAll();\n this.#beforeCache.deactivate();\n this.#restoreAll();\n this.#lastHidden = null;\n }\n\n /** Re-measures and rebalances items between the bar and the More menu. */\n update(): void {\n if (!this.hasItemsTarget || !this.hasMoreTarget) return;\n this.#syncItems();\n\n // Reveal More so its trigger is measurable, then refresh the widths of the items\n // currently in the bar (menu items keep their location-independent last value).\n this.moreTarget.hidden = false;\n // Server-rendered overflow arrives with items already in the menu, which is\n // hidden, so they measure zero and the budget would read as \"everything fits\".\n // Bring the set back to the bar once, unbanked, so the first balance works from\n // real widths taken in the context the items are actually laid out in — a\n // banked item can carry consumer styling of its own.\n if (\n this.#items.some((item) => item.parentElement !== this.itemsTarget && !this.#widths.has(item))\n ) {\n this.#removeBoundary();\n for (const item of this.#items) this.#unbank(item);\n this.#reorder(this.itemsTarget, this.#items);\n }\n for (const item of this.#items) {\n if (item.parentElement === this.itemsTarget) this.#widths.set(item, item.offsetWidth);\n }\n const moreWidth = (this.#trigger() ?? this.moreTarget).offsetWidth;\n const itemGap = this.#gap(this.itemsTarget); // between the items themselves\n const barGap = this.#gap(this.element); // between the items row and the More button\n\n const widthOf = (el: HTMLElement): number => this.#widths.get(el) ?? el.offsetWidth;\n const containerWidth = this.element.clientWidth - this.#paddingX(this.element);\n // An authored `hidden` item occupies no width, but a naive count would still\n // charge a gap for it and could bank a sibling that in fact fits — or raise a\n // More button whose menu has nothing operable in it. It keeps its canonical\n // slot; it just does not take part in the budget or in the drop order.\n const rendered = this.#items.filter((item) => this.#rendered(item));\n const itemsWidth = rendered.reduce((sum, el) => sum + widthOf(el), 0);\n let visibleWidth = itemsWidth + Math.max(0, rendered.length - 1) * itemGap;\n\n const hidden = new Set<HTMLElement>();\n if (visibleWidth > containerWidth) {\n const budget = containerWidth - moreWidth - barGap; // reserve the More button + its gap\n // Drop lowest-retention first: no usable `data-priority` (rank ∞), then highest\n // number; ties broken right-to-left so leading items survive.\n const dropOrder = [...rendered].sort(\n (a, b) => this.#rank(b) - this.#rank(a) || this.#indexOf(b) - this.#indexOf(a),\n );\n for (const item of dropOrder) {\n if (visibleWidth <= budget) break;\n hidden.add(item);\n visibleWidth -= widthOf(item) + itemGap; // dropping an item frees its width and a gap\n }\n }\n\n // Decided before any node moves, so it cannot race the browser's blur.\n const active = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const focused = active === null ? null : this.#ownerOf(active);\n const retreating =\n focused !== null &&\n hidden.has(focused) &&\n focused.parentElement === this.itemsTarget && // i.e. *starting* to retreat\n !this.#menuExpanded();\n // The mirror image: the item holding focus is on its way *out* of an expanded\n // menu. Focus rides along with the node, but once it sits outside the More\n // wrapper the menu owns nothing that reaches it — the shared dismissal\n // resolver stops claiming for this layer, and the item's own menu bindings\n // fall out of Stimulus scope. Leaving the menu open would strand it with no\n // owner, so it is collapsed after the move (see below).\n const returning =\n focused !== null &&\n !hidden.has(focused) &&\n focused.parentElement !== this.itemsTarget && // i.e. *leaving* the menu\n this.#menuExpanded();\n\n // A fully-banked snapshot retains an inert split point so a fresh controller can\n // tell prepend from append. Once a real item remains in the bar, its saved index is\n // the stronger anchor and the boundary must not participate in DOM reordering.\n if (hidden.size === 0 || hidden.size !== this.#items.length) this.#removeBoundary();\n\n // The menu pass runs first, so retreating items leave the bar before it is reordered\n // (otherwise every trailing item would be shuffled needlessly).\n for (const item of this.#items) {\n if (hidden.has(item)) this.#bank(item);\n else this.#unbank(item);\n }\n this.#reorder(\n this.#menuList(),\n this.#items.filter((item) => hidden.has(item)),\n );\n this.#reorder(\n this.itemsTarget,\n this.#items.filter((item) => !hidden.has(item)),\n );\n\n if (retreating) (this.#trigger() ?? this.moreTarget).focus();\n else if (active !== null && this.#lostFocus(active)) active.focus();\n\n const count = hidden.size;\n // Keep the canonical positions on both sides while overflow exists. If the bar is\n // emptied, also retain an inert split point: a later prepend lands before it and an\n // append after it, preserving intent when a fresh controller adopts the snapshot.\n for (const item of this.#items) {\n if (count > 0) item.setAttribute(INDEX, String(this.#indexOf(item)));\n else item.removeAttribute(INDEX);\n }\n if (count > 0 && count === this.#items.length) this.#ensureBoundary();\n else this.#removeBoundary();\n const inMore =\n document.activeElement instanceof HTMLElement &&\n this.moreTarget.contains(document.activeElement);\n if (count === 0 || returning) {\n // Either the wrapper is about to be hidden — collapse the menu so it cannot\n // reappear expanded without a gesture, and move focus out before it\n // disappears — or the item that held focus just carried it out of the menu.\n // `close()` rather than the dismissal path, so the trigger does not take\n // back focus the user is now holding on the returned item; `inMore` is false\n // in that case, so the rescue below stays out of the way. Items still banked\n // remain reachable by reopening from the trigger.\n this.#closeMenu();\n if (inMore) this.#rescueFocus();\n }\n this.moreTarget.hidden = count === 0;\n if (count > 0) this.element.setAttribute(\"data-overflowing\", \"true\");\n else this.element.removeAttribute(\"data-overflowing\");\n this.element.setAttribute(\"data-overflow-count\", String(count));\n\n if (this.#lastHidden !== count) {\n this.#lastHidden = count;\n this.dispatch(\"change\", { detail: { visible: this.#items.length - count, hidden: count } });\n }\n }\n\n /** The flex `column-gap` on `el` in px (0 when none / unsupported). */\n #gap(el: HTMLElement): number {\n const style = this.#styleOf(el);\n return style === null ? 0 : this.#px(style.columnGap || style.gap);\n }\n\n /** Horizontal padding on `el` in px — `clientWidth` counts it, the content box cannot. */\n #paddingX(el: HTMLElement): number {\n const style = this.#styleOf(el);\n return style === null ? 0 : this.#px(style.paddingLeft) + this.#px(style.paddingRight);\n }\n\n #styleOf(el: HTMLElement): CSSStyleDeclaration | null {\n return typeof window.getComputedStyle === \"function\" ? window.getComputedStyle(el) : null;\n }\n\n #px(value: string | undefined): number {\n const parsed = Number.parseFloat(value ?? \"\");\n return Number.isNaN(parsed) ? 0 : parsed;\n }\n\n /**\n * Rebuilds the managed set and the canonical order from the DOM. The bar's children\n * give the order of everything inline (so a leading insert is not silently appended)\n * and {@link #merge} weaves the banked items back among them.\n */\n #syncItems(): void {\n const previous = this.#items;\n const bar: HTMLElement[] = [];\n let boundaryAt: number | undefined;\n for (const el of this.itemsTarget.children) {\n if (el instanceof HTMLTemplateElement && el.hasAttribute(BOUNDARY)) {\n boundaryAt ??= bar.length;\n continue;\n }\n if (el instanceof HTMLElement) bar.push(el);\n }\n\n const banked: HTMLElement[] = [];\n for (const el of this.#menuList().children) {\n if (el instanceof HTMLElement && el.hasAttribute(BANKED)) banked.push(el);\n }\n banked.sort((a, b) => this.#bankedIndex(a) - this.#bankedIndex(b));\n\n const items = this.#merge(bar, banked, boundaryAt);\n\n // An item re-homed elsewhere is no longer ours, but it would keep the menu\n // semantics we gave it — strip them before dropping it from the set.\n for (const el of previous) {\n if (!items.includes(el)) {\n this.#unbank(el);\n el.removeAttribute(INDEX);\n }\n }\n\n this.#items = items;\n this.#index = new WeakMap();\n items.forEach((el, i) => {\n this.#index.set(el, i);\n });\n }\n\n /**\n * Interleaves the banked items back among the bar's children.\n *\n * A saved index is a position in the *canonical* order, so it can only be compared\n * against another canonical position — never used as an offset into the current bar,\n * which is a shorter and differently-indexed list. (Doing so survives an untouched\n * round trip and silently scrambles the order as soon as the consumer inserts into a\n * bar that is already short, and `#bank()` then burns the scrambled index back into\n * the attribute, so widening never heals it.) Each bar child the controller already\n * knows carries its canonical index from the previous pass; a banked item goes in\n * front of the first known child whose index is higher.\n *\n * Children never seen before — inserted by the consumer since the last pass — have no\n * canonical position yet, so they keep their DOM neighbours. The exception is a\n * *trailing* run of them: appending to the bar means appending to the toolbar, so\n * everything banked is emitted before it.\n *\n * With no known child at all (a fresh instance connecting to markup that already\n * holds banked items), a fully-banked snapshot's inert boundary preserves whether an\n * unindexed run was prepended or appended before connect. Older or server-rendered\n * markup has no boundary; for that compatibility path the saved index is used as the\n * offset, the inverse of the move that banked it.\n */\n #merge(\n bar: readonly HTMLElement[],\n banked: readonly HTMLElement[],\n boundaryAt?: number,\n ): HTMLElement[] {\n const canonical = bar.map((el) => this.#index.get(el) ?? this.#savedIndex(el));\n let lastKnown = -1;\n canonical.forEach((index, i) => {\n if (index !== undefined) lastKnown = i;\n });\n\n if (lastKnown === -1) {\n if (boundaryAt !== undefined) {\n return [...bar.slice(0, boundaryAt), ...banked, ...bar.slice(boundaryAt)];\n }\n const restored = [...bar];\n for (const item of banked) {\n restored.splice(Math.min(this.#bankedIndex(item), restored.length), 0, item);\n }\n return restored;\n }\n\n const items: HTMLElement[] = [];\n let next = 0;\n const drainWhile = (accept: (saved: number) => boolean): void => {\n while (next < banked.length) {\n const item = banked[next];\n if (item === undefined || !accept(this.#bankedIndex(item))) break;\n items.push(item);\n next++;\n }\n };\n\n bar.forEach((el, i) => {\n const index = canonical[i];\n if (index !== undefined) drainWhile((saved) => saved < index);\n else if (i > lastKnown) drainWhile(() => true);\n items.push(el);\n });\n drainWhile(() => true);\n return items;\n }\n\n /** The canonical index a banked item saved, or ∞ (append) when it carries none. */\n #bankedIndex(item: HTMLElement): number {\n return this.#savedIndex(item) ?? Number.POSITIVE_INFINITY;\n }\n\n /** A finite canonical index stored on either side of the overflow split. */\n #savedIndex(item: HTMLElement): number | undefined {\n const raw = item.getAttribute(INDEX);\n if (raw === null) return undefined;\n const value = Number(raw);\n return Number.isFinite(value) ? value : undefined;\n }\n\n /** The inert split point written only when every managed item lives in More. */\n #boundary(): HTMLTemplateElement | null {\n for (const el of this.itemsTarget.children) {\n if (el instanceof HTMLTemplateElement && el.hasAttribute(BOUNDARY)) return el;\n }\n return null;\n }\n\n #ensureBoundary(): void {\n if (this.#boundary() !== null) return;\n const boundary = document.createElement(\"template\");\n boundary.setAttribute(BOUNDARY, \"\");\n this.itemsTarget.appendChild(boundary);\n }\n\n #removeBoundary(): void {\n this.#boundary()?.remove();\n }\n\n /** Debounced re-measure for resize-driven churn. */\n #scheduleUpdate(): void {\n this.#timers.clearAll();\n this.#timers.set(() => this.update(), this.debounceValue);\n }\n\n /** Returns the menu list the items are banked into (falls back to the More wrapper). */\n #menuList(): HTMLElement {\n return (\n this.moreTarget.querySelector<HTMLElement>('[data-stimeo--menu-target=\"menu\"]') ??\n this.moreTarget\n );\n }\n\n #trigger(): HTMLElement | null {\n return this.moreTarget.querySelector<HTMLElement>('[data-stimeo--menu-target=\"trigger\"]');\n }\n\n /**\n * Whether the More trigger is bare enough for the label to be safe to write.\n * Assigning `textContent` replaces *every* child node, so a trigger holding an\n * icon would silently lose it — and the loss is permanent, since the restore\n * pass returns items but not authored trigger content. A trigger that already\n * carries an accessible name is left alone too: injecting visible text under a\n * different `aria-label` would make the label and the name disagree. A trigger\n * with neither text, nor children, nor a name has nothing to lose and gets the\n * fallback; one that is empty *and* unnamed is the only case the label rescues.\n */\n #isBareTrigger(trigger: HTMLElement): boolean {\n return (\n (trigger.textContent ?? \"\").trim() === \"\" &&\n trigger.firstElementChild === null &&\n !trigger.hasAttribute(\"aria-label\") &&\n !trigger.hasAttribute(\"aria-labelledby\")\n );\n }\n\n /**\n * Whether the More menu is expanded. Menu owns that state and reflects it on the\n * trigger's `aria-expanded`, so read the contract rather than guess from `hidden`\n * (which is absent until Menu connects).\n */\n #menuExpanded(): boolean {\n return this.#trigger()?.getAttribute(\"aria-expanded\") === \"true\";\n }\n\n /**\n * Collapses the More menu before its wrapper is hidden. Menu owns the state (and the\n * Escape-stack membership that goes with it), so ask it; the DOM fallback covers markup\n * that reached an expanded state with no Menu mounted.\n */\n #closeMenu(): void {\n if (!this.#menuExpanded()) return;\n const menu = this.application.getControllerForElementAndIdentifier(\n this.moreTarget,\n \"stimeo--menu\",\n ) as MenuController | null;\n if (menu) {\n menu.close();\n return;\n }\n this.#trigger()?.setAttribute(\"aria-expanded\", \"false\");\n const list = this.#menuList();\n if (list !== this.moreTarget) list.hidden = true;\n }\n\n /** The managed item that is, or contains, `el` — focus rescue works on either. */\n #ownerOf(el: HTMLElement): HTMLElement | null {\n return this.#items.find((item) => item === el || item.contains(el)) ?? null;\n }\n\n /** Whether the item takes up room in the bar; an authored `hidden` one does not. */\n #rendered(item: HTMLElement): boolean {\n return !item.hasAttribute(\"hidden\");\n }\n\n /**\n * Moves focus out of the More wrapper just before it is hidden, to the last\n * item in canonical order that can hold it. When every item refuses, the root\n * takes focus instead of letting the browser drop it to `<body>`, borrowing a\n * `tabindex=\"-1\"` just-in-time — not a Tab stop, and handed back on restore\n * when this controller was the one that added it.\n */\n #rescueFocus(): void {\n for (let i = this.#items.length - 1; i >= 0; i--) {\n const item = this.#items[i];\n // The shared pre-check, not `#rendered`: that one answers \"does this item\n // take up room in the bar\", which reads only the item's own `hidden`. Focus\n // eligibility has to see an ancestor's too — the same rule `#lostFocus`\n // applies below.\n if (item !== undefined && canTakeFocus(item)) {\n item.focus();\n return;\n }\n }\n this.#tabindex.lend(this.element);\n this.element.focus();\n }\n\n /**\n * Whether `el` held focus, is still in a visible part of this controller, and lost it —\n * what a re-insert does in a real browser. An item that retreated into a collapsed menu\n * is excluded: it sits in a `hidden` subtree and must not be focused back.\n */\n #lostFocus(el: HTMLElement): boolean {\n return (\n el.isConnected &&\n document.activeElement !== el &&\n this.element.contains(el) &&\n el.closest(\"[hidden]\") === null\n );\n }\n\n /** Returns every item to the bar and removes all traces of this controller. */\n #restoreAll(): void {\n if (!this.hasItemsTarget || !this.hasMoreTarget) return;\n this.#syncItems();\n this.#removeBoundary();\n this.#reorder(this.itemsTarget, this.#items);\n for (const item of this.#items) {\n this.#unbank(item);\n item.removeAttribute(INDEX);\n }\n // The wrapper is being hidden for good, so the composed menu must not stay\n // expanded behind it: an unclosed menu keeps its dismissal-stack membership\n // and would be written into a Turbo snapshot mid-gesture. Focus is left\n // exactly where it is — this path runs at teardown, where moving it would be\n // the surprise.\n this.#closeMenu();\n this.moreTarget.hidden = true;\n this.element.removeAttribute(\"data-overflowing\");\n this.element.removeAttribute(\"data-overflow-count\");\n this.#tabindex.returnAll();\n }\n\n /**\n * Makes `parent`'s managed children match `sequence`, moving only what is out of place.\n * Walking backwards lets each item be compared against the element that should follow\n * it, so an unchanged run costs zero DOM mutations — the point of the exercise, since\n * every re-insert blurs the focused node.\n */\n #reorder(parent: HTMLElement, sequence: readonly HTMLElement[]): void {\n let next: HTMLElement | null = null;\n for (let i = sequence.length - 1; i >= 0; i--) {\n const item = sequence[i];\n if (item === undefined) continue;\n if (item.parentElement !== parent || item.nextElementSibling !== next) {\n this.#insert(parent, item, next);\n }\n next = item;\n }\n }\n\n /** Relocates `item`, preferring `moveBefore` (keeps focus and element state). */\n #insert(parent: HTMLElement, item: HTMLElement, before: HTMLElement | null): void {\n const move = (parent as HTMLElement & MovableParent).moveBefore;\n if (typeof move === \"function\") {\n try {\n move.call(parent, item, before);\n return;\n } catch {\n // Not movable in place (e.g. a disconnected node) — fall through.\n }\n }\n parent.insertBefore(item, before);\n }\n\n /**\n * Gives an item menuitem semantics for Menu to drive and records its canonical index,\n * saving every authored value it overwrites (\"\" means the attribute was absent).\n */\n #bank(item: HTMLElement): void {\n if (!item.hasAttribute(BANKED)) {\n item.setAttribute(BANKED, \"true\");\n item.setAttribute(SAVED_ROLE, item.getAttribute(\"role\") ?? \"\");\n item.setAttribute(SAVED_TABINDEX, item.getAttribute(\"tabindex\") ?? \"\");\n item.setAttribute(SAVED_MENU_TARGET, item.getAttribute(MENU_TARGET) ?? \"\");\n item.setAttribute(\"role\", \"menuitem\");\n item.setAttribute(\"tabindex\", \"-1\");\n item.setAttribute(MENU_TARGET, \"item\");\n }\n item.setAttribute(INDEX, String(this.#indexOf(item)));\n }\n\n /** Undoes the banking: restores every authored value and drops the bookkeeping. */\n #unbank(item: HTMLElement): void {\n if (!item.hasAttribute(BANKED)) return;\n this.#restoreAttr(item, \"role\", item.getAttribute(SAVED_ROLE));\n this.#restoreAttr(item, \"tabindex\", item.getAttribute(SAVED_TABINDEX));\n this.#restoreAttr(item, MENU_TARGET, item.getAttribute(SAVED_MENU_TARGET));\n for (const name of BOOKKEEPING) item.removeAttribute(name);\n }\n\n /** Re-applies a saved attribute value, or removes the attribute when it was absent. */\n #restoreAttr(item: HTMLElement, name: string, original: string | null): void {\n if (original === null || original === \"\") item.removeAttribute(name);\n else item.setAttribute(name, original);\n }\n\n #indexOf(item: HTMLElement): number {\n return this.#index.get(item) ?? 0;\n }\n\n /**\n * Retention rank: lower keeps longer. An absent, empty, or non-numeric `data-priority`\n * ranks lowest (drops first) — empty is the common ERB accident\n * (`data-priority=\"<%= maybe_nil %>\"`), and `Number(\"\")` is 0, which would otherwise\n * read as the *highest* retention.\n */\n #rank(item: HTMLElement): number {\n const raw = item.getAttribute(\"data-priority\");\n if (raw === null || raw.trim() === \"\") return Number.POSITIVE_INFINITY;\n const value = Number(raw);\n return Number.isNaN(value) ? Number.POSITIVE_INFINITY : value;\n }\n}\n"]}
@@ -61,6 +61,10 @@ declare class ProgressController extends Controller<HTMLElement> {
61
61
  type: StringConstructor;
62
62
  default: string;
63
63
  };
64
+ announceText: {
65
+ type: StringConstructor;
66
+ default: string;
67
+ };
64
68
  };
65
69
  static actions: readonly ["setValue"];
66
70
  static events: readonly ["change", "complete"];
@@ -71,15 +75,26 @@ declare class ProgressController extends Controller<HTMLElement> {
71
75
  maxValue: number;
72
76
  indeterminateValue: boolean;
73
77
  valueTextValue: string;
78
+ announceTextValue: string;
74
79
  connect(): void;
80
+ /** Closes the window in which a queued repaint may still run. */
81
+ disconnect(): void;
75
82
  /**
76
83
  * Updates the progress value from an action param (`amount`) or a
77
84
  * `detail.value` CustomEvent, normalizes it into range, syncs ARIA, and
78
85
  * dispatches `change` (always) plus `complete` when `max` is reached.
79
86
  */
80
87
  setValue(event: SetValueEvent): void;
81
- /** Re-render when the indeterminate flag is toggled via its data attribute. */
88
+ /** Repaints when application code (or a Turbo morph) changes `indeterminate` at runtime. */
82
89
  indeterminateValueChanged(): void;
90
+ /** Repaints when application code (or a Turbo morph) changes `value` at runtime. */
91
+ valueValueChanged(): void;
92
+ /** Repaints when application code (or a Turbo morph) changes `min` at runtime. */
93
+ minValueChanged(): void;
94
+ /** Repaints when application code (or a Turbo morph) changes `max` at runtime. */
95
+ maxValueChanged(): void;
96
+ /** Repaints when application code (or a Turbo morph) changes `valueText` at runtime. */
97
+ valueTextValueChanged(): void;
83
98
  }
84
99
 
85
100
  export { ProgressController };
@@ -2,6 +2,23 @@ import { Controller } from '@hotwired/stimulus';
2
2
 
3
3
  // src/controllers/progress_controller.ts
4
4
 
5
+ // src/utils/announce.ts
6
+ function announce(message, options = {}) {
7
+ const text = message.trim();
8
+ if (text.length === 0) return;
9
+ window.dispatchEvent(
10
+ new CustomEvent("stimeo--announcer:announce", {
11
+ detail: { message: text, assertive: options.assertive === true }
12
+ })
13
+ );
14
+ }
15
+ function fillTemplate(template, values) {
16
+ return template.replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (match, name) => {
17
+ const replacement = values[name];
18
+ return replacement === void 0 ? match : String(replacement);
19
+ });
20
+ }
21
+
5
22
  // src/utils/coerce.ts
6
23
  function toFiniteNumber(raw) {
7
24
  if (raw === null || raw === void 0 || raw === "") return null;
@@ -9,7 +26,57 @@ function toFiniteNumber(raw) {
9
26
  return Number.isFinite(value) ? value : null;
10
27
  }
11
28
 
29
+ // src/utils/microtask_coalescer.ts
30
+ var MicrotaskCoalescer = class {
31
+ #run;
32
+ #queued = false;
33
+ #active = false;
34
+ #generation = 0;
35
+ /** @param run - the single reconciliation pass, invoked at most once per batch. */
36
+ constructor(run) {
37
+ this.#run = run;
38
+ }
39
+ /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
40
+ activate() {
41
+ this.#active = true;
42
+ }
43
+ /** Closes the window and drops any pending pass; call from `disconnect()`. */
44
+ cancel() {
45
+ this.#active = false;
46
+ this.#queued = false;
47
+ this.#generation += 1;
48
+ }
49
+ /** Requests one pass after the batch settles. Idempotent; inert outside the window. */
50
+ schedule() {
51
+ if (!this.#active || this.#queued) return;
52
+ this.#queued = true;
53
+ const generation = this.#generation;
54
+ queueMicrotask(() => {
55
+ if (generation !== this.#generation || !this.#queued || !this.#active) return;
56
+ this.#queued = false;
57
+ this.#run();
58
+ });
59
+ }
60
+ };
61
+
62
+ // src/utils/range.ts
63
+ function rangeFraction(value, min, max) {
64
+ const span = max - min;
65
+ if (!(span > 0)) return 0;
66
+ const clamped = Math.min(max, Math.max(min, value));
67
+ let fraction;
68
+ if (Number.isFinite(span)) {
69
+ fraction = (clamped - min) / span;
70
+ } else {
71
+ const scale = Math.max(Math.abs(min), Math.abs(max));
72
+ fraction = (clamped / scale - min / scale) / (max / scale - min / scale);
73
+ }
74
+ if (!Number.isFinite(fraction)) return 0;
75
+ return Math.min(1, Math.max(0, fraction));
76
+ }
77
+
12
78
  // src/controllers/progress_controller.ts
79
+ var OWNED_VALUE_TEXT = "data-stimeo--progress-owns-valuetext";
13
80
  var ProgressController = class extends Controller {
14
81
  static targets = ["bar"];
15
82
  static values = {
@@ -17,13 +84,27 @@ var ProgressController = class extends Controller {
17
84
  min: { type: Number, default: 0 },
18
85
  max: { type: Number, default: 100 },
19
86
  indeterminate: { type: Boolean, default: false },
20
- valueText: { type: String, default: "" }
87
+ valueText: { type: String, default: "" },
88
+ announceText: { type: String, default: "" }
21
89
  };
22
90
  static actions = ["setValue"];
23
91
  static events = ["change", "complete"];
92
+ /**
93
+ * Collapses a morph that swaps several render inputs at once into one repaint.
94
+ * A single update usually rewrites the whole set, and each Value would otherwise
95
+ * repaint on its own.
96
+ */
97
+ #repaint = new MicrotaskCoalescer(() => {
98
+ this.#render();
99
+ });
24
100
  connect() {
101
+ this.#repaint.activate();
25
102
  this.#render();
26
103
  }
104
+ /** Closes the window in which a queued repaint may still run. */
105
+ disconnect() {
106
+ this.#repaint.cancel();
107
+ }
27
108
  /**
28
109
  * Updates the progress value from an action param (`amount`) or a
29
110
  * `detail.value` CustomEvent, normalizes it into range, syncs ARIA, and
@@ -39,11 +120,30 @@ var ProgressController = class extends Controller {
39
120
  this.dispatch("change", { detail: { value, ratio: this.#ratio } });
40
121
  if (value >= this.maxValue) {
41
122
  this.dispatch("complete", { detail: { value } });
123
+ announce(
124
+ fillTemplate(this.announceTextValue, { value, percent: Math.round(this.#ratio * 100) })
125
+ );
42
126
  }
43
127
  }
44
- /** Re-render when the indeterminate flag is toggled via its data attribute. */
128
+ /** Repaints when application code (or a Turbo morph) changes `indeterminate` at runtime. */
45
129
  indeterminateValueChanged() {
46
- this.#render();
130
+ this.#repaint.schedule();
131
+ }
132
+ /** Repaints when application code (or a Turbo morph) changes `value` at runtime. */
133
+ valueValueChanged() {
134
+ this.#repaint.schedule();
135
+ }
136
+ /** Repaints when application code (or a Turbo morph) changes `min` at runtime. */
137
+ minValueChanged() {
138
+ this.#repaint.schedule();
139
+ }
140
+ /** Repaints when application code (or a Turbo morph) changes `max` at runtime. */
141
+ maxValueChanged() {
142
+ this.#repaint.schedule();
143
+ }
144
+ /** Repaints when application code (or a Turbo morph) changes `valueText` at runtime. */
145
+ valueTextValueChanged() {
146
+ this.#repaint.schedule();
47
147
  }
48
148
  /** Clamps `raw` into the configured `[min, max]` range. */
49
149
  #clamp(raw) {
@@ -51,9 +151,7 @@ var ProgressController = class extends Controller {
51
151
  }
52
152
  /** Current fraction of the range in `[0, 1]`; `0` when the range is empty. */
53
153
  get #ratio() {
54
- const span = this.maxValue - this.minValue;
55
- if (span <= 0) return 0;
56
- return (this.#clamp(this.valueValue) - this.minValue) / span;
154
+ return rangeFraction(this.valueValue, this.minValue, this.maxValue);
57
155
  }
58
156
  /** Reflects value/range/indeterminate onto ARIA, `data-state`, and the ratio. */
59
157
  #render() {
@@ -61,7 +159,7 @@ var ProgressController = class extends Controller {
61
159
  this.element.setAttribute("aria-valuemax", String(this.maxValue));
62
160
  if (this.indeterminateValue) {
63
161
  this.element.removeAttribute("aria-valuenow");
64
- this.element.removeAttribute("aria-valuetext");
162
+ this.#clearOwnValueText();
65
163
  this.element.style.removeProperty("--stimeo-progress-ratio");
66
164
  this.element.setAttribute("data-state", "indeterminate");
67
165
  return;
@@ -75,16 +173,25 @@ var ProgressController = class extends Controller {
75
173
  /**
76
174
  * Sets `aria-valuetext` from the consumer-provided template, substituting
77
175
  * `{value}` and `{percent}`. Left to the consumer so the human-readable text
78
- * stays i18n-neutral in the library; cleared when no template is given.
176
+ * stays i18n-neutral in the library. With no template the attribute belongs to
177
+ * the consumer, so only a text this controller wrote is taken back
178
+ * ({@link OWNED_VALUE_TEXT}).
79
179
  */
80
180
  #applyValueText(value) {
81
181
  if (this.valueTextValue.length === 0) {
82
- this.element.removeAttribute("aria-valuetext");
182
+ this.#clearOwnValueText();
83
183
  return;
84
184
  }
85
185
  const percent = Math.round(this.#ratio * 100);
86
186
  const text = this.valueTextValue.replaceAll("{value}", String(value)).replaceAll("{percent}", String(percent));
87
187
  this.element.setAttribute("aria-valuetext", text);
188
+ this.element.setAttribute(OWNED_VALUE_TEXT, "");
189
+ }
190
+ /** Removes `aria-valuetext` only when this controller is the one that wrote it. */
191
+ #clearOwnValueText() {
192
+ if (!this.element.hasAttribute(OWNED_VALUE_TEXT)) return;
193
+ this.element.removeAttribute("aria-valuetext");
194
+ this.element.removeAttribute(OWNED_VALUE_TEXT);
88
195
  }
89
196
  };
90
197