@vectoriox/iox-ui 5.57.0 → 5.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/composite-core/index.d.ts +3 -3
  2. package/design-core/index.d.ts +40 -2
  3. package/fesm2022/vectoriox-iox-ui-composite-core.mjs +6 -10
  4. package/fesm2022/vectoriox-iox-ui-composite-core.mjs.map +1 -1
  5. package/fesm2022/vectoriox-iox-ui-design-core.mjs +46 -1
  6. package/fesm2022/vectoriox-iox-ui-design-core.mjs.map +1 -1
  7. package/fesm2022/vectoriox-iox-ui-generation-core.mjs +4043 -740
  8. package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
  9. package/fesm2022/vectoriox-iox-ui-harness-core.mjs +5 -7
  10. package/fesm2022/vectoriox-iox-ui-harness-core.mjs.map +1 -1
  11. package/fesm2022/vectoriox-iox-ui.mjs +27 -1
  12. package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
  13. package/generation-core/index.d.ts +3740 -1100
  14. package/harness-core/index.d.ts +6 -6
  15. package/index.d.ts +22 -1
  16. package/package.json +1 -1
  17. package/src/composite-core/accordion-runtime.ts +2 -1
  18. package/src/composite-core/lightbox.ts +5 -6
  19. package/src/design-core/entrance-timing.ts +56 -0
  20. package/src/design-core/public-api.ts +1 -0
  21. package/src/generation-core/compose-site.ts +213 -42
  22. package/src/generation-core/entrances.ts +82 -13
  23. package/src/generation-core/patterns.ts +127 -15
  24. package/src/generation-core/plan-words.ts +3 -2
  25. package/src/generation-core/public-api.ts +3 -2
  26. package/src/generation-core/showcase.ts +81 -0
  27. package/src/generation-core/site-plan-schema.ts +21 -8
  28. package/src/generation-core/site-plan.model.ts +75 -4
  29. package/src/generation-core/site-spec.generated.ts +4019 -1174
  30. package/src/generation-core/validate-site-plan.ts +129 -21
  31. package/src/harness-core/harness-spec.generated.ts +3 -3
  32. package/src/harness-core/intake.ts +3 -4
@@ -110,13 +110,13 @@ declare const SPEC_STRUCTURES: {
110
110
  readonly label: "Practice";
111
111
  readonly blurb: "Services, prices and a clear way to book.";
112
112
  readonly pages: readonly ["Home", "Services", "Prices", "About", "Contact"];
113
- readonly shipped: false;
113
+ readonly shipped: true;
114
114
  };
115
115
  readonly place: {
116
116
  readonly label: "Place";
117
117
  readonly blurb: "A menu, opening hours and how to find you.";
118
- readonly pages: readonly ["Home", "Menu", "Visit (hours + map)", "About", "Contact"];
119
- readonly shipped: false;
118
+ readonly pages: readonly ["Home", "Menu", "Visit (hours and address)", "About", "Contact"];
119
+ readonly shipped: true;
120
120
  };
121
121
  };
122
122
  declare const SPEC_BUSINESS_TYPES: readonly [{
@@ -2136,13 +2136,13 @@ declare const STRUCTURES: {
2136
2136
  readonly label: "Practice";
2137
2137
  readonly blurb: "Services, prices and a clear way to book.";
2138
2138
  readonly pages: readonly ["Home", "Services", "Prices", "About", "Contact"];
2139
- readonly shipped: false;
2139
+ readonly shipped: true;
2140
2140
  };
2141
2141
  readonly place: {
2142
2142
  readonly label: "Place";
2143
2143
  readonly blurb: "A menu, opening hours and how to find you.";
2144
- readonly pages: readonly ["Home", "Menu", "Visit (hours + map)", "About", "Contact"];
2145
- readonly shipped: false;
2144
+ readonly pages: readonly ["Home", "Menu", "Visit (hours and address)", "About", "Contact"];
2145
+ readonly shipped: true;
2146
2146
  };
2147
2147
  };
2148
2148
  /** How much a kind of business needs "book a slot" — the next product bet (off this road). */
package/index.d.ts CHANGED
@@ -2229,6 +2229,27 @@ declare function keyframeStyleEntries(frame: InteractionKeyframe | null | undefi
2229
2229
  * CSS — so the server render ships it already hidden (no visible→hidden flash). `{}` for anything else.
2230
2230
  */
2231
2231
  declare function entrancePreStateStyle(type: string, params?: Readonly<Record<string, unknown>> | null): Record<string, string>;
2232
+ /** Triggers that play an entrance by themselves — the page loading or arriving, the element scrolling into view. */
2233
+ declare const SELF_PLAYING_TRIGGERS: ReadonlySet<string>;
2234
+ /**
2235
+ * Whether an entrance on `trigger` starts hidden (its pre-state). Always — a menu revealed by a click must stay hidden
2236
+ * until the click — except a self-playing one under reduced motion: it would only ever reveal what is already there,
2237
+ * so it starts shown and never moves (M1-6b: "nothing moves and nothing stays hidden"). Both runtimes ask this.
2238
+ */
2239
+ declare function entranceStartsHidden(trigger: string, reducedMotion?: boolean): boolean;
2240
+ /** The attribute a SERVER render puts on an element it ships in its entrance's first frame (`entrancePreStateStyle`).
2241
+ * The live runtime takes the element over — and drops the attribute — when it attaches; until then the fallback CSS
2242
+ * below reads it. */
2243
+ declare const ENTRANCE_PRESTATE_ATTRIBUTE = "data-iox-enter";
2244
+ /**
2245
+ * What keeps a server-rendered entrance from hiding content where nothing will play it (AI plan §5 "Entrances that hide
2246
+ * content"; M1-6b): under reduced motion every pre-stated element is shown at once, before any script; and if the
2247
+ * runtime never takes an element over (a script that failed), it is revealed after a few seconds. One stylesheet for
2248
+ * the engine's head — `ENTRANCE_NOSCRIPT_CSS` covers a visitor with no script at all.
2249
+ */
2250
+ declare const ENTRANCE_FALLBACK_CSS: string;
2251
+ /** The same, for a visitor with no script: every pre-stated element shown at once (served inside `<noscript>`). */
2252
+ declare const ENTRANCE_NOSCRIPT_CSS = "[data-iox-enter]{opacity:1!important;transform:none!important;visibility:visible!important;pointer-events:auto!important;animation:none!important}";
2232
2253
  /** The frame an animation comes to rest on (what reduced motion applies at once). */
2233
2254
  declare function finalKeyframe(frames: ReadonlyArray<InteractionKeyframe> | null | undefined): InteractionKeyframe | null;
2234
2255
 
@@ -3175,5 +3196,5 @@ declare class GalleryLoop {
3175
3196
  private emit;
3176
3197
  }
3177
3198
 
3178
- export { A11yAttribute, A11yTrait, ACCESSIBLE_NAME_TYPES, AOSService, ARIA_CURRENT_PAGE, BACKDROP_TWIN_KEY, BACKDROP_WHOLE_KEY, BREAKPOINTS, Breakpoint, BreakpointQueryKind, BuilderButtonComponent, BuilderDividerComponent, BuilderHeadingComponent, BuilderIconComponent, BuilderImageComponent, BuilderLinkComponent, BuilderSpacerComponent, ButtonBlockComponent, COMPONENT_STATE_SELECTOR, CONTAINER_HTML_TAGS, CONTEXT_ACTION_TYPES, CURRENT_LINK_TYPES, CardComponent, ClientGalleryComponent, ClientListComponent, ClientListItemComponent, ClientRepeaterComponent, ClientSliderContainerComponent, ClientSliderSlideComponent, ComponentInstanceRegistryService, ComponentState, ContainerComponent, ContextStore, DECORATIVE_TYPES, DEFAULT_GALLERY_SCHEDULER, DEFAULT_PAGE_TRANSITION, DEFAULT_PAGE_TRANSITION_DURATION, DEFAULT_PAGE_TRANSITION_EASING, DEFAULT_PAGE_TRANSITION_PERSPECTIVE, DEFAULT_PHOSPHOR_WEIGHT, DEFAULT_WIDTH_BY_TYPE, DIALOG_CLOSE_ABOVE_ATTRIBUTE, DIALOG_NODE_TYPE, DeclarationContext, ENTRANCE_ACTION_TYPES, EXIT_ACTION_TYPES, FormRenderState, FormRuntimeService, GALLERY_EFFECTS, GALLERY_EFFECT_DESCRIPTORS, GalleryLoop, HOVER_DEFAULT_TRANSITION, HOVER_STATES, INTERACTION_HIDDEN_ATTRIBUTE, IOX_BUILDER_EVENTS, IOX_FORM_MESSAGES, IOX_FORM_NAVIGATOR, IOX_FORM_TRANSPORT, IS_PREVIEW, IoxAnimateContainer, IoxAosDirective, IoxAosModule, IoxBuilderComponentsModule, IoxComponentRegistryService, IoxDialogComponent, IoxFieldComponent, IoxFormComponent, IoxFormErrorComponent, IoxFormSuccessComponent, IoxPageComponent, IoxPageModule, IoxSubmitButtonComponent, IoxUiModule, IoxVideoComponent, LAST_EMITTED_STATES, LEGACY_DIRECTION_KEY, LEGACY_HOVER_TRANSITION, LEGACY_SWIPER_CONTROLS, LinkedContainerComponent, MANAGED_A11Y_ATTRIBUTES, MAX_LINES_KEY, NAMED_GROUP_ROLES, NO_PAGE_TRANSITION, ON_STATE_ROLES, PAGE_STYLE_TOKENS, PAGE_TOKEN_FALLBACKS, PAGE_TRANSITION_CATEGORIES, PAGE_TRANSITION_PRESETS, PART_CLASS_NAMES, PART_PAGINATION_MODIFIER, PHONE_TRANSITION_QUERY, PIPE_DESCRIPTORS, PIPE_REGISTRY, PageScrollProvider, PageStyleField, PageStyleSource, REDUCED_MOTION_QUERY, SCROLL_EASINGS, SLIDER_INPUTS_ATTRIBUTE, SLIDER_INPUT_NAMES, STATE_PSEUDO_CLASS, SUPPRESSED_STYLE_PROPS_BY_TYPE, SWIPER_A11Y_OPTIONS, SWIPER_RESPONSIVE_TRAITS, SWIPER_TRIGGER_EVENTS, ScrollEasing, SectionComponent, SwiperModuleName, TARGETED_STATE_SUFFIX, TEXT_ALIGN_KEY, TEXT_DIRECTION_KEY, TRANSITION_FEELS, TextAlign, TextBlockComponent, VALIDATION_STATES, VALIDATION_STATE_CLASS, VIRTUAL_TRAIT_GROUPS, VIRTUAL_TRAIT_KEYS, ViewPositionDirective, ViewPositionModule, VisibilityActionType, activeActions, applyBindingPipes, applyFeel, bootSlider, breakpointDef, breakpointForWidth, breakpointQueryFor, buildInteractionKeyframes, buildPartSelector, buildSwiperBreakpoints, buildTargetedStateSelector, buildTargetedSuffixSelector, buildTransitionTimeline, cascadeChain, clearInputOverride, clearOverride, closeAboveMediaQuery, collectContextSlotKeys, compileDeclarations, compilePageStyle, componentStatesFor, composeVirtualTraits, containerHtmlTag, contextActionEffect, contextSlotKeys, countOverrides, declaredInputNames, decomposeBackdropFilter, defaultHoverTransition, defaultMessageResolver, deriveSeoFromContent, describePageStyle, describeSeoFields, dialogCloseAboveMinWidth, domHasSliderParts, effectiveActionType, effectiveTransitionId, entrancePreStateStyle, feelFor, finalKeyframe, getSeoValue, hasHoverState, hasOwnPageTransition, hasOwnTransition, initialSlotValues, isActionEnabled, isContextAction, isCurrentLink, isExternalOrFragment, isGradientPaint, isInputOverriddenAt, isLastEmittedStateKey, isOverriddenAt, isValidSlotKey, isWholeBackdropSet, keyframePropertyName, keyframeStyleEntries, legacyEnterToTransition, mediaQueryFor, mergeSwiperBreakpoints, migrateLegacyDirection, migrateLegacyTextAlign, motionAllowed, nearestCommonAncestorId, needsAccessibleName, needsGroupName, nodeA11yAttributes, nodeCssId, nodeTraitValue, nodeUsesContext, normalizeAppPath, normalizeGalleryImage, normalizeIconClass, orderStatesForEmit, pageTransitionOf, parentBreakpoint, parseUrlList, partClassName, planResponsiveRules, planScroll, planSwiperOptions, playDualLayerTransition, prefersReducedMotion, renderDefaultDeclarations, resetPageStyleField, resetSeoField, resolveBoundValue, resolveContextValue, resolveGalleryEffect, resolveGalleryUrls, resolveInputChain, resolveInputs, resolvePageTransition, resolvePath, resolveSeo, resolveStateStyles, resolveStyleProps, resolveToggleVisibility, resolveValueChain, rewriteViewportUnits, safeSetInput, serializeA11yAttributes, setInputOverride, setOverride, setSeoAuto, setSeoBinding, setSeoOverride, setSeoValue, sliderControlElements, sliderInputsFromProps, sliderInputsOf, stateNamesIn, statePseudoClass, stateSelectorSuffix, stripSuppressedProps, swiperAutoplayAllowed, swiperLoopOptions, swiperModuleNames, syncNodeA11yAttributes, targetedStateSelector, viewportTransitionContext, withContextSlots, withDefaultHoverTransition, wrapInBreakpointQuery, wrapInMediaQuery };
3199
+ export { A11yAttribute, A11yTrait, ACCESSIBLE_NAME_TYPES, AOSService, ARIA_CURRENT_PAGE, BACKDROP_TWIN_KEY, BACKDROP_WHOLE_KEY, BREAKPOINTS, Breakpoint, BreakpointQueryKind, BuilderButtonComponent, BuilderDividerComponent, BuilderHeadingComponent, BuilderIconComponent, BuilderImageComponent, BuilderLinkComponent, BuilderSpacerComponent, ButtonBlockComponent, COMPONENT_STATE_SELECTOR, CONTAINER_HTML_TAGS, CONTEXT_ACTION_TYPES, CURRENT_LINK_TYPES, CardComponent, ClientGalleryComponent, ClientListComponent, ClientListItemComponent, ClientRepeaterComponent, ClientSliderContainerComponent, ClientSliderSlideComponent, ComponentInstanceRegistryService, ComponentState, ContainerComponent, ContextStore, DECORATIVE_TYPES, DEFAULT_GALLERY_SCHEDULER, DEFAULT_PAGE_TRANSITION, DEFAULT_PAGE_TRANSITION_DURATION, DEFAULT_PAGE_TRANSITION_EASING, DEFAULT_PAGE_TRANSITION_PERSPECTIVE, DEFAULT_PHOSPHOR_WEIGHT, DEFAULT_WIDTH_BY_TYPE, DIALOG_CLOSE_ABOVE_ATTRIBUTE, DIALOG_NODE_TYPE, DeclarationContext, ENTRANCE_ACTION_TYPES, ENTRANCE_FALLBACK_CSS, ENTRANCE_NOSCRIPT_CSS, ENTRANCE_PRESTATE_ATTRIBUTE, EXIT_ACTION_TYPES, FormRenderState, FormRuntimeService, GALLERY_EFFECTS, GALLERY_EFFECT_DESCRIPTORS, GalleryLoop, HOVER_DEFAULT_TRANSITION, HOVER_STATES, INTERACTION_HIDDEN_ATTRIBUTE, IOX_BUILDER_EVENTS, IOX_FORM_MESSAGES, IOX_FORM_NAVIGATOR, IOX_FORM_TRANSPORT, IS_PREVIEW, IoxAnimateContainer, IoxAosDirective, IoxAosModule, IoxBuilderComponentsModule, IoxComponentRegistryService, IoxDialogComponent, IoxFieldComponent, IoxFormComponent, IoxFormErrorComponent, IoxFormSuccessComponent, IoxPageComponent, IoxPageModule, IoxSubmitButtonComponent, IoxUiModule, IoxVideoComponent, LAST_EMITTED_STATES, LEGACY_DIRECTION_KEY, LEGACY_HOVER_TRANSITION, LEGACY_SWIPER_CONTROLS, LinkedContainerComponent, MANAGED_A11Y_ATTRIBUTES, MAX_LINES_KEY, NAMED_GROUP_ROLES, NO_PAGE_TRANSITION, ON_STATE_ROLES, PAGE_STYLE_TOKENS, PAGE_TOKEN_FALLBACKS, PAGE_TRANSITION_CATEGORIES, PAGE_TRANSITION_PRESETS, PART_CLASS_NAMES, PART_PAGINATION_MODIFIER, PHONE_TRANSITION_QUERY, PIPE_DESCRIPTORS, PIPE_REGISTRY, PageScrollProvider, PageStyleField, PageStyleSource, REDUCED_MOTION_QUERY, SCROLL_EASINGS, SELF_PLAYING_TRIGGERS, SLIDER_INPUTS_ATTRIBUTE, SLIDER_INPUT_NAMES, STATE_PSEUDO_CLASS, SUPPRESSED_STYLE_PROPS_BY_TYPE, SWIPER_A11Y_OPTIONS, SWIPER_RESPONSIVE_TRAITS, SWIPER_TRIGGER_EVENTS, ScrollEasing, SectionComponent, SwiperModuleName, TARGETED_STATE_SUFFIX, TEXT_ALIGN_KEY, TEXT_DIRECTION_KEY, TRANSITION_FEELS, TextAlign, TextBlockComponent, VALIDATION_STATES, VALIDATION_STATE_CLASS, VIRTUAL_TRAIT_GROUPS, VIRTUAL_TRAIT_KEYS, ViewPositionDirective, ViewPositionModule, VisibilityActionType, activeActions, applyBindingPipes, applyFeel, bootSlider, breakpointDef, breakpointForWidth, breakpointQueryFor, buildInteractionKeyframes, buildPartSelector, buildSwiperBreakpoints, buildTargetedStateSelector, buildTargetedSuffixSelector, buildTransitionTimeline, cascadeChain, clearInputOverride, clearOverride, closeAboveMediaQuery, collectContextSlotKeys, compileDeclarations, compilePageStyle, componentStatesFor, composeVirtualTraits, containerHtmlTag, contextActionEffect, contextSlotKeys, countOverrides, declaredInputNames, decomposeBackdropFilter, defaultHoverTransition, defaultMessageResolver, deriveSeoFromContent, describePageStyle, describeSeoFields, dialogCloseAboveMinWidth, domHasSliderParts, effectiveActionType, effectiveTransitionId, entrancePreStateStyle, entranceStartsHidden, feelFor, finalKeyframe, getSeoValue, hasHoverState, hasOwnPageTransition, hasOwnTransition, initialSlotValues, isActionEnabled, isContextAction, isCurrentLink, isExternalOrFragment, isGradientPaint, isInputOverriddenAt, isLastEmittedStateKey, isOverriddenAt, isValidSlotKey, isWholeBackdropSet, keyframePropertyName, keyframeStyleEntries, legacyEnterToTransition, mediaQueryFor, mergeSwiperBreakpoints, migrateLegacyDirection, migrateLegacyTextAlign, motionAllowed, nearestCommonAncestorId, needsAccessibleName, needsGroupName, nodeA11yAttributes, nodeCssId, nodeTraitValue, nodeUsesContext, normalizeAppPath, normalizeGalleryImage, normalizeIconClass, orderStatesForEmit, pageTransitionOf, parentBreakpoint, parseUrlList, partClassName, planResponsiveRules, planScroll, planSwiperOptions, playDualLayerTransition, prefersReducedMotion, renderDefaultDeclarations, resetPageStyleField, resetSeoField, resolveBoundValue, resolveContextValue, resolveGalleryEffect, resolveGalleryUrls, resolveInputChain, resolveInputs, resolvePageTransition, resolvePath, resolveSeo, resolveStateStyles, resolveStyleProps, resolveToggleVisibility, resolveValueChain, rewriteViewportUnits, safeSetInput, serializeA11yAttributes, setInputOverride, setOverride, setSeoAuto, setSeoBinding, setSeoOverride, setSeoValue, sliderControlElements, sliderInputsFromProps, sliderInputsOf, stateNamesIn, statePseudoClass, stateSelectorSuffix, stripSuppressedProps, swiperAutoplayAllowed, swiperLoopOptions, swiperModuleNames, syncNodeA11yAttributes, targetedStateSelector, viewportTransitionContext, withContextSlots, withDefaultHoverTransition, wrapInBreakpointQuery, wrapInMediaQuery };
3179
3200
  export type { A11yNodeSource, BoundValueSpec, BreakpointDef, ContextActionEffect, ContextActionLike, ContextItemRef, ContextSlotDefault, ContextValueSpec, ContextWriteScope, CurrentLinkOptions, FormMessageResolver, GalleryBoundSource, GalleryDurations, GalleryEffect, GalleryEffectDescriptor, GalleryImage, GalleryLoopOptions, GalleryLoopScheduler, GalleryLoopState, GallerySlideState, IBuilderEventEmitter, InputMap, InteractionKeyframe, IoxContextSlot, IoxPipe, MatchMediaHost, NodeA11yContext, OverrideBreakpoint, PageScrollStart, PageStyleFieldState, PageStyleOptions, PageStyleSettings, PageTransitionCategory, PageTransitionCategoryMeta, PageTransitionContext, PageTransitionOptions, PageTransitionPreset, PipeArgSpec, PipeContext, PipeDescriptor, PlannedPageTransition, ResolvedPageTransition, ResponsiveLayer, ResponsiveOverrides, ResponsiveRuleSet, RouteAnimationLike, ScrollPlanContext, SeoDerivedContent, SeoFieldSource, SeoFieldState, SeoResolveContext, SetContextParams, SliderBootOptions, SliderControlElements, SliderInputs, StateStyleMap, StyleMap, StyleTreeNode, SwiperBreakpointMap, SwiperModuleFlags, SwiperPlan, SwiperPlanContext, ToggleableAction, TransitionFeel, TransitionPhase, TransitionPreviewLayers, TransitionTimelineInput, TransitionViewport, ValueSource, VirtualTraitGroup };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectoriox/iox-ui",
3
- "version": "5.57.0",
3
+ "version": "5.58.1",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=20.0.0",
6
6
  "@angular/core": ">=20.0.0",
@@ -1,3 +1,5 @@
1
+ import { ROW_INDEX_ATTRIBUTE } from '@vectoriox/iox-ui/design-core';
2
+
1
3
  import {
2
4
  AccordionBehaviour, AccordionClass, AccordionDefaultOn, accordionDomIds, accordionFocusIndex, accordionKeyAction,
3
5
  ACCORDION_DEFAULT_ONS, closeAccordionItem, COMPOSITE_ATTRIBUTE, DEFAULT_ON_ATTRIBUTE, hasLabelledRegion, initialAccordionOpen, ITEM_KEY_ATTRIBUTE,
@@ -394,7 +396,6 @@ export function detachAccordion(runtime: AccordionRuntime): void {
394
396
  * destroy), so an item action finds the runtime of whatever item it targets. */
395
397
  const RUNTIMES = new WeakMap<Element, AccordionRuntime>();
396
398
 
397
- const ROW_INDEX_ATTRIBUTE = 'data-iox-row-idx';
398
399
 
399
400
  /** The repeated rows an element sits in, outermost first — each row's index as its row wrappers stamp it
400
401
  * (`data-iox-row-idx`: the builder's Repeater rows, the engine's component path). The builder folds them into a
@@ -1,4 +1,4 @@
1
- import { setColorScheme } from '@vectoriox/iox-ui/design-core';
1
+ import { repeatedRowIndex, ROW_INDEX_ATTRIBUTE, setColorScheme } from '@vectoriox/iox-ui/design-core';
2
2
 
3
3
  import { CompositeNode, CompositeNodeFactory, makeCompositePart, NO_ELEMENT_STYLE, readProp, writeProp, writeStyles } from './composite-node';
4
4
  import { buildSliderPart, SLIDE_TYPE, SLIDER_TYPE, SliderRole } from './slider';
@@ -20,8 +20,9 @@ import { buildSliderPart, SLIDE_TYPE, SLIDER_TYPE, SliderRole } from './slider';
20
20
  */
21
21
 
22
22
  export const SLIDE_TO_ROW = 'row';
23
- /** The attribute a renderer writes on every repeated row (the context-state provenance, both engine paths, the canvas). */
24
- export const ROW_INDEX_ATTRIBUTE = 'data-iox-row-idx';
23
+ /** The attribute a renderer writes on every repeated row (the context-state provenance, both engine paths, the canvas) —
24
+ * defined once in design-core (the entrance stagger reads it too). */
25
+ export { ROW_INDEX_ATTRIBUTE };
25
26
  export const LIGHTBOX_LABEL = 'Lightbox';
26
27
  const DIALOG = 'Dialog';
27
28
  const REPEATER = 'Repeater';
@@ -186,7 +187,5 @@ export function canOpenAtClickedItem(ownerPath: ReadonlyArray<CompositeNode>, di
186
187
 
187
188
  /** The repeated row an element sits in (its row index), 0 when it is in none (the canvas' template row). */
188
189
  export function rowIndexOf(el: Element | null | undefined): number {
189
- const row = el?.closest?.(`[${ROW_INDEX_ATTRIBUTE}]`);
190
- const index = Number(row?.getAttribute(ROW_INDEX_ATTRIBUTE));
191
- return Number.isInteger(index) && index >= 0 ? index : 0;
190
+ return repeatedRowIndex(el) ?? 0;
192
191
  }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * WHEN a look-stamped entrance plays (AI plan rev 3.1 §3p, G29) — the one piece of timing both interaction runtimes, the
3
+ * composer and the Design specimen share. An item entrance names `stagger` (ms per item) and `cap` (how many items wait
4
+ * longer than the one before): a static row of cards gets its delays written at stamp time (`staggerDelay`), a Repeater's
5
+ * rows share ONE template node, so its entrance carries them as params and each runtime adds them for the row it plays on
6
+ * (`entranceDelay`, the row read from `data-iox-row-idx`). Pure.
7
+ */
8
+
9
+ /** The params an item entrance carries for a Repeater's rows. */
10
+ export enum EntranceParam {
11
+ Distance = 'distance',
12
+ Stagger = 'stagger',
13
+ Cap = 'cap',
14
+ }
15
+
16
+ /** The row attribute both renderers write on a repeated row (its 0-based index in the source) — the ONE definition. */
17
+ export const ROW_INDEX_ATTRIBUTE = 'data-iox-row-idx';
18
+
19
+ export interface StaggerSpec {
20
+ readonly stagger?: number;
21
+ readonly cap?: number;
22
+ }
23
+
24
+ /** The delay of the `index`-th item: `stagger` ms each, the last `cap` waiting no longer than the one before. */
25
+ export function staggerDelay(spec: StaggerSpec, index = 0): number {
26
+ const stagger = Number(spec.stagger ?? 0);
27
+ if (!(stagger > 0)) return 0;
28
+ const cap = Math.max(1, Math.floor(Number(spec.cap ?? 1)) || 1);
29
+ const i = Number.isFinite(index) ? Math.max(0, Math.floor(index)) : 0;
30
+ return Math.min(i, cap - 1) * stagger;
31
+ }
32
+
33
+ /** What an action carries, as both runtimes read it. */
34
+ export interface TimedAction {
35
+ readonly delay?: number;
36
+ readonly params?: Readonly<Record<string, unknown>> | null;
37
+ }
38
+
39
+ /**
40
+ * The delay an action plays with on the row at `rowIndex`: its own delay, plus — when it carries a stagger — that row's
41
+ * share (`staggerDelay`). No row (`null`, the template outside a Repeater) adds nothing.
42
+ */
43
+ export function entranceDelay(action: TimedAction, rowIndex: number | null | undefined): number {
44
+ const own = Number(action.delay ?? 0) || 0;
45
+ const params = action.params ?? {};
46
+ if (rowIndex === null || rowIndex === undefined || params[EntranceParam.Stagger] === undefined) return own;
47
+ return own + staggerDelay({ stagger: Number(params[EntranceParam.Stagger]), cap: Number(params[EntranceParam.Cap] ?? 1) }, rowIndex);
48
+ }
49
+
50
+ /** The row index an element sits in (the nearest `data-iox-row-idx` up its tree), or null outside a Repeater's rows. */
51
+ export function repeatedRowIndex(el: { closest?: (selector: string) => { getAttribute(name: string): string | null } | null } | null | undefined): number | null {
52
+ const raw = el?.closest?.(`[${ROW_INDEX_ATTRIBUTE}]`)?.getAttribute(ROW_INDEX_ATTRIBUTE);
53
+ if (raw === null || raw === undefined || raw === '') return null;
54
+ const n = Number(raw);
55
+ return Number.isInteger(n) && n >= 0 ? n : null;
56
+ }
@@ -25,6 +25,7 @@ export * from './contrast-audit';
25
25
  export * from './flavor-tokens';
26
26
  export * from './flavor-seed';
27
27
  export * from './spring';
28
+ export * from './entrance-timing';
28
29
  export * from './fonts';
29
30
  export * from './token-names';
30
31
  export * from './design-settings';