@vectoriox/iox-ui 5.37.0 → 5.39.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 (45) hide show
  1. package/actions-core/index.d.ts +6 -1
  2. package/composite-core/index.d.ts +684 -28
  3. package/design-core/index.d.ts +452 -6
  4. package/fesm2022/vectoriox-iox-ui-actions-core.mjs +12 -4
  5. package/fesm2022/vectoriox-iox-ui-actions-core.mjs.map +1 -1
  6. package/fesm2022/vectoriox-iox-ui-composite-core.mjs +1761 -143
  7. package/fesm2022/vectoriox-iox-ui-composite-core.mjs.map +1 -1
  8. package/fesm2022/vectoriox-iox-ui-design-core.mjs +555 -6
  9. package/fesm2022/vectoriox-iox-ui-design-core.mjs.map +1 -1
  10. package/fesm2022/vectoriox-iox-ui-generation-core.mjs +534 -12
  11. package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
  12. package/fesm2022/vectoriox-iox-ui-media-core.mjs +571 -0
  13. package/fesm2022/vectoriox-iox-ui-media-core.mjs.map +1 -0
  14. package/fesm2022/vectoriox-iox-ui.mjs +494 -127
  15. package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
  16. package/generation-core/index.d.ts +210 -4
  17. package/index.d.ts +217 -30
  18. package/media-core/index.d.ts +277 -0
  19. package/media-core/package.json +3 -0
  20. package/package.json +5 -1
  21. package/src/actions-core/element-actions.ts +12 -3
  22. package/src/composite-core/accordion-runtime.ts +3 -15
  23. package/src/composite-core/accordion.ts +4 -2
  24. package/src/composite-core/composite-kinds.ts +121 -7
  25. package/src/composite-core/composite-node.ts +4 -0
  26. package/src/composite-core/composite-runtime.ts +68 -0
  27. package/src/composite-core/exclusive-runtime.ts +358 -0
  28. package/src/composite-core/lightbox.ts +192 -0
  29. package/src/composite-core/public-api.ts +8 -2
  30. package/src/composite-core/slider-runtime.ts +180 -0
  31. package/src/composite-core/slider.ts +378 -0
  32. package/src/composite-core/structure.ts +38 -5
  33. package/src/composite-core/tabs.ts +628 -0
  34. package/src/design-core/contrast-audit.ts +5 -0
  35. package/src/design-core/element-styles.ts +34 -3
  36. package/src/design-core/flavor-spec.generated.ts +517 -2
  37. package/src/generation-core/baseline-roles.ts +2 -0
  38. package/src/generation-core/compose-site.ts +147 -4
  39. package/src/generation-core/node-baselines.generated.ts +156 -6
  40. package/src/generation-core/patterns.ts +20 -0
  41. package/src/generation-core/site-spec.generated.ts +210 -0
  42. package/src/media-core/public-api.ts +9 -0
  43. package/src/media-core/video-runtime.ts +239 -0
  44. package/src/media-core/video.ts +443 -0
  45. package/styles/iox-design.css +112 -0
@@ -34,6 +34,9 @@ interface CompositeNode extends ElementStyleTarget {
34
34
  * (the builder's `createConfig`, generation-core's `createSerializedNode`), with these props and this
35
35
  * element style. `key` is stable per recipe node — a consumer that needs deterministic ids builds them
36
36
  * from it (generation-core: `<root id>-<key>`). */
37
+ /** `elementStyle: NO_ELEMENT_STYLE` asks for a node that wears NO element style (undefined / null = the type's default,
38
+ * as both node factories have always read it): a migrated slider's bare chevrons, a lightbox's slide (CC3). */
39
+ declare const NO_ELEMENT_STYLE = "";
37
40
  interface CompositeNodeSpec {
38
41
  key: string;
39
42
  type: string;
@@ -72,15 +75,22 @@ declare function parentInComposite(root: CompositeNode, node: CompositeNode): Co
72
75
  declare function removeFromComposite(root: CompositeNode, node: CompositeNode): boolean;
73
76
 
74
77
  /**
75
- * The open/close composites' kinds and roles (CC2 Accordion, CC2.1 Disclosure — composite plan T9 / T21). ONE
76
- * family: a Disclosure is a one-item accordion whose ROOT is its item, so both run the same state machine, the
77
- * same attribute planners and the same runtime (`accordion-runtime.ts`). Every consumer that treats "an item",
78
- * "a header" or "a panel" alike asks these predicates, never a role literal.
78
+ * The composites' kinds and roles. Two families:
79
+ * - OPEN/CLOSE (CC2 Accordion, CC2.1 Disclosure — composite plan T9 / T21): a Disclosure is a one-item accordion whose
80
+ * ROOT is its item, so both run the same state machine, attribute planners and runtime (`accordion-runtime.ts`);
81
+ * - EXCLUSIVE (CC4 Tabs — composite T17; the Segmented control joins in CC4b): exactly one item is on, a trigger and
82
+ * its panel paired by `itemKey` (`tabs.ts`, `exclusive-runtime.ts`).
83
+ * Every consumer that treats "an item", "a trigger" or "a panel" alike asks these predicates, never a role literal.
79
84
  */
80
85
  declare enum CompositeKind {
81
86
  Accordion = "accordion",
82
- Disclosure = "disclosure"
87
+ Disclosure = "disclosure",
88
+ Tabs = "tabs"
83
89
  }
90
+ /** The kinds the open/close runtime runs (`AccordionRuntime`). */
91
+ type ToggleCompositeKind = CompositeKind.Accordion | CompositeKind.Disclosure;
92
+ /** The kinds the exclusive runtime runs (`ExclusiveRuntime`): one item on at a time, always one. */
93
+ type ExclusiveCompositeKind = CompositeKind.Tabs;
84
94
  declare enum AccordionRole {
85
95
  Accordion = "accordion",
86
96
  Item = "accordion.item",
@@ -101,10 +111,22 @@ declare enum DisclosureRole {
101
111
  Icon = "disclosure.icon",
102
112
  Panel = "disclosure.panel"
103
113
  }
104
- interface RoleLike$1 {
114
+ /**
115
+ * TABS (CC4a — composite T17). The tab LIST holds the triggers, the PANELS holder holds the panels; a tab and its panel
116
+ * share an `itemKey` (never their index — moving a tab keeps its own panel). From content (R3) the list and the panels
117
+ * holder are both Repeaters over the SAME source, one row giving its tab AND its panel (paired by the row's id).
118
+ */
119
+ declare enum TabsRole {
120
+ Tabs = "tabs",
121
+ List = "tabs.list",
122
+ Trigger = "tabs.trigger",
123
+ Panels = "tabs.panels",
124
+ Panel = "tabs.panel"
125
+ }
126
+ interface RoleLike$2 {
105
127
  role?: string | null;
106
128
  }
107
- /** The roles each kind plays in the shared runtime. */
129
+ /** The roles each open/close kind plays in the shared runtime. */
108
130
  interface CompositeKindRoles {
109
131
  root: string;
110
132
  item: string;
@@ -112,26 +134,61 @@ interface CompositeKindRoles {
112
134
  panel: string;
113
135
  icon: string;
114
136
  }
115
- declare const COMPOSITE_KIND_ROLES: Readonly<Record<CompositeKind, CompositeKindRoles>>;
137
+ declare const COMPOSITE_KIND_ROLES: Readonly<Record<ToggleCompositeKind, CompositeKindRoles>>;
138
+ /** The roles each EXCLUSIVE kind plays: its root, the holder of its triggers, its triggers, and — when its items show
139
+ * a panel (Tabs; a Segmented control has none) — the holder of its panels and the panels. */
140
+ interface ExclusiveKindRoles {
141
+ root: string;
142
+ list: string;
143
+ trigger: string;
144
+ panels: string | null;
145
+ panel: string | null;
146
+ }
147
+ declare const EXCLUSIVE_KIND_ROLES: Readonly<Record<ExclusiveCompositeKind, ExclusiveKindRoles>>;
116
148
  /** The kind a role belongs to (`disclosure.panel` → Disclosure), or null for any other role. */
117
149
  declare function compositeKindOfRole(role: string | null | undefined): CompositeKind | null;
150
+ /** True for a kind the open/close runtime runs. */
151
+ declare function isToggleKind(kind: CompositeKind | null | undefined): kind is ToggleCompositeKind;
152
+ /** True for a kind the exclusive runtime runs. */
153
+ declare function isExclusiveKind(kind: CompositeKind | null | undefined): kind is ExclusiveCompositeKind;
118
154
  /** A root that runs the open/close runtime (an Accordion or a Disclosure). */
119
- declare function isCompositeRoot(node: RoleLike$1 | null | undefined): boolean;
155
+ declare function isCompositeRoot(node: RoleLike$2 | null | undefined): boolean;
120
156
  /** An ITEM — an accordion's item, or a disclosure (its own item). */
121
- declare function isCompositeItem(node: RoleLike$1 | null | undefined): boolean;
157
+ declare function isCompositeItem(node: RoleLike$2 | null | undefined): boolean;
122
158
  /** A trigger — rendered as a `<button>` that opens its item, never a link. */
123
- declare function isCompositeTrigger(node: RoleLike$1 | null | undefined): boolean;
159
+ declare function isCompositeTrigger(node: RoleLike$2 | null | undefined): boolean;
124
160
  /** A panel — rendered inside the track + region the one hiding rule collapses. */
125
- declare function isCompositePanel(node: RoleLike$1 | null | undefined): boolean;
126
- declare function isDisclosureRoot(node: RoleLike$1 | null | undefined): boolean;
161
+ declare function isCompositePanel(node: RoleLike$2 | null | undefined): boolean;
162
+ declare function isDisclosureRoot(node: RoleLike$2 | null | undefined): boolean;
127
163
  /** True for any part of a disclosure (its root included). */
128
- declare function isDisclosurePart(node: RoleLike$1 | null | undefined): boolean;
164
+ declare function isDisclosurePart(node: RoleLike$2 | null | undefined): boolean;
129
165
  /** The composite root a node belongs to: the nearest ancestor (or the node itself) that is one. `path` = the
130
166
  * node's ancestors, root first. */
131
- declare function compositeRootOf<T extends RoleLike$1>(node: T, path: ReadonlyArray<T>): T | null;
167
+ declare function compositeRootOf<T extends RoleLike$2>(node: T, path: ReadonlyArray<T>): T | null;
132
168
  /** The item a node sits in — the nearest item of either kind (itself when it is one) — or null. An accordion
133
169
  * root ends the walk (its items are below it). */
134
- declare function compositeItemOf<T extends RoleLike$1>(node: T, path: ReadonlyArray<T>): T | null;
170
+ declare function compositeItemOf<T extends RoleLike$2>(node: T, path: ReadonlyArray<T>): T | null;
171
+ /** A root that runs the exclusive runtime (Tabs). */
172
+ declare function isExclusiveRoot(node: RoleLike$2 | null | undefined): boolean;
173
+ /** The holder of an exclusive composite's triggers (a tab list): it takes only triggers. */
174
+ declare function isExclusiveList(node: RoleLike$2 | null | undefined): boolean;
175
+ /** One of an exclusive composite's triggers (a tab): pressing it turns its item on. */
176
+ declare function isExclusiveTrigger(node: RoleLike$2 | null | undefined): boolean;
177
+ /** The holder of an exclusive composite's panels: it takes only panels. */
178
+ declare function isExclusivePanels(node: RoleLike$2 | null | undefined): boolean;
179
+ /** One of an exclusive composite's panels (a tab panel): shown only while its item is on. */
180
+ declare function isExclusivePanel(node: RoleLike$2 | null | undefined): boolean;
181
+ /** True for a trigger or a panel — a part that IS one item of an exclusive composite (it carries the `itemKey`). */
182
+ declare function isExclusiveItemPart(node: RoleLike$2 | null | undefined): boolean;
183
+ /** True for any part of a Tabs (its root included). */
184
+ declare function isTabsPart(node: RoleLike$2 | null | undefined): boolean;
185
+ /** A root of either family — anything that runs a composite runtime. */
186
+ declare function isAnyCompositeRoot(node: RoleLike$2 | null | undefined): boolean;
187
+ /** The exclusive root a node belongs to (the node itself when it is one), or null. `path` = its ancestors, root first. */
188
+ declare function exclusiveRootOf<T extends RoleLike$2>(node: T, path: ReadonlyArray<T>): T | null;
189
+ /** The trigger or panel a node sits in (itself when it is one) inside an exclusive composite, or null. A nested
190
+ * exclusive root ends the walk. */
191
+ declare function exclusiveItemPartOf<T extends RoleLike$2>(node: T, path: ReadonlyArray<T>): T | null;
135
192
 
136
193
  /**
137
194
  * ACCORDION (CC2 — composite K1; complex-components boards 3, 4 and 9, APPROVED 2026-10-20). Not a
@@ -442,6 +499,8 @@ interface AccordionRuntimeOptions {
442
499
  declare function closestAccordion(el: Element | null | undefined): HTMLElement | null;
443
500
  /** The item an element sits in (itself when it is one) — an accordion item, or a disclosure. */
444
501
  declare function closestAccordionItem(el: Element | null | undefined): HTMLElement | null;
502
+ /** The composite root whose items an item belongs to: a disclosure is its own root. */
503
+ declare function accordionRootOfItem(item: HTMLElement): HTMLElement | null;
445
504
  /** Subscribe to an item turning on / off — what the `itemOn` / `itemOff` interaction triggers listen to. The
446
505
  * item is the element's own item (the element itself when it is one). Returns the unsubscribe. */
447
506
  declare function onAccordionItemState(el: Element, on: boolean, handler: () => void): () => void;
@@ -512,12 +571,6 @@ declare enum CompositeItemAction {
512
571
  Close = "close",
513
572
  Toggle = "toggle"
514
573
  }
515
- /**
516
- * Run an item action on the element of an ITEM (an accordion item, or a disclosure) — the `openItem` /
517
- * `closeItem` / `toggleItem` interaction actions, on the canvas and on the live site through this one function.
518
- * Returns whether the item shows open afterwards, or null when `el` is in no running composite.
519
- */
520
- declare function runCompositeItemAction(el: Element | null | undefined, action: CompositeItemAction): boolean | null;
521
574
  /** True when an item an action just opened is out of view and the page should scroll to it (T14: "opens that item
522
575
  * and scrolls to it") — never when its head is already on screen, so a button beside it does not jolt the page. */
523
576
  declare function shouldScrollToItem(top: number, viewportHeight: number): boolean;
@@ -740,8 +793,14 @@ declare function setCardLinked(card: CompositeNode, on: boolean): boolean;
740
793
  interface CompositeRoleSpec {
741
794
  /** The role of the part's parent; null for a composite root. */
742
795
  readonly parent: string | null;
796
+ /** The TYPE of the part's parent, for a part whose parent carries no role (a Slider's controls). */
797
+ readonly parentType?: string;
743
798
  readonly locked?: boolean;
799
+ /** May be deleted, but never moved out of its parent (a Slider's controls work only as its direct children). */
800
+ readonly pinned?: boolean;
744
801
  readonly part?: CardPart;
802
+ /** The only roles that may be dropped INTO this part (a tab list takes tabs, a panels holder takes panels). */
803
+ readonly accepts?: ReadonlyArray<string>;
745
804
  }
746
805
  declare const COMPOSITE_ROLE_SPECS: Readonly<Record<string, CompositeRoleSpec>>;
747
806
  declare enum StructureEdit {
@@ -753,19 +812,616 @@ declare enum StructureRefusal {
753
812
  /** A locked part cannot be deleted (the card's Content and Title). */
754
813
  LockedPart = "locked-part",
755
814
  /** A locked part can only live directly inside its own parent role. */
756
- LockedPlacement = "locked-placement"
815
+ LockedPlacement = "locked-placement",
816
+ /** The new parent takes only certain roles (a tab list takes only tabs, CC4a). */
817
+ NotAccepted = "not-accepted"
757
818
  }
758
- interface RoleLike {
819
+ interface RoleLike$1 {
759
820
  role?: string | null;
821
+ type?: string;
760
822
  }
761
823
  /**
762
824
  * Why the structure guard refuses `edit` on `node`, or null when it is allowed. `ancestors` (Move only) =
763
825
  * the new parent chain, root first, the direct parent last.
764
826
  */
765
- declare function structureRefusal(node: RoleLike | null | undefined, edit: StructureEdit, ancestors?: ReadonlyArray<RoleLike>): StructureRefusal | null;
827
+ declare function structureRefusal(node: RoleLike$1 | null | undefined, edit: StructureEdit, ancestors?: ReadonlyArray<RoleLike$1>): StructureRefusal | null;
766
828
  /** True when `node` is a locked part (shown with a lock and no delete in the layer tree). Deleting a whole
767
829
  * composite is always allowed — only its locked parts are refused. */
768
- declare function isLockedPart(node: RoleLike | null | undefined): boolean;
830
+ declare function isLockedPart(node: RoleLike$1 | null | undefined): boolean;
831
+ /** Why `parent` refuses `node` as a child (it takes only certain roles), or null. */
832
+ declare function acceptsRefusal(node: RoleLike$1 | null | undefined, parent: RoleLike$1 | null | undefined): StructureRefusal | null;
833
+
834
+ /**
835
+ * THE ACCESSIBLE CAROUSEL (CC3 — complex-components plan §7c, board 6; board 9 Q13). The Slider's controls are no
836
+ * longer drawn by Swiper: Previous, Next, Pause and Pagination are REAL nodes with roles — selectable on the canvas,
837
+ * in the layer tree and the breadcrumb, and styled on their own (R2) — handed to Swiper as its navigation and
838
+ * pagination elements.
839
+ *
840
+ * SliderContainer (.swiper)
841
+ * ├─ ButtonBlock `button-secondary` role slider.pause FIRST focus stop; present while Autoplay is on, locked
842
+ * ├─ ButtonBlock `button-secondary` role slider.prev › Icon caret (points the reading way in RTL)
843
+ * ├─ ButtonBlock `button-secondary` role slider.next › Icon caret
844
+ * ├─ (the slides — `.swiper-wrapper` › SliderSlide …)
845
+ * └─ Container role slider.pagination Swiper draws the dots (or "3 / 6") inside it
846
+ *
847
+ * The parts render INSIDE the `.swiper` element, never inside `.swiper-wrapper` (slider.md: a `.swiper-slide` must be
848
+ * the wrapper's direct child): the parts that come before the first slide in the tree render before the wrapper, the
849
+ * rest after it. By default they sit over the slides like Swiper's own controls (the shared CSS, iox-design.css, at
850
+ * zero specificity — a part's own styles win), so a saved slider migrated from Swiper-drawn controls keeps its look.
851
+ *
852
+ * The Bindings switches stay the source of truth: Navigation arrows ⇔ Previous + Next, Pagination ⇔ Pagination,
853
+ * Autoplay ⇔ Pause (WCAG 2.2.2 — "added while Autoplay is on, cannot be removed"). `syncSliderParts` is the one edit.
854
+ */
855
+ declare enum SliderRole {
856
+ Pause = "slider.pause",
857
+ Prev = "slider.prev",
858
+ Next = "slider.next",
859
+ Pagination = "slider.pagination"
860
+ }
861
+ /** Parts in the order they are stamped: the pause control first (APG: the first focus stop), the dots last. */
862
+ declare const SLIDER_PART_ROLES: ReadonlyArray<SliderRole>;
863
+ declare const SLIDER_TYPE = "SliderContainer";
864
+ declare const SLIDE_TYPE = "SliderSlide";
865
+ /** The Bindings switches that own the parts. */
866
+ declare enum SliderFlag {
867
+ Navigation = "enableNavigation",
868
+ Pagination = "enablePagination",
869
+ Autoplay = "enableAutoplay"
870
+ }
871
+ /** The trait that names the carousel (Slider ▸ Accessibility ▸ Carousel name) — the A11y trait every named part uses. */
872
+ declare const SLIDER_NAME_TRAIT = "ariaLabel";
873
+ interface RoleLike {
874
+ role?: string | null;
875
+ type?: string;
876
+ }
877
+ declare function isSliderPart(node: RoleLike | null | undefined): boolean;
878
+ declare function isSlider(node: RoleLike | null | undefined): boolean;
879
+ /** The slider's own part playing `role` (a direct child), or undefined. */
880
+ declare function sliderPart<T extends RoleLike>(slider: {
881
+ children?: T[] | null;
882
+ }, role: SliderRole): T | undefined;
883
+ /** True when the slider's controls are parts (it was created or migrated in CC3) — Swiper then draws none of its own. */
884
+ declare function hasSliderParts(slider: {
885
+ children?: ReadonlyArray<RoleLike> | null;
886
+ }): boolean;
887
+ /** A slider's children split as they render: parts before the first slide, the slides (into `.swiper-wrapper`), and
888
+ * the parts after it. */
889
+ declare function splitSliderChildren<T extends RoleLike>(children: ReadonlyArray<T> | null | undefined): {
890
+ lead: T[];
891
+ slides: T[];
892
+ trail: T[];
893
+ };
894
+ /** The slides only (the template slide of a bound slider is `sliderSlides(children)[0]`). */
895
+ declare function sliderSlides<T extends RoleLike>(children: ReadonlyArray<T> | null | undefined): T[];
896
+ /** Each part's glyph (Phosphor) and its default accessible name. */
897
+ declare const SLIDER_PART_GLYPH: Readonly<Record<Exclude<SliderRole, SliderRole.Pagination>, string>>;
898
+ declare const SLIDER_PLAY_GLYPH = "ph-fill ph-play";
899
+ /**
900
+ * What a saved slider drew through Swiper before CC3, carried into its parts by the migration so it looks the same:
901
+ * bare chevrons in the author's arrow colour and size, the dots in the author's colour. Swiper's own default colour
902
+ * is its theme blue — what the live site drew, because the engine never applied the colour traits.
903
+ */
904
+ interface LegacySliderLook {
905
+ navigationColor?: string;
906
+ navigationSize?: number;
907
+ paginationColor?: string;
908
+ }
909
+ declare const SWIPER_THEME_COLOR = "#007aff";
910
+ /** One part, from the recipe (board 6: `button-secondary` controls, token dots) or in a migrated slider's legacy look. */
911
+ declare function buildSliderPart(create: CompositeNodeFactory, role: SliderRole, legacy?: LegacySliderLook): CompositeNode;
912
+ /** The parts the slider's switches call for, in stamping order. */
913
+ declare function wantedSliderParts(slider: CompositeNode): SliderRole[];
914
+ interface SliderPartsChange {
915
+ added: CompositeNode[];
916
+ removed: CompositeNode[];
917
+ }
918
+ /**
919
+ * Make the slider's parts match its switches — ONE edit (a palette switch, the migration, the composer). Missing
920
+ * parts are stamped from the recipe (or, `legacy`, in the migrated look) at their place: the pause control, Previous
921
+ * and Next before the first slide, the pagination after the last; parts whose switch is off are removed. Everything
922
+ * else (the slides, the author's edits to an existing part) is kept.
923
+ */
924
+ declare function syncSliderParts(slider: CompositeNode, create: CompositeNodeFactory, legacy?: LegacySliderLook): SliderPartsChange;
925
+ /** True when a saved slider still relies on Swiper-drawn controls: a switch is on and no part exists yet. */
926
+ declare function needsSliderMigration(slider: CompositeNode | null | undefined): boolean;
927
+ /**
928
+ * The migration of a saved slider (board 9 Q13): its Swiper-drawn arrows, dots — and, when Autoplay is on, the pause
929
+ * control WCAG 2.2.2 requires — become parts, in the place and the colours Swiper drew them. Idempotent: a slider
930
+ * that already has parts is left alone. True when it changed.
931
+ */
932
+ declare function migrateSliderControls(slider: CompositeNode, create: CompositeNodeFactory): boolean;
933
+ /**
934
+ * A switch flipped in the panel: on a slider still on Swiper-drawn controls, migrate it first (so its other controls
935
+ * keep their look), then stamp / remove the parts the new switch calls for. ONE edit.
936
+ */
937
+ declare function setSliderFlag(slider: CompositeNode, flag: SliderFlag, on: boolean, create: CompositeNodeFactory): SliderPartsChange;
938
+ interface SliderWords {
939
+ stop: string;
940
+ start: string;
941
+ prev: string;
942
+ next: string;
943
+ carousel: string;
944
+ slide: string;
945
+ /** `{{index}}` and `{{slidesLength}}`, Swiper's placeholders. */
946
+ slideLabel: string;
947
+ goTo: string;
948
+ }
949
+ declare const SLIDER_WORDS: Readonly<Record<'en' | 'he', SliderWords>>;
950
+ declare function sliderWords(lang?: string | null): SliderWords;
951
+ /** The wrapper's live region (APG): silent while the slides move on their own, polite otherwise. */
952
+ declare function sliderLiveRegion(rotating: boolean): 'off' | 'polite';
953
+ /**
954
+ * The pause control's state (APG carousel): its NAME says what it will do ("Stop automatic slide show" while it
955
+ * rotates, "Start automatic slide show" when stopped). An author who named the control keeps the name, and the
956
+ * state is `aria-pressed` instead (pressed = stopped).
957
+ */
958
+ declare function sliderPauseAttributes(rotating: boolean, words?: SliderWords, authorName?: string | null): Record<string, string>;
959
+ /** The pause control's glyph: pause while it rotates, play when stopped. */
960
+ declare function sliderPauseGlyph(rotating: boolean): string;
961
+ interface CarouselQuote {
962
+ quote: string;
963
+ who: string;
964
+ }
965
+ /** Board 6's sample quotes — PLACEHOLDERS: testimonials are facts the studio gives, never invented. */
966
+ declare const CAROUSEL_QUOTES: ReadonlyArray<CarouselQuote>;
967
+ interface CarouselOptions {
968
+ /** The carousel's accessible name (a `region` landmark). */
969
+ name?: string;
970
+ quotes?: ReadonlyArray<CarouselQuote>;
971
+ }
972
+ /**
973
+ * The testimonial carousel (board 6): a named Slider, one quote per slide (each a `card`), rotating every 5s with its
974
+ * control parts — the pause control first, Previous · Next, the dots. ONE recipe for the composer and the builder.
975
+ */
976
+ declare function buildCarouselRecipe(create: CompositeNodeFactory, options?: CarouselOptions): CompositeNode;
977
+ /** The slide a lightbox opens at for the clicked row (clamped to the slides there are). */
978
+ declare function slideIndexForRow(rowIndex: number, slideCount: number): number;
979
+
980
+ /**
981
+ * The accessible carousel's RUNTIME (CC3, board 6; closes vectoriox/iox-ui#13) — DOM only, over a running Swiper,
982
+ * ONE copy for the engine (both paths) and the admin's Preview. Swiper's A11y module gives the container
983
+ * `aria-roledescription="carousel"`, every slide `role=group` + "slide" + "n of m"; this adds what the APG
984
+ * carousel needs on top:
985
+ * - the PAUSE control (role `slider.pause`, rendered first): it stops rotation for good and starts it again; its
986
+ * name says what it will do, its glyph swaps;
987
+ * - rotation PAUSES while focus is anywhere inside (hover is Swiper's `pauseOnMouseEnter`) and resumes when it
988
+ * leaves — unless the visitor pressed pause;
989
+ * - the wrapper's live region is `off` while the slides move on their own and `polite` otherwise;
990
+ * - slides that are not in view are `inert` (and hidden from assistive technology), so Tab never lands in one.
991
+ * The builder's EDIT canvas never attaches it (no autoplay there, and a slide must stay clickable).
992
+ */
993
+ /** The parts of the Swiper instance this runtime reads — a real Swiper, or a stub in a spec. */
994
+ interface CarouselSwiper {
995
+ el: HTMLElement;
996
+ wrapperEl: HTMLElement;
997
+ slides: HTMLElement[];
998
+ activeIndex: number;
999
+ destroyed?: boolean;
1000
+ params?: {
1001
+ slidesPerView?: number | 'auto';
1002
+ autoplay?: {
1003
+ pauseOnMouseEnter?: boolean;
1004
+ } | boolean;
1005
+ };
1006
+ autoplay?: {
1007
+ running: boolean;
1008
+ paused?: boolean;
1009
+ start(): void;
1010
+ stop(): void;
1011
+ pause(): void;
1012
+ resume(): void;
1013
+ };
1014
+ on(event: string, handler: (...args: unknown[]) => void): void;
1015
+ off(event: string, handler: (...args: unknown[]) => void): void;
1016
+ }
1017
+ interface CarouselA11yOptions {
1018
+ words?: SliderWords;
1019
+ }
1020
+ /** The part of `role` that belongs to THIS slider (never one of a slider nested in a slide). */
1021
+ declare function sliderPartElement(sliderEl: Element, role: SliderRole): HTMLElement | null;
1022
+ declare class CarouselA11y {
1023
+ private readonly swiper;
1024
+ /** The visitor pressed pause: rotation stays stopped until they press it again. */
1025
+ private stoppedByVisitor;
1026
+ private focusInside;
1027
+ /** The pointer is over the carousel and Swiper holds rotation for it (`pauseOnMouseEnter`). */
1028
+ private hovering;
1029
+ private readonly cleanups;
1030
+ private readonly words;
1031
+ private readonly pause;
1032
+ private readonly authorName;
1033
+ constructor(swiper: CarouselSwiper, options?: CarouselA11yOptions);
1034
+ /** True while the slides move on their own: autoplay runs and nothing holds it — not focus inside, not the
1035
+ * pointer over it. (Swiper's own `paused` also flips during every transition, so it is not read here.) */
1036
+ get rotating(): boolean;
1037
+ private get hoverPauses();
1038
+ /** The pause control: stop rotation for good, or start it again. */
1039
+ togglePause(): void;
1040
+ destroy(): void;
1041
+ private listen;
1042
+ private onFocusIn;
1043
+ private onFocusOut;
1044
+ /** Re-state the carousel: the live region, the pause control, the slides out of view. */
1045
+ sync(): void;
1046
+ private syncHiddenSlides;
1047
+ }
1048
+ /** The carousel runtime attached to a slider element, if any. */
1049
+ declare function carouselOf(el: Element | null | undefined): CarouselA11y | null;
1050
+ /** Attach once per Swiper (a re-init gets a fresh runtime). */
1051
+ declare function attachCarouselA11y(swiper: CarouselSwiper, options?: CarouselA11yOptions): CarouselA11y;
1052
+
1053
+ /**
1054
+ * THE LIGHTBOX (CC3 — complex-components plan §7d, board 6). Not a component: a Dialog holding a Slider bound to the
1055
+ * SAME source as the grid of thumbnails. The one new thing is `openDialog`'s "Open at the clicked item"
1056
+ * (`slideTo: 'row'`): a thumbnail in a repeater row opens the lightbox at ITS slide.
1057
+ *
1058
+ * Dialog `dialog` · centre · full viewport · Inverse scheme "Lightbox" (a free-standing Dialog: board A4)
1059
+ * ├─ ButtonBlock `button-ghost` "Close" › Icon × click → closeDialog
1060
+ * └─ SliderContainer one slide in view · keyboard · the source's rows
1061
+ * ├─ Previous · Next (slider.prev / slider.next, button-secondary) hidden on a phone (swipe)
1062
+ * ├─ SliderSlide › Image `media` (contain, keeps its alt) + Text `small` caption
1063
+ * └─ Pagination (slider.pagination) — the counter "3 / 6"
1064
+ *
1065
+ * Keyboard ← → are the Slider's Keyboard module; Esc and the focus trap are the `<dialog>`'s; focus returns to the
1066
+ * thumbnail that opened it (the dialog opener's own rule).
1067
+ */
1068
+ declare const SLIDE_TO_ROW = "row";
1069
+ /** The attribute a renderer writes on every repeated row (the context-state provenance, both engine paths, the canvas). */
1070
+ declare const ROW_INDEX_ATTRIBUTE = "data-iox-row-idx";
1071
+ declare const LIGHTBOX_LABEL = "Lightbox";
1072
+ interface LightboxOptions {
1073
+ /** The list the slides come from (the grid's own source). Empty = three manual slides. */
1074
+ source?: string;
1075
+ sourcePath?: string;
1076
+ /** The row field each slide's image and caption read (`item` = the row itself, a bare URL). */
1077
+ imageField?: string;
1078
+ captionField?: string;
1079
+ /** The image's alt binding; '' = decorative (a bare URL row has no words of its own). */
1080
+ altField?: string;
1081
+ }
1082
+ /** On a phone the arrows give way to a swipe (board 6, "the arrows hide on touch-only widths"). */
1083
+ declare const LIGHTBOX_ARROWS_HIDE_AT = "mobile";
1084
+ /** A fresh lightbox: the Dialog, its Close part and the Slider (bound to `source`, or three manual slides). */
1085
+ declare function buildLightboxRecipe(create: CompositeNodeFactory, options?: LightboxOptions): CompositeNode;
1086
+ interface RepeatSource {
1087
+ source: string;
1088
+ path: string;
1089
+ }
1090
+ /** What a Repeater (its `source` binding) or a bound Slider (its `source` / `sourcePath` traits) repeats over. */
1091
+ declare function repeatSourceOf(node: CompositeNode | null | undefined): RepeatSource | null;
1092
+ declare function sameRepeatSource(a: RepeatSource | null, b: RepeatSource | null): boolean;
1093
+ /** The Slider a lightbox Dialog holds (the first one, depth first), or null. */
1094
+ declare function lightboxSliderOf(dialog: CompositeNode | null | undefined): CompositeNode | null;
1095
+ /** The repeated rows the element is in: the nearest Repeater or bound Slider among its ancestors (`path` = root → the
1096
+ * element, inclusive). */
1097
+ declare function rowSourceOf(path: ReadonlyArray<CompositeNode>): RepeatSource | null;
1098
+ /**
1099
+ * Interactions ▸ openDialog ▸ "Open at the clicked item" is offered only when it can work (board 9): the clicked
1100
+ * element sits in a repeater row AND the target Dialog holds a Slider bound to the same source.
1101
+ */
1102
+ declare function canOpenAtClickedItem(ownerPath: ReadonlyArray<CompositeNode>, dialog: CompositeNode | null | undefined): boolean;
1103
+ /** The repeated row an element sits in (its row index), 0 when it is in none (the canvas' template row). */
1104
+ declare function rowIndexOf(el: Element | null | undefined): number;
1105
+
1106
+ /**
1107
+ * TABS (CC4a — composite K2 T17–T20; complex-components boards 3 and 9, APPROVED 2026-10-20). Not a component: a
1108
+ * recipe of ordinary nodes, each part carrying a role, so every tab and every panel is selectable on the canvas, in
1109
+ * the layer tree and the breadcrumb, and wears its own element style (R2).
1110
+ *
1111
+ * Container `box` role tabs traits activateOn · orientation · ariaLabel (the list's name)
1112
+ * ├─ Container `tab-list` role tabs.list → role=tablist (locked) — or a Repeater (From content)
1113
+ * │ └─ ButtonBlock `tab` ×3 role tabs.trigger itemKey k1… → <button role=tab> › Text `button-label`
1114
+ * └─ Container `box` role tabs.panels (locked) — or a Repeater (From content)
1115
+ * └─ Container `box` ×3 role tabs.panel the SAME itemKey as its tab → role=tabpanel, hidden while off
1116
+ * ├─ Image `media` 4 / 3
1117
+ * └─ Text `body`
1118
+ *
1119
+ * A tab and its panel are a PAIR by `itemKey` — never by index, so a tab moved to the end still shows its own panel.
1120
+ * The behaviour is BUILT IN (composite plan D1 = B): exactly one item is on (`exclusive`), the APG tabs pattern with
1121
+ * AUTOMATIC activation (arrows move focus and activate, roving tabindex) — one runtime (`exclusive-runtime.ts`) on the
1122
+ * builder canvas and both engine paths, from the attribute planners below.
1123
+ */
1124
+ declare enum TabsBehaviourTrait {
1125
+ /** Which pointer gesture turns a tab on: a click (always) or also a hover. */
1126
+ ActivateOn = "activateOn",
1127
+ /** The tab list across the top, or beside the panels. */
1128
+ Orientation = "orientation",
1129
+ /** The tab list's accessible name (`aria-label` on the role=tablist element) — the root's, edited in Accessibility. */
1130
+ Label = "ariaLabel"
1131
+ }
1132
+ declare enum TabsActivateOn {
1133
+ Click = "click",
1134
+ Hover = "hover"
1135
+ }
1136
+ declare enum TabsOrientation {
1137
+ Horizontal = "horizontal",
1138
+ Vertical = "vertical"
1139
+ }
1140
+ declare const TABS_ACTIVATE_ONS: ReadonlyArray<TabsActivateOn>;
1141
+ declare const TABS_ORIENTATIONS: ReadonlyArray<TabsOrientation>;
1142
+ /** Tabs from content default to six rows: more tabs do not fit a row (board 9 Q13). */
1143
+ declare const TABS_CONTENT_LIMIT = 6;
1144
+ /** The breakpoint whose layer stacks a VERTICAL tabs (the list above the panels) and a panel's picture above its words. */
1145
+ declare const TABS_STACK_BREAKPOINT = "mobile";
1146
+ interface TabWords {
1147
+ label: string;
1148
+ text: string;
1149
+ }
1150
+ /** The words a fresh Tabs starts with — generic, the author's to replace (Card v2.1: never invented facts). */
1151
+ declare const TABS_WORDS: ReadonlyArray<TabWords>;
1152
+ declare const TABS_NEW_TAB_WORDS: Readonly<TabWords>;
1153
+ interface TabsOptions {
1154
+ tabs?: ReadonlyArray<TabWords>;
1155
+ activateOn?: TabsActivateOn;
1156
+ orientation?: TabsOrientation;
1157
+ /** The tab list's accessible name (empty: unnamed — a section heading usually names the section). */
1158
+ label?: string;
1159
+ }
1160
+ interface TabPair {
1161
+ tab: CompositeNode;
1162
+ panel: CompositeNode;
1163
+ }
1164
+ /** One tab and its panel, sharing `itemKey`. */
1165
+ declare function buildTabPair(create: CompositeNodeFactory, words: TabWords, itemKey: string): TabPair;
1166
+ /** A fresh Tabs: three tabs, the first on, activated by a click, the list across the top (board 3). */
1167
+ declare function buildTabsRecipe(create: CompositeNodeFactory, options?: TabsOptions): CompositeNode;
1168
+ declare function isTabsRoot(node: {
1169
+ role?: string | null;
1170
+ } | null | undefined): boolean;
1171
+ /** The tab list (the holder of the triggers). */
1172
+ declare function tabsListOf(root: CompositeNode): CompositeNode | undefined;
1173
+ /** The holder of the panels. */
1174
+ declare function tabsPanelsOf(root: CompositeNode): CompositeNode | undefined;
1175
+ /** The tabs in order — every tab (Manual), or the one template tab (From content). */
1176
+ declare function tabsTriggers(root: CompositeNode): CompositeNode[];
1177
+ /** The panels in their holder's order (their order does not pair them — their key does). */
1178
+ declare function tabsPanels(root: CompositeNode): CompositeNode[];
1179
+ /** True when the Tabs takes its tabs from content (its list is a Repeater, R3). */
1180
+ declare function isTabsFromContent(root: CompositeNode | null | undefined): boolean;
1181
+ /** The panel paired with `tab` (the same key), or undefined. From content the one template panel pairs the template tab. */
1182
+ declare function tabPanelOf(root: CompositeNode, tab: CompositeNode): CompositeNode | undefined;
1183
+ /** The tab paired with `panel` (the same key), or undefined. */
1184
+ declare function tabTriggerOf(root: CompositeNode, panel: CompositeNode): CompositeNode | undefined;
1185
+ /** The other half of a tab ⇄ panel pair, or undefined for any other node. */
1186
+ declare function tabsPartnerOf(root: CompositeNode, node: CompositeNode): CompositeNode | undefined;
1187
+ /** The words a tab shows: its first Text's. */
1188
+ declare function tabLabelNodeOf(tab: CompositeNode): CompositeNode | undefined;
1189
+ /** A tab's name in the Items list, the layer tree and the item-action picker: its words. */
1190
+ declare function tabLabel(tab: CompositeNode): string;
1191
+ /** Items ▸ rename: the tab's words. */
1192
+ declare function renameTab(tab: CompositeNode, words: string): boolean;
1193
+ /** The first Text inside a panel (the words From content binds to). */
1194
+ declare function tabPanelTextOf(panel: CompositeNode): CompositeNode | undefined;
1195
+ /** The first Image inside a panel. */
1196
+ declare function tabPanelImageOf(panel: CompositeNode): CompositeNode | undefined;
1197
+ interface TabsBehaviour {
1198
+ activateOn: TabsActivateOn;
1199
+ orientation: TabsOrientation;
1200
+ }
1201
+ /** The root's behaviour (an unset trait reads its default: a click, the list across the top). */
1202
+ declare function tabsBehaviour(root: CompositeNode | null | undefined): TabsBehaviour;
1203
+ /** The tab list's accessible name (empty when unnamed). */
1204
+ declare function tabsLabel(root: CompositeNode | null | undefined): string;
1205
+ /** Behaviour ▸ Activate on / Orientation (and Accessibility ▸ the list's name). False when the root has no such trait. */
1206
+ declare function setTabsBehaviour(root: CompositeNode, patch: Partial<TabsBehaviour> & {
1207
+ label?: string;
1208
+ }): boolean;
1209
+ /** A key no tab of `root` holds yet (`k4`…). */
1210
+ declare function nextTabKey(root: CompositeNode): string;
1211
+ /** Items ▸ Add tab (and the toolbar's "Add tab"): a fresh tab after `after` (or at the end) AND its panel. */
1212
+ declare function addTabPair(root: CompositeNode, create: CompositeNodeFactory, after?: CompositeNode | null, words?: TabWords): TabPair | null;
1213
+ /** Items ▸ drag to reorder: move a tab — and its panel, so the layer tree reads in the same order — to `toIndex`.
1214
+ * The pairing never depended on the order. False when `tab` is not one of the root's tabs. */
1215
+ declare function moveTabPair(root: CompositeNode, tab: CompositeNode, toIndex: number): boolean;
1216
+ /** Remove a tab and its panel (the pair) — what "Delete tab and its panel" does. True when the tab was removed. */
1217
+ declare function removeTabPair(root: CompositeNode, node: CompositeNode): boolean;
1218
+ declare enum TabsEditRefusal {
1219
+ /** A Tabs keeps at least one tab (composite plan T18). */
1220
+ LastTab = "last-tab"
1221
+ }
1222
+ /** Why removing `node` (a tab or a panel) from `root` is refused, or null. */
1223
+ declare function tabsRemovalRefusal(root: CompositeNode | null | undefined, node: CompositeNode | null | undefined): TabsEditRefusal | null;
1224
+ /** Every "Item open" (`trigger-on`) state inside a tab or a panel points at ITS tab or panel — the part that carries
1225
+ * `data-iox-on` while its item is on. */
1226
+ declare function tabsItemTriggerIds(root: CompositeNode): void;
1227
+ /** The render scope of one Tabs: its scope id, behaviour, every item key in order and the one that is on. */
1228
+ interface TabsScope {
1229
+ rootId: string;
1230
+ behaviour: TabsBehaviour;
1231
+ keys: ReadonlyArray<string>;
1232
+ /** The key on at first paint: the first tab (null when there is none). */
1233
+ active: string | null;
1234
+ label: string;
1235
+ }
1236
+ declare function tabsScope(rootId: string, behaviour: TabsBehaviour, keys: ReadonlyArray<string>, label?: string): TabsScope;
1237
+ /** The item keys a manual Tabs pairs by — its tabs' own keys, in order (a tab with none by its index). */
1238
+ declare function manualTabKeys(root: CompositeNode): string[];
1239
+ interface TabsItemState {
1240
+ key: string;
1241
+ on: boolean;
1242
+ ids: AccordionDomIds;
1243
+ }
1244
+ /** One item's render state: its key, whether it is on, and its ARIA ids (`iox-tab-<scope>-<key>-h` / `-p`). */
1245
+ declare function tabsItemState(scope: TabsScope, key: string): TabsItemState;
1246
+ declare const ACTIVATE_ON_ATTRIBUTE = "data-iox-activate-on";
1247
+ declare const ORIENTATION_ATTRIBUTE = "data-iox-orientation";
1248
+ declare function tabsRootAttributes(behaviour: TabsBehaviour, scopeId?: string): DomAttributes;
1249
+ /** The tab list: `role=tablist`, vertical said aloud, named by the root's label. */
1250
+ declare function tabListAttributes(behaviour: TabsBehaviour, label?: string): DomAttributes;
1251
+ /** A tab: a real button that selects its panel — selected = the one tab in the Tab order (roving tabindex). */
1252
+ declare function tabTriggerAttributes(state: TabsItemState): DomAttributes;
1253
+ /** A panel: `role=tabpanel`, named by its tab, a Tab stop of its own, and `hidden` (display:none) while off. */
1254
+ declare function tabPanelAttributes(state: TabsItemState): DomAttributes;
1255
+ /**
1256
+ * The render scope of one rendered Tabs — ONE decision for both engine paths (and the composer's checks): its scope id
1257
+ * (its node id + the rows around it, vectoriox/iox-ui#20), its behaviour, its list's name and every item key in order —
1258
+ * a manual tab's own `itemKey`, or, From content, each ROW's own id (R3: never its index — a reorder in the CMS keeps
1259
+ * every tab with its own panel). `rows` = the rows the tab list's Repeater resolved (null for a manual Tabs).
1260
+ */
1261
+ declare function tabsScopeFor(root: CompositeNode, rootCssId: string, rows: ReadonlyArray<unknown> | null, rowKeys?: ReadonlyArray<string>): TabsScope;
1262
+ /** The key a manual tab or panel renders with: its own key, else its index among its kind. */
1263
+ declare function tabPartKey(node: CompositeNode, index: number): string;
1264
+ /**
1265
+ * The attributes a part of a Tabs writes on its own element (both engine paths, SSR included): the root's data
1266
+ * attributes (its scope id when it sits in repeated rows), the list's role and name, a tab's and a panel's state by
1267
+ * `key` (its own key, or — From content — its row's). Anything else writes nothing.
1268
+ */
1269
+ declare function tabsPartAttributes(node: {
1270
+ role?: string | null;
1271
+ }, scope: TabsScope, key: string | null, rowScoped?: boolean): DomAttributes;
1272
+ /**
1273
+ * The APG tabs keys on a tab (automatic activation): → / ← move along a horizontal list — mirrored under RTL — and ↓ /
1274
+ * ↑ along a vertical one; Home / End jump. Every move wraps. Enter / Space are the button's own.
1275
+ */
1276
+ declare function tabsKeyAction(key: string, orientation: TabsOrientation, rtl?: boolean): AccordionKeyAction | null;
1277
+ interface TabsAutoBinds {
1278
+ /** The first short-text field: the tab's words. */
1279
+ label: string | null;
1280
+ /** The first long-text field: the panel's words. */
1281
+ text: string | null;
1282
+ /** The first image field: the panel's picture. */
1283
+ image: string | null;
1284
+ }
1285
+ /** R3 (board 3 "Tabs from content"): switching to From content binds the tab's words to the first short-text field,
1286
+ * the panel's words to the first long-text field and its picture to the first image field. ONE rule for the builder's
1287
+ * switch and the composer. */
1288
+ declare function pickTabsAutoBinds(fields: ReadonlyArray<ContentFieldLike>): TabsAutoBinds;
1289
+ /** The bound props of a tab's words, a panel's words and its picture. */
1290
+ declare const TABS_LABEL_BIND_PROP = "content";
1291
+ declare const TABS_TEXT_BIND_PROP = "content";
1292
+ declare const TABS_IMAGE_BIND_PROP = "src";
1293
+ /**
1294
+ * Manual → From content (board 9 "Items: Manual · From content"): the list becomes `listRepeater` and the panels
1295
+ * holder `panelsRepeater` (Repeater nodes the caller created with the same ids, roles, names, element styles and
1296
+ * styles — a type change is the consumer's). The FIRST tab and ITS panel become the templates (their parts, styles
1297
+ * and interactions kept; their keys dropped — a row's key is its id); every other pair is removed. Returns the removed
1298
+ * nodes.
1299
+ */
1300
+ declare function tabsToContent(root: CompositeNode, listRepeater: CompositeNode, panelsRepeater: CompositeNode): CompositeNode[];
1301
+ /**
1302
+ * From content → Manual: the rows come in as static pairs — each a copy of the template tab and panel (`clone`, which
1303
+ * gives the copy fresh ids) whose bound words are written in as its own and whose bindings are dropped. `list` and
1304
+ * `panels` are the manual holders the caller created. Returns the new pairs.
1305
+ */
1306
+ declare function tabsToManual(root: CompositeNode, list: CompositeNode, panels: CompositeNode, rows: ReadonlyArray<unknown>, clone: (template: CompositeNode) => CompositeNode, resolve: (row: unknown, binding: CompositeBinding) => unknown): TabPair[];
1307
+
1308
+ /**
1309
+ * The EXCLUSIVE composites' RUNTIME (CC4a Tabs; the Segmented control runs it too in CC4b) — ONE copy, DOM only, for
1310
+ * the builder canvas and the live site (both engine paths render the same markup from `tabs.ts`'s attribute planners):
1311
+ *
1312
+ * [root] data-iox-composite="tabs" data-iox-activate-on data-iox-orientation [data-iox-scope]
1313
+ * .iox-role-tabs-list role=tablist [aria-orientation=vertical]
1314
+ * .iox-role-tabs-trigger role=tab id aria-selected aria-controls tabindex 0|-1 data-iox-item-key [data-iox-on]
1315
+ * .iox-role-tabs-panels
1316
+ * .iox-role-tabs-panel role=tabpanel id aria-labelledby tabindex=0 data-iox-item-key [hidden] | [data-iox-on]
1317
+ *
1318
+ * Exactly one item is on, always (a Tabs with tabs never shows none). It owns: a click on a trigger turns its item on
1319
+ * (and a hover, when the root says `activate-on=hover`); the APG tabs keys with AUTOMATIC activation — ← → along a
1320
+ * horizontal list (mirrored under RTL), ↑ ↓ along a vertical one, Home / End — moving focus AND turning the item on,
1321
+ * the roving tabindex keeping one trigger in the Tab order. A trigger and its panel pair by `data-iox-item-key`
1322
+ * (else their index among their kind — the builder's From-content rows). Every change dispatches `iox-item-on` /
1323
+ * `iox-item-off` on the trigger AND its panel (the `itemOn` / `itemOff` interaction triggers). The item shown is
1324
+ * FORCED ?? LIVE: the builder forces one (a selection inside an inactive panel); the live site forces nothing. The
1325
+ * server's first state is trusted (no flash).
1326
+ */
1327
+ interface ExclusiveRuntimeOptions {
1328
+ /** The scope id the ARIA ids are built from (else `data-iox-scope`, else the root's `iox-node-<id>`). A function is
1329
+ * read at every stamp (the builder canvas: a preview row's index is known once it is in the page). */
1330
+ rootId?: string | (() => string);
1331
+ /** The behaviour (else read from the root's data attributes). */
1332
+ behaviour?: TabsBehaviour;
1333
+ /** The list's accessible name, stamped by the runtime (the builder canvas; the engine renders it). */
1334
+ label?: () => string;
1335
+ /** The key forced on, on top of the live state (the builder's design state), or null. */
1336
+ forced?: () => string | null;
1337
+ /** The live item changed (a click, a key, a hover, an action) — the builder's "Showing on canvas" follows it. */
1338
+ onChange?: (key: string) => void;
1339
+ /** Re-stamp when the markup under the root changes (the builder canvas re-renders parts). */
1340
+ observe?: boolean;
1341
+ }
1342
+ /** The exclusive composite an element belongs to (the element itself when it is a root). */
1343
+ declare function closestExclusive(el: Element | null | undefined): HTMLElement | null;
1344
+ /** The trigger or panel an element sits in (itself when it is one) — its ITEM part — or null. */
1345
+ declare function closestExclusiveItemPart(el: Element | null | undefined): HTMLElement | null;
1346
+ declare class ExclusiveRuntime {
1347
+ readonly root: HTMLElement;
1348
+ private readonly options;
1349
+ private live;
1350
+ private shown;
1351
+ private observer;
1352
+ private stampQueued;
1353
+ private behaviourValue;
1354
+ private awaitingItems;
1355
+ readonly kind: ExclusiveCompositeKind;
1356
+ constructor(root: HTMLElement, options?: ExclusiveRuntimeOptions);
1357
+ get behaviour(): TabsBehaviour;
1358
+ /** The behaviour changed in the panel (Activate on, Orientation). */
1359
+ setBehaviour(behaviour: TabsBehaviour): void;
1360
+ /** THIS composite's triggers in document order (a nested composite's are its own). */
1361
+ triggers(): HTMLElement[];
1362
+ /** THIS composite's panels in document order. */
1363
+ panels(): HTMLElement[];
1364
+ /** The key on right now (forced ?? live). */
1365
+ get activeKey(): string | null;
1366
+ /** The key the live state holds (before anything forced). */
1367
+ get liveKey(): string | null;
1368
+ /** The key of a trigger or a panel: its `data-iox-item-key`, else its index among its kind. */
1369
+ keyOf(part: Element): string;
1370
+ /** The key of the item an element sits in (a part inside a tab or a panel), or null. */
1371
+ keyAt(el: Element | null | undefined): string | null;
1372
+ /** Turn `key` on (a click, a key, a hover, the `openItem` action, "Showing on canvas"). */
1373
+ activate(key: string): void;
1374
+ /** Run an item action on `key`: Open turns it on; Close and Toggle do nothing (one item is always on). True when it
1375
+ * is on afterwards. */
1376
+ run(open: boolean, key: string): boolean;
1377
+ /** The forced key changed (builder design state): show it. */
1378
+ refresh(): void;
1379
+ destroy(): void;
1380
+ private keys;
1381
+ /** The element(s) that ARE the tablist: the ones a renderer already gave the role (the engine's component-path
1382
+ * Repeater puts it on its inner root, which holds the tabs), else the elements carrying the list's role class. */
1383
+ private lists;
1384
+ private own;
1385
+ private queueStamp;
1386
+ private rootId;
1387
+ /** Write every part's state into its markup; announce what changed. */
1388
+ private stamp;
1389
+ private ownTrigger;
1390
+ private readonly onClick;
1391
+ private readonly onHover;
1392
+ private readonly onKeydown;
1393
+ }
1394
+ /** The runtime running an exclusive root, or null. */
1395
+ declare function exclusiveRuntimeOf(root: Element | null | undefined): ExclusiveRuntime | null;
1396
+ /** Attach the runtime to one rendered exclusive root, unless it already runs one. Returns the NEW runtime, or null. */
1397
+ declare function attachExclusiveAt(root: HTMLElement, options?: Omit<ExclusiveRuntimeOptions, 'behaviour'>): ExclusiveRuntime | null;
1398
+ /** True when `el` is (or sits in) an exclusive item part — a tab or a panel. */
1399
+ declare function isExclusiveItemOn(el: Element): boolean;
1400
+ /** Subscribe to the item part `el` sits in turning on / off. Returns the unsubscribe. */
1401
+ declare function onExclusiveItemState(el: Element, on: boolean, handler: () => void): () => void;
1402
+
1403
+ /**
1404
+ * The composites' runtimes behind ONE door (CC4a): the open/close runtime (Accordion, Disclosure) and the exclusive
1405
+ * runtime (Tabs; the Segmented control in CC4b). The engine attaches whichever a rendered root needs; the interaction
1406
+ * engines (builder canvas and live site) ask these for `itemOn` / `itemOff` and run the item actions through them —
1407
+ * never a family's own function, so a new kind joins without touching either engine.
1408
+ */
1409
+ type CompositeRuntime = AccordionRuntime | ExclusiveRuntime;
1410
+ /** Attach the runtime a rendered composite root needs (its `data-iox-composite`), unless it runs one already. Returns
1411
+ * the NEW runtime, or null. */
1412
+ declare function attachCompositeAt(root: HTMLElement, options?: Omit<AccordionRuntimeOptions, 'rootId' | 'behaviour'> & Omit<ExclusiveRuntimeOptions, 'behaviour'>): CompositeRuntime | null;
1413
+ /** Subscribe to the item `el` sits in turning on / off — what the `itemOn` / `itemOff` interaction triggers listen to,
1414
+ * in both families. Returns the unsubscribe. */
1415
+ declare function onCompositeItemState(el: Element, on: boolean, handler: () => void): () => void;
1416
+ /** True when the item `el` sits in is on now (an open accordion item, the active tab or its panel). */
1417
+ declare function isCompositeItemOn(el: Element): boolean;
1418
+ /**
1419
+ * Run an item action on the element of an ITEM — an accordion item, a disclosure, or a tab (CC4a: `openItem` turns it
1420
+ * on; a Tabs always shows one, so Close and Toggle leave it) — the `openItem` / `closeItem` / `toggleItem` interaction
1421
+ * actions, on the canvas and on the live site through this one function. Returns whether the item shows on
1422
+ * afterwards, or null when `el` is in no running composite.
1423
+ */
1424
+ declare function runCompositeItemAction(el: Element | null | undefined, action: CompositeItemAction): boolean | null;
769
1425
 
770
- export { ACCORDION_BIND_PROP, ACCORDION_CONTENT_LIMIT, ACCORDION_DEFAULT_ONS, ACCORDION_ICONS, ACCORDION_ICON_GLYPH, ACCORDION_NEW_ITEM_WORDS, ACCORDION_WORDS, AccordionClass, AccordionDefaultOn, AccordionEditRefusal, AccordionIcon, AccordionKeyAction, AccordionRole, AccordionRuntime, BADGE_TONES, BADGE_TONE_ICONS, BadgeTone, CARD_LAYOUTS, CARD_LAYOUT_CUSTOM, CARD_PARTS, CARD_PART_ROLE, CARD_STACK_BREAKPOINT, CARD_WORDS, CHIP_ICON, CHIP_STYLE, COMPOSITE_ATTRIBUTE, COMPOSITE_KIND_ROLES, COMPOSITE_ROLE_SPECS, CardLayout, CardPart, CardRole, CompositeBehaviourTrait, CompositeItemAction, CompositeKind, DEFAULT_ON_ATTRIBUTE, DISCLOSURE_ITEM_KEY, DISCLOSURE_WORDS, DisclosureRole, ITEM_KEY_ATTRIBUTE, ITEM_OFF_EVENT, ITEM_ON_EVENT, ITEM_OPEN_STATE, MULTIPLE_ATTRIBUTE, ON_ATTRIBUTE, ON_STATE, PILL_LABEL_STYLE, SCOPE_ATTRIBUTE, StructureEdit, StructureRefusal, UNTIL_FOUND, accordionAnswerOf, accordionBehaviour, accordionDomIds, accordionFocusIndex, accordionHeadingLevel, accordionItemAttributes, accordionItemLabel, accordionItemOf, accordionItemState, accordionItems, accordionKeyAction, accordionPanelAttributes, accordionPanelOf, accordionPartStyle, accordionQuestionOf, accordionRegionAttributes, accordionRemovalRefusal, accordionRootAttributes, accordionRootOf, accordionRuntimeOf, accordionScope, accordionToContent, accordionToManual, accordionTrackAttributes, accordionTriggerAttributes, accordionTriggerOf, addAccordionItem, applyCardLayout, attachAccordionAt, attachAccordions, badgeStyleId, badgeToneOf, buildAccordionItem, buildAccordionRecipe, buildBadge, buildCardRecipe, buildChip, buildCompositeIcon, buildDisclosureRecipe, cardPartsOf, cardRootOf, cardTitleOf, clearLayerStyles, closeAccordionItem, closestAccordion, closestAccordionItem, compositeItemOf, compositeItems, compositeKindOfRole, compositeRootOf, compositeRowKeys, compositeScopeId, detachAccordion, detectAccordionIcon, detectCardLayout, disclosureOpenByDefault, domSafeKey, findByRole, hasLabelledRegion, initialAccordionOpen, isAccordionFromContent, isAccordionItemOn, isAccordionPart, isAccordionRoot, isCardLinked, isCardRoot, isCompositeItem, isCompositePanel, isCompositeRoot, isCompositeTrigger, isDisclosurePart, isDisclosureRoot, isLockedPart, isPillNode, itemOpenTriggerIds, makeCompositePart, moveAccordionItem, nextAccordionState, nextItemKey, onAccordionItemState, openAccordionItem, parentInComposite, pickAccordionAutoBinds, readLayerStyle, readProp, readStyle, removeFromComposite, renameAccordionItem, rowItemKey, runCompositeItemAction, serializeDomAttributes, setAccordionBehaviour, setAccordionIcon, setBadgeTone, setCardLinked, setCardPart, shouldScrollToItem, structureRefusal, walkComposite, writeLayerStyles, writeProp, writeStyles };
771
- export type { AccordionAutoBinds, AccordionBehaviour, AccordionDomIds, AccordionItemState, AccordionOptions, AccordionRuntimeOptions, AccordionScope, AccordionWords, BaselineStyles, CardEditOptions, CardLayoutResult, CardLayoutState, CardOptions, CardPartChange, CardWords, CompositeBinding, CompositeKindRoles, CompositeLayer, CompositeNode, CompositeNodeFactory, CompositeNodeSpec, CompositeRoleSpec, CompositeTrait, ContentFieldLike, DisclosureOptions, DisclosureWords, DomAttributes, PillOptions };
1426
+ export { ACCORDION_BIND_PROP, ACCORDION_CONTENT_LIMIT, ACCORDION_DEFAULT_ONS, ACCORDION_ICONS, ACCORDION_ICON_GLYPH, ACCORDION_NEW_ITEM_WORDS, ACCORDION_WORDS, ACTIVATE_ON_ATTRIBUTE, AccordionClass, AccordionDefaultOn, AccordionEditRefusal, AccordionIcon, AccordionKeyAction, AccordionRole, AccordionRuntime, BADGE_TONES, BADGE_TONE_ICONS, BadgeTone, CARD_LAYOUTS, CARD_LAYOUT_CUSTOM, CARD_PARTS, CARD_PART_ROLE, CARD_STACK_BREAKPOINT, CARD_WORDS, CAROUSEL_QUOTES, CHIP_ICON, CHIP_STYLE, COMPOSITE_ATTRIBUTE, COMPOSITE_KIND_ROLES, COMPOSITE_ROLE_SPECS, CardLayout, CardPart, CardRole, CarouselA11y, CompositeBehaviourTrait, CompositeItemAction, CompositeKind, DEFAULT_ON_ATTRIBUTE, DISCLOSURE_ITEM_KEY, DISCLOSURE_WORDS, DisclosureRole, EXCLUSIVE_KIND_ROLES, ExclusiveRuntime, ITEM_KEY_ATTRIBUTE, ITEM_OFF_EVENT, ITEM_ON_EVENT, ITEM_OPEN_STATE, LIGHTBOX_ARROWS_HIDE_AT, LIGHTBOX_LABEL, MULTIPLE_ATTRIBUTE, NO_ELEMENT_STYLE, ON_ATTRIBUTE, ON_STATE, ORIENTATION_ATTRIBUTE, PILL_LABEL_STYLE, ROW_INDEX_ATTRIBUTE, SCOPE_ATTRIBUTE, SLIDER_NAME_TRAIT, SLIDER_PART_GLYPH, SLIDER_PART_ROLES, SLIDER_PLAY_GLYPH, SLIDER_TYPE, SLIDER_WORDS, SLIDE_TO_ROW, SLIDE_TYPE, SWIPER_THEME_COLOR, SliderFlag, SliderRole, StructureEdit, StructureRefusal, TABS_ACTIVATE_ONS, TABS_CONTENT_LIMIT, TABS_IMAGE_BIND_PROP, TABS_LABEL_BIND_PROP, TABS_NEW_TAB_WORDS, TABS_ORIENTATIONS, TABS_STACK_BREAKPOINT, TABS_TEXT_BIND_PROP, TABS_WORDS, TabsActivateOn, TabsBehaviourTrait, TabsEditRefusal, TabsOrientation, TabsRole, UNTIL_FOUND, acceptsRefusal, accordionAnswerOf, accordionBehaviour, accordionDomIds, accordionFocusIndex, accordionHeadingLevel, accordionItemAttributes, accordionItemLabel, accordionItemOf, accordionItemState, accordionItems, accordionKeyAction, accordionPanelAttributes, accordionPanelOf, accordionPartStyle, accordionQuestionOf, accordionRegionAttributes, accordionRemovalRefusal, accordionRootAttributes, accordionRootOf, accordionRootOfItem, accordionRuntimeOf, accordionScope, accordionToContent, accordionToManual, accordionTrackAttributes, accordionTriggerAttributes, accordionTriggerOf, addAccordionItem, addTabPair, applyCardLayout, attachAccordionAt, attachAccordions, attachCarouselA11y, attachCompositeAt, attachExclusiveAt, badgeStyleId, badgeToneOf, buildAccordionItem, buildAccordionRecipe, buildBadge, buildCardRecipe, buildCarouselRecipe, buildChip, buildCompositeIcon, buildDisclosureRecipe, buildLightboxRecipe, buildSliderPart, buildTabPair, buildTabsRecipe, canOpenAtClickedItem, cardPartsOf, cardRootOf, cardTitleOf, carouselOf, clearLayerStyles, closeAccordionItem, closestAccordion, closestAccordionItem, closestExclusive, closestExclusiveItemPart, compositeItemOf, compositeItems, compositeKindOfRole, compositeRootOf, compositeRowKeys, compositeScopeId, detachAccordion, detectAccordionIcon, detectCardLayout, disclosureOpenByDefault, domSafeKey, exclusiveItemPartOf, exclusiveRootOf, exclusiveRuntimeOf, findByRole, hasLabelledRegion, hasSliderParts, initialAccordionOpen, isAccordionFromContent, isAccordionItemOn, isAccordionPart, isAccordionRoot, isAnyCompositeRoot, isCardLinked, isCardRoot, isCompositeItem, isCompositeItemOn, isCompositePanel, isCompositeRoot, isCompositeTrigger, isDisclosurePart, isDisclosureRoot, isExclusiveItemOn, isExclusiveItemPart, isExclusiveKind, isExclusiveList, isExclusivePanel, isExclusivePanels, isExclusiveRoot, isExclusiveTrigger, isLockedPart, isPillNode, isSlider, isSliderPart, isTabsFromContent, isTabsPart, isTabsRoot, isToggleKind, itemOpenTriggerIds, lightboxSliderOf, makeCompositePart, manualTabKeys, migrateSliderControls, moveAccordionItem, moveTabPair, needsSliderMigration, nextAccordionState, nextItemKey, nextTabKey, onAccordionItemState, onCompositeItemState, onExclusiveItemState, openAccordionItem, parentInComposite, pickAccordionAutoBinds, pickTabsAutoBinds, readLayerStyle, readProp, readStyle, removeFromComposite, removeTabPair, renameAccordionItem, renameTab, repeatSourceOf, rowIndexOf, rowItemKey, rowSourceOf, runCompositeItemAction, sameRepeatSource, serializeDomAttributes, setAccordionBehaviour, setAccordionIcon, setBadgeTone, setCardLinked, setCardPart, setSliderFlag, setTabsBehaviour, shouldScrollToItem, slideIndexForRow, sliderLiveRegion, sliderPart, sliderPartElement, sliderPauseAttributes, sliderPauseGlyph, sliderSlides, sliderWords, splitSliderChildren, structureRefusal, syncSliderParts, tabLabel, tabLabelNodeOf, tabListAttributes, tabPanelAttributes, tabPanelImageOf, tabPanelOf, tabPanelTextOf, tabPartKey, tabTriggerAttributes, tabTriggerOf, tabsBehaviour, tabsItemState, tabsItemTriggerIds, tabsKeyAction, tabsLabel, tabsListOf, tabsPanels, tabsPanelsOf, tabsPartAttributes, tabsPartnerOf, tabsRemovalRefusal, tabsRootAttributes, tabsScope, tabsScopeFor, tabsToContent, tabsToManual, tabsTriggers, walkComposite, wantedSliderParts, writeLayerStyles, writeProp, writeStyles };
1427
+ export type { AccordionAutoBinds, AccordionBehaviour, AccordionDomIds, AccordionItemState, AccordionOptions, AccordionRuntimeOptions, AccordionScope, AccordionWords, BaselineStyles, CardEditOptions, CardLayoutResult, CardLayoutState, CardOptions, CardPartChange, CardWords, CarouselA11yOptions, CarouselOptions, CarouselQuote, CarouselSwiper, CompositeBinding, CompositeKindRoles, CompositeLayer, CompositeNode, CompositeNodeFactory, CompositeNodeSpec, CompositeRoleSpec, CompositeRuntime, CompositeTrait, ContentFieldLike, DisclosureOptions, DisclosureWords, DomAttributes, ExclusiveCompositeKind, ExclusiveKindRoles, ExclusiveRuntimeOptions, LegacySliderLook, LightboxOptions, PillOptions, RepeatSource, SliderPartsChange, SliderWords, TabPair, TabWords, TabsAutoBinds, TabsBehaviour, TabsItemState, TabsOptions, TabsScope, ToggleCompositeKind };