@vectoriox/iox-builder 11.10.3 → 11.11.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.
|
@@ -17,7 +17,7 @@ import { TooltipModule } from 'primeng/tooltip';
|
|
|
17
17
|
import * as i20 from 'primeng/dialog';
|
|
18
18
|
import { DialogModule } from 'primeng/dialog';
|
|
19
19
|
import * as i1$1 from '@vectoriox/iox-ui';
|
|
20
|
-
import { nodeCssId, needsGroupName, resolveBoundValue, VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, TEXT_DIRECTION_KEY, TEXT_ALIGN_KEY, TextAlign, COLOR_SCHEME_TRAIT, COLOR_SCHEMES, ColorScheme, LinkType, MAX_LINES_KEY, A11yTrait, BREAKPOINTS, Breakpoint, withSchemeInk, stripSuppressedProps, DeclarationContext,
|
|
20
|
+
import { nodeCssId, needsGroupName, resolveBoundValue, STRUCTURAL_STATES as STRUCTURAL_STATES$1, VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, TEXT_DIRECTION_KEY, TEXT_ALIGN_KEY, TextAlign, COLOR_SCHEME_TRAIT, COLOR_SCHEMES, ColorScheme, LinkType, MAX_LINES_KEY, A11yTrait, BREAKPOINTS, Breakpoint, withSchemeInk, stripSuppressedProps, DeclarationContext, planPartRule, planResponsiveRules, resolveStyleProps, planStateRule, splitOuterProps, OUTER_STYLE_PROPS, compileTokenCssBlocks, catalogFontId, fontsForTokens, GOOGLE_FONTS_FILE_ORIGIN, googleFontHref, compileDeclarations, isLastEmittedStateKey, wrapInBreakpointQuery, BreakpointQueryKind, NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, applyElementStyle, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, ContextStore, ENTRANCE_ACTION_TYPES, EXIT_ACTION_TYPES, ComponentInstanceRegistryService, entranceStartsHidden, isActionEnabled, isContextAction, contextActionEffect, resolveContextValue, effectiveActionType, INTERACTION_HIDDEN_ATTRIBUTE, motionAllowed, settleInteraction, settleModeFor, playInteraction, entranceDelay, repeatedRowIndex, entrancePreStateStyle, buildInteractionKeyframes, cascadeChain, declaredInputNames, emptyImagePlaceholder, syncNodeDesignClasses, nodeTraitValue, syncNodeA11yAttributes, nodeA11yAttributes, safeSetInput, colorSchemeOf, composeVirtualTraits, withDefaultHoverTransition, stateNamesIn, partClassName, switchElementStyle, releaseElementStyle, countOverrides, setOverride, breakpointDef, breakpointForWidth, FormRenderState, needsAccessibleName, resolveInputs, setInputOverride, barReserveClass, collectContextSlotKeys, withContextSlots, compilePageStyle, nodeUsesContext, syncSubmitButtons, IS_PREVIEW, buttonBlockHref, bootSlider, IoxPageModule, PALETTE_PRESETS, elementStyleById, PART_CLASS_NAMES } from '@vectoriox/iox-ui';
|
|
21
21
|
export { ComponentInstanceRegistryService, VIRTUAL_TRAIT_KEYS, composeVirtualTraits } from '@vectoriox/iox-ui';
|
|
22
22
|
import { StructureEdit, isAccordionPart, isDisclosurePart, isSliderPart, isTabsPart, isSegmentedPart, structureRefusal, StructureRefusal, SegmentedRole, SEGMENTED_MAX_OPTIONS, AccordionRole, SEGMENTED_MIN_OPTIONS, isExclusiveItemPart, TabsRole, ITEM_OPEN_STATE, readStyle, isSegmentedRoot, segmentedDefaultOn, segmentedOptions, isTabsRoot, isTabsFromContent, tabsTriggers, isAccordionRoot, isAccordionFromContent, accordionItems, initialAccordionOpen, accordionBehaviour, exclusiveItemLabel, exclusiveRootOf, tabTriggerOf, tabLabel, removeTabPair, tabPanelOf, tabsListOf, tabsPanelsOf, nextTabKey, CompositeBehaviourTrait, ACCORDION_DEFAULT_ONS, TabsBehaviourTrait, TABS_ACTIVATE_ONS, TABS_ORIENTATIONS, onCompositeItemState, isCompositeItemOn, runCompositeItemAction, shouldScrollToItem, rowIndexOf as rowIndexOf$1, slideIndexForRow, DisclosureRole, isExclusiveTrigger, compositeScopeId, compositeRowKeys, isExclusiveRoot, ExclusiveRuntime, exclusiveDefaultOf, exclusiveLabelOf, exclusiveBehaviourOf, exclusiveKindOf, compositeKindOfRole, AccordionRuntime, isToggleKind, closestAccordionItem, isAnyCompositeRoot, SceneRole, isExclusiveList, buildCardRecipe, buildBadge, buildChip, buildAccordionRecipe, buildDisclosureRecipe, buildTabsRecipe, buildSegmentedRecipe, buildLightboxRecipe, NO_ELEMENT_STYLE, CompositeKind, SliderRole, accordionItemLabel, segmentedOptionLabel, isExclusivePanels, isLockedPart, accordionRootOf, accordionItemOf, addAccordionItem, addTabPair, segmentedAddRefusal, addSegmentedOption, isCompositeItem, accordionHeadingLevel, isCompositePanel, isCompositeTrigger, splitSliderChildren, hasSliderParts } from '@vectoriox/iox-ui/composite-core';
|
|
23
23
|
import { formContentInHost, isInteractiveHost, findFormContentInHosts } from '@vectoriox/iox-ui/forms-core';
|
|
@@ -32,7 +32,7 @@ import Lenis from 'lenis';
|
|
|
32
32
|
import Moveable from 'moveable';
|
|
33
33
|
import Selecto from 'selecto';
|
|
34
34
|
import * as i18 from 'primeng/api';
|
|
35
|
-
import { planVideo, VideoSource, VIDEO_PROVIDER_LABEL, VideoTrait, VideoMode } from '@vectoriox/iox-ui/media-core';
|
|
35
|
+
import { planVideo, VideoKind, VideoSource, VIDEO_PROVIDER_LABEL, VideoTrait, VideoMode } from '@vectoriox/iox-ui/media-core';
|
|
36
36
|
import { ConsentCategory } from '@vectoriox/iox-ui/consent-core';
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -105,6 +105,7 @@ const BUILDER_CHROME_EN = Object.freeze({
|
|
|
105
105
|
'builder.chrome.kindSlider': 'Slider',
|
|
106
106
|
'builder.chrome.kindVideo': 'Video',
|
|
107
107
|
'builder.chrome.videoPosterOnly': 'poster only',
|
|
108
|
+
'builder.chrome.videoFrames': 'played by the scroll',
|
|
108
109
|
'builder.chrome.videoFile': 'Uploaded file',
|
|
109
110
|
'builder.chrome.refuseLockedSliderPartMove': 'This control belongs to its slider — it can’t be moved out.',
|
|
110
111
|
'builder.chrome.refuseLockedSliderPause': 'The pause button stays while Autoplay is on — moving content must be pausable. Turn Autoplay off in the slider’s Bindings to remove it.',
|
|
@@ -1348,8 +1349,9 @@ const DIALOG_ACTION_TYPES = new Set(['openDialog', 'closeDialog', 'toggleDialog'
|
|
|
1348
1349
|
const EASING_OPTIONS = ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'];
|
|
1349
1350
|
/** Interaction pseudo-classes — compiled to .iox-node-{id}:state */
|
|
1350
1351
|
const INTERACTION_STATES = ['hover', 'active', 'focus'];
|
|
1351
|
-
/** Structural pseudo-classes —
|
|
1352
|
-
|
|
1352
|
+
/** Structural pseudo-classes — matched on the outer element by the shared `planStateRule` (@vectoriox/iox-ui), the
|
|
1353
|
+
* engine's planner too (iox-client-engine#14). */
|
|
1354
|
+
const STRUCTURAL_STATES = [...STRUCTURAL_STATES$1];
|
|
1353
1355
|
/**
|
|
1354
1356
|
* Relational pseudo-classes — the styled element is a descendant, the pseudo-class
|
|
1355
1357
|
* lives on an ANCESTOR. Compiled to `.iox-node-{parentId}:{base} .iox-node-{id} { … }`,
|
|
@@ -2144,26 +2146,6 @@ class StyleRegistryService {
|
|
|
2144
2146
|
this.styleEl = null;
|
|
2145
2147
|
this._flushPending = false;
|
|
2146
2148
|
}
|
|
2147
|
-
/**
|
|
2148
|
-
* Properties that must live on the OUTER wrapper (.iox-outer-{id}) because they
|
|
2149
|
-
* affect how the element participates in its PARENT layout (flex/block flow).
|
|
2150
|
-
* Everything else goes to the INNER element (.iox-node-{id}).
|
|
2151
|
-
*
|
|
2152
|
-
* Exception — out-of-flow positioning (position:fixed/absolute):
|
|
2153
|
-
* When position is fixed or absolute, width is redirected to the inner element
|
|
2154
|
-
* (the positioned one) and a default width:100% is added if none is set, so the
|
|
2155
|
-
* element stays visible. top/right/bottom/left/zIndex are always inner because
|
|
2156
|
-
* they are co-ordinates of the positioned element, not the flow wrapper.
|
|
2157
|
-
* position itself goes to inner with `!important` to beat component-scoped CSS.
|
|
2158
|
-
*/
|
|
2159
|
-
static { this.OUTER_PROPS = new Set([
|
|
2160
|
-
'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',
|
|
2161
|
-
'alignSelf', 'flexGrow', 'flexShrink', 'flexBasis', 'order',
|
|
2162
|
-
// Grid-child placement — like the flex-child props above, these position the node
|
|
2163
|
-
// within the PARENT's grid, so they must land on the outer host, not the inner div.
|
|
2164
|
-
'gridColumn', 'gridRow', 'justifySelf',
|
|
2165
|
-
'width',
|
|
2166
|
-
]); }
|
|
2167
2149
|
/**
|
|
2168
2150
|
* Properties that need !important on the inner element to beat Angular's scoped-CSS
|
|
2169
2151
|
* specificity boost. CANVAS-ONLY (H2 audit, 2026-10-11): the shared compiler never forces
|
|
@@ -2220,8 +2202,7 @@ class StyleRegistryService {
|
|
|
2220
2202
|
// breakpoint is scoped identically without re-resolving it (see upsertResponsive).
|
|
2221
2203
|
if (relativeToId || triggerId)
|
|
2222
2204
|
this.stateScopes.set(key, { relativeToId, triggerId });
|
|
2223
|
-
const
|
|
2224
|
-
const css = selector ? this.compile(selector, styles) : '';
|
|
2205
|
+
const css = this.stateRuleCss(nodeId, state, styles, relativeToId, triggerId, DeclarationContext.Base);
|
|
2225
2206
|
if (css)
|
|
2226
2207
|
this.rules.set(key, css);
|
|
2227
2208
|
else
|
|
@@ -2255,9 +2236,10 @@ class StyleRegistryService {
|
|
|
2255
2236
|
if (!nodeId || !partClassName)
|
|
2256
2237
|
return;
|
|
2257
2238
|
const key = `${nodeId}:part:${partClassName}${state ? ':' + state : ''}`;
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
const
|
|
2239
|
+
// The shared planner the engine uses (iox-client-engine#14): a part's hover / focus is the PART's own pseudo-class
|
|
2240
|
+
// — before, any non-validation state compiled to the bare part selector and applied at all times.
|
|
2241
|
+
const selector = planPartRule(nodeId, partClassName, state);
|
|
2242
|
+
const css = selector && Object.keys(styles).length ? this.compileSelector(selector, styles) : '';
|
|
2261
2243
|
if (css)
|
|
2262
2244
|
this.rules.set(key, css);
|
|
2263
2245
|
else
|
|
@@ -2303,10 +2285,9 @@ class StyleRegistryService {
|
|
|
2303
2285
|
this.setResponsiveRule(nodeId, bp, `${nodeId}::marker`, marker);
|
|
2304
2286
|
for (const [state, map] of Object.entries(layer.stateStyles)) {
|
|
2305
2287
|
const scope = this.stateScopes.get(`${nodeId}:${state}`);
|
|
2306
|
-
const selector = this.stateSelector(nodeId, state, scope?.relativeToId, scope?.triggerId);
|
|
2307
2288
|
// A relational/targeted state whose scope isn't known yet is skipped; it is re-emitted
|
|
2308
2289
|
// when the base state rule arrives with its scope (see upsert).
|
|
2309
|
-
const css =
|
|
2290
|
+
const css = this.stateRuleCss(nodeId, state, this.ownProps(nodeId, map), scope?.relativeToId, scope?.triggerId, DeclarationContext.Override);
|
|
2310
2291
|
if (css)
|
|
2311
2292
|
this.setResponsiveRule(nodeId, bp, `${nodeId}:${state}`, css);
|
|
2312
2293
|
}
|
|
@@ -2332,37 +2313,20 @@ class StyleRegistryService {
|
|
|
2332
2313
|
return pos === 'fixed' || pos === 'absolute';
|
|
2333
2314
|
}
|
|
2334
2315
|
/**
|
|
2335
|
-
*
|
|
2336
|
-
* state has no scope yet (emitting it unscoped would be wrong — a page-global `:has()`).
|
|
2316
|
+
* A state rule's CSS through the SHARED planner the engine emits with (`planStateRule`, iox-client-engine#14), or ''
|
|
2317
|
+
* when a relational / targeted state has no scope yet (emitting it unscoped would be wrong — a page-global `:has()`).
|
|
2318
|
+
* `relativeToId` is the parent for a relational state (parent-hover) and the nearest common ancestor of the node and
|
|
2319
|
+
* its trigger for a targeted one (trigger-hover, trigger-on). A structural state is matched on the outer element and
|
|
2320
|
+
* reaches the node's own; its outer props stay outer.
|
|
2337
2321
|
*/
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
}
|
|
2347
|
-
// Relational states (parent-hover): the pseudo-class lives on an ANCESTOR
|
|
2348
|
-
// and cascades to this element. Requires the ancestor's css id.
|
|
2349
|
-
if (RELATIONAL_STATES.includes(state)) {
|
|
2350
|
-
const base = RELATIONAL_STATE_BASE[state];
|
|
2351
|
-
return relativeToId && base ? `iox-node-${relativeToId}:${base} .iox-node-${nodeId}` : null;
|
|
2352
|
-
}
|
|
2353
|
-
// Validation states (wrong/accepted, board 7) are not real CSS pseudo-classes — `:wrong`
|
|
2354
|
-
// doesn't exist. Compound a CLASS instead, matching the host class IoxFieldComponent
|
|
2355
|
-
// already sets from forceInvalid/showValid. Reuses buildPartSelector with no part, since
|
|
2356
|
-
// "whole node, when wrong" is exactly that function's no-part case.
|
|
2357
|
-
const validationClass = VALIDATION_STATE_CLASS[state];
|
|
2358
|
-
if (validationClass)
|
|
2359
|
-
return buildPartSelector(nodeId, undefined, validationClass);
|
|
2360
|
-
// Structural pseudo-classes (first-child, last-child, nth-child) target the
|
|
2361
|
-
// outer wrapper element so they participate correctly in grid/flex layout.
|
|
2362
|
-
const prefix = STRUCTURAL_STATES.includes(state) ? 'iox-outer' : 'iox-node';
|
|
2363
|
-
// `focus` compiles to :focus-visible (DS2) and a component state to its attribute (`current` →
|
|
2364
|
-
// [aria-current="page"], CC1) — shared with the engine via stateSelectorSuffix.
|
|
2365
|
-
return `${prefix}-${nodeId}${stateSelectorSuffix(state)}`;
|
|
2322
|
+
stateRuleCss(nodeId, state, styles, relativeToId, triggerId, context) {
|
|
2323
|
+
const targeted = TARGETED_STATES.includes(state);
|
|
2324
|
+
const plan = planStateRule(nodeId, state, targeted ? { scopeId: relativeToId, triggerId } : { parentId: relativeToId });
|
|
2325
|
+
if (!plan)
|
|
2326
|
+
return '';
|
|
2327
|
+
const { inner, outer } = plan.outer ? splitOuterProps(styles) : { inner: styles, outer: {} };
|
|
2328
|
+
return [this.compileSelector(plan.inner, inner, context), plan.outer ? this.compileSelector(plan.outer, outer, context) : '']
|
|
2329
|
+
.filter(Boolean).join('\n');
|
|
2366
2330
|
}
|
|
2367
2331
|
/**
|
|
2368
2332
|
* The inner + outer rule (joined) and the `::marker` rule for one composed style map.
|
|
@@ -2379,7 +2343,7 @@ class StyleRegistryService {
|
|
|
2379
2343
|
for (const [k, v] of Object.entries(styles)) {
|
|
2380
2344
|
if (k === '__markerStyles')
|
|
2381
2345
|
continue;
|
|
2382
|
-
const wantsOuter =
|
|
2346
|
+
const wantsOuter = OUTER_STYLE_PROPS.has(k);
|
|
2383
2347
|
// width goes to inner for fixed/absolute (the positioned element owns its own width)
|
|
2384
2348
|
if (wantsOuter && !(isOutOfFlow && k === 'width')) {
|
|
2385
2349
|
outer[k] = v;
|
|
@@ -2525,14 +2489,16 @@ class StyleRegistryService {
|
|
|
2525
2489
|
}
|
|
2526
2490
|
}
|
|
2527
2491
|
compile(className, styles, context = DeclarationContext.Base) {
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2492
|
+
return this.compileSelector(`.${className}`, styles, context);
|
|
2493
|
+
}
|
|
2494
|
+
/** One rule for a FULL selector. Declaration compilation (kebab-case, viewport-unit rewrite, !important) lives in
|
|
2495
|
+
* the shared style-compiler so the SSR engine produces byte-identical output. */
|
|
2496
|
+
compileSelector(selector, styles, context = DeclarationContext.Base) {
|
|
2531
2497
|
const decls = compileDeclarations(styles, StyleRegistryService.IMPORTANT_PROPS, context);
|
|
2532
2498
|
if (!decls.length)
|
|
2533
2499
|
return '';
|
|
2534
2500
|
const body = decls.map(d => ` ${d};`).join('\n');
|
|
2535
|
-
return
|
|
2501
|
+
return `${selector} {\n${body}\n}`;
|
|
2536
2502
|
}
|
|
2537
2503
|
flush() {
|
|
2538
2504
|
if (!this.styleEl || this._flushPending)
|
|
@@ -4084,6 +4050,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
|
|
|
4084
4050
|
// Re-exported from the shared iox-ui package so iox-builder consumers
|
|
4085
4051
|
// don't need to import from two different packages.
|
|
4086
4052
|
|
|
4053
|
+
/** What the canvas never writes inline (a transform inside the scaled page breaks Lenis). */
|
|
4054
|
+
const CANVAS_SKIPPED_PROPS = new Set(['transform']);
|
|
4087
4055
|
/**
|
|
4088
4056
|
* Wires ComponentNode interactions to live DOM elements via the
|
|
4089
4057
|
* OverlayService node-element registry.
|
|
@@ -4705,22 +4673,27 @@ class InteractionEngineService {
|
|
|
4705
4673
|
element.removeAttribute(INTERACTION_HIDDEN_ATTRIBUTE);
|
|
4706
4674
|
else if (this.EXIT_TYPES.has(type))
|
|
4707
4675
|
element.setAttribute(INTERACTION_HIDDEN_ATTRIBUTE, '');
|
|
4708
|
-
// Reduced motion (CC1 R1): no animation runs — the element
|
|
4676
|
+
// Reduced motion (CC1 R1): no animation runs — the element is left as the run would leave it (the shared settle
|
|
4677
|
+
// rule: an entrance releases to the stylesheet, an exit holds its hidden frame).
|
|
4709
4678
|
if (!motionAllowed()) {
|
|
4710
|
-
|
|
4679
|
+
settleInteraction(element, keyframes, settleModeFor(type), this.settleOptions());
|
|
4711
4680
|
this.settleAfter(element, type);
|
|
4712
4681
|
return;
|
|
4713
4682
|
}
|
|
4714
|
-
//
|
|
4683
|
+
// The ONE call the live site makes too: fill both (holds the first frame through a delay), started from the live
|
|
4684
|
+
// value, settled by the shared rule — an element that has entered keeps its hover and press (iox-ui#41). A look
|
|
4715
4685
|
// entrance on a Repeater's template staggers its rows: each copy adds its row's share (shared `entranceDelay`).
|
|
4716
|
-
const anim =
|
|
4686
|
+
const anim = playInteraction(element, { type, params: action.params }, keyframes, {
|
|
4717
4687
|
duration: action.duration,
|
|
4718
4688
|
delay: entranceDelay(action, repeatedRowIndex(element)),
|
|
4719
4689
|
easing: action.easing,
|
|
4720
|
-
|
|
4721
|
-
});
|
|
4690
|
+
}, this.settleOptions());
|
|
4722
4691
|
anim.finished.then(() => this.settleAfter(element, type)).catch(() => { });
|
|
4723
4692
|
}
|
|
4693
|
+
/** On the canvas a run never writes a transform inline (one inside the scaled page breaks Lenis). */
|
|
4694
|
+
settleOptions() {
|
|
4695
|
+
return this.isBuilderMode() ? { skip: CANVAS_SKIPPED_PROPS } : {};
|
|
4696
|
+
}
|
|
4724
4697
|
/** What an element is left as once an action is done: a revealed one interactive, a hidden one inert. */
|
|
4725
4698
|
settleAfter(element, type) {
|
|
4726
4699
|
if (this.ENTRANCE_TYPES.has(type)) {
|
|
@@ -4737,15 +4710,6 @@ class InteractionEngineService {
|
|
|
4737
4710
|
element.style.setProperty('pointer-events', 'none');
|
|
4738
4711
|
}
|
|
4739
4712
|
}
|
|
4740
|
-
/** Write a frame inline. On the canvas never a transform: one inside the scaled page breaks Lenis. */
|
|
4741
|
-
applyFrame(element, frame) {
|
|
4742
|
-
const canvas = this.isBuilderMode();
|
|
4743
|
-
for (const [prop, value] of keyframeStyleEntries(frame)) {
|
|
4744
|
-
if (canvas && prop === 'transform')
|
|
4745
|
-
continue;
|
|
4746
|
-
element.style.setProperty(prop, value);
|
|
4747
|
-
}
|
|
4748
|
-
}
|
|
4749
4713
|
/**
|
|
4750
4714
|
* Freeze an element at the animation's starting frame immediately, before any
|
|
4751
4715
|
* trigger fires. Called for ALL entrance-type actions regardless of trigger so
|
|
@@ -4786,20 +4750,22 @@ class InteractionEngineService {
|
|
|
4786
4750
|
element.style.removeProperty('pointer-events');
|
|
4787
4751
|
element.removeAttribute(INTERACTION_HIDDEN_ATTRIBUTE);
|
|
4788
4752
|
}
|
|
4753
|
+
/** A hover-out: the action played back from where the element IS (never from its end frame), settled by the shared
|
|
4754
|
+
* rule — played back to hidden, it holds hidden; to shown, it releases. */
|
|
4789
4755
|
reverseAction(element, action) {
|
|
4790
|
-
const
|
|
4756
|
+
const type = effectiveActionType(action.type, element.hasAttribute(INTERACTION_HIDDEN_ATTRIBUTE));
|
|
4757
|
+
const keyframes = this.keyframesFor(type, action);
|
|
4791
4758
|
if (!keyframes.length)
|
|
4792
4759
|
return;
|
|
4760
|
+
const frames = [...keyframes].reverse();
|
|
4793
4761
|
if (!motionAllowed()) {
|
|
4794
|
-
|
|
4762
|
+
settleInteraction(element, frames, settleModeFor(type, true), this.settleOptions());
|
|
4795
4763
|
return;
|
|
4796
4764
|
}
|
|
4797
|
-
|
|
4798
|
-
animateAction(element, action, [...keyframes].reverse(), {
|
|
4765
|
+
playInteraction(element, { type, params: action.params }, frames, {
|
|
4799
4766
|
duration: action.duration,
|
|
4800
4767
|
easing: action.easing,
|
|
4801
|
-
|
|
4802
|
-
}, { reverse: true });
|
|
4768
|
+
}, { ...this.settleOptions(), reverse: true });
|
|
4803
4769
|
}
|
|
4804
4770
|
/** The action's keyframes from the ONE shared table both runtimes animate from (composite T2). */
|
|
4805
4771
|
keyframesFor(type, action) {
|
|
@@ -5360,6 +5326,18 @@ class SceneCanvasService {
|
|
|
5360
5326
|
if (el)
|
|
5361
5327
|
this.driver?.reread(el);
|
|
5362
5328
|
}
|
|
5329
|
+
/**
|
|
5330
|
+
* A value a layer's own component draws changed (a Video's pictures): its instance takes it now. Its Scene reads the new
|
|
5331
|
+
* attribute when it lands, with no re-render of the page.
|
|
5332
|
+
*/
|
|
5333
|
+
setLayerInput(node, name, value) {
|
|
5334
|
+
const ref = this.overlay?.getNodeRef(node) ?? (node.id ? this.overlay?.findRefByNodeId(node.id)?.ref : undefined);
|
|
5335
|
+
const component = ref?.componentRef;
|
|
5336
|
+
if (!component?.instance)
|
|
5337
|
+
return;
|
|
5338
|
+
component.instance[name] = value;
|
|
5339
|
+
component.changeDetectorRef.detectChanges();
|
|
5340
|
+
}
|
|
5363
5341
|
ngOnDestroy() {
|
|
5364
5342
|
this.driver?.destroy();
|
|
5365
5343
|
this.driver = null;
|
|
@@ -7854,6 +7832,7 @@ const VIDEO_TYPE = 'Video';
|
|
|
7854
7832
|
const VIDEO_KIND_KEY = 'builder.chrome.kindVideo';
|
|
7855
7833
|
const VIDEO_POSTER_ONLY_KEY = 'builder.chrome.videoPosterOnly';
|
|
7856
7834
|
const VIDEO_FILE_KEY = 'builder.chrome.videoFile';
|
|
7835
|
+
const VIDEO_FRAMES_KEY = 'builder.chrome.videoFrames';
|
|
7857
7836
|
/** The parts that offer "Add item" on the selection toolbar (board 3: the "Add slide" pattern). */
|
|
7858
7837
|
const ADD_ITEM_ROLES = new Set([
|
|
7859
7838
|
AccordionRole.Accordion, AccordionRole.Item, AccordionRole.Trigger, AccordionRole.Panel,
|
|
@@ -8113,6 +8092,9 @@ class OverlayComponent {
|
|
|
8113
8092
|
}
|
|
8114
8093
|
videoBadge(node) {
|
|
8115
8094
|
const plan = planVideo(node, null);
|
|
8095
|
+
// Unlike every other Video, the canvas really plays this one.
|
|
8096
|
+
if (plan.kind === VideoKind.Frames)
|
|
8097
|
+
return `${this.builderLabels(VIDEO_KIND_KEY, BUILDER_CHROME_EN[VIDEO_KIND_KEY])} · ${this.builderLabels(VIDEO_FRAMES_KEY, BUILDER_CHROME_EN[VIDEO_FRAMES_KEY])}`;
|
|
8116
8098
|
const where = plan.source === VideoSource.File
|
|
8117
8099
|
? this.builderLabels(VIDEO_FILE_KEY, BUILDER_CHROME_EN[VIDEO_FILE_KEY])
|
|
8118
8100
|
: VIDEO_PROVIDER_LABEL[plan.source];
|
|
@@ -11130,6 +11112,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
|
|
|
11130
11112
|
type: Output
|
|
11131
11113
|
}] } });
|
|
11132
11114
|
|
|
11115
|
+
/** The formClass a Form's canvas twin wears (form.config). */
|
|
11116
|
+
const FORM_CLASS = 'iox-form';
|
|
11133
11117
|
const ACCORDION_TRACK_WRAPPER = 'track';
|
|
11134
11118
|
/**
|
|
11135
11119
|
* Directive-host Container (Phase 2 of the Moveable migration = task 9c). The real tag (div/section/
|
|
@@ -11140,6 +11124,14 @@ const ACCORDION_TRACK_WRAPPER = 'track';
|
|
|
11140
11124
|
* See moveable-migration.md.
|
|
11141
11125
|
*/
|
|
11142
11126
|
class BuilderContainerComponent {
|
|
11127
|
+
/** Which state the canvas is showing. Only meaningful on a form host: its submit buttons follow it (busy, disabled
|
|
11128
|
+
* while Sending — the ONE `syncSubmitButtons` both live paths call, iox-ui#42); "While sending" is the shared CSS's. */
|
|
11129
|
+
set formState(state) {
|
|
11130
|
+
this._formState = state;
|
|
11131
|
+
if (this.formClass === FORM_CLASS)
|
|
11132
|
+
syncSubmitButtons(this.elRef?.nativeElement, state);
|
|
11133
|
+
}
|
|
11134
|
+
get formState() { return this._formState; }
|
|
11143
11135
|
/** The wrapper a child renders in: an Accordion item's header → its heading level; an item's panel (either
|
|
11144
11136
|
* kind) → the track. A disclosure's toggle has no heading — it is a button in the flow. */
|
|
11145
11137
|
wrapperOf(child) {
|
|
@@ -11169,8 +11161,7 @@ class BuilderContainerComponent {
|
|
|
11169
11161
|
* stylesheet treat them exactly as it treats the engine's own twins.
|
|
11170
11162
|
*/
|
|
11171
11163
|
this.formClass = '';
|
|
11172
|
-
|
|
11173
|
-
this.formState = 'idle';
|
|
11164
|
+
this._formState = 'idle';
|
|
11174
11165
|
this.childClick = new EventEmitter();
|
|
11175
11166
|
this.childMouseEnter = new EventEmitter();
|
|
11176
11167
|
this.childMouseLeave = new EventEmitter();
|
|
@@ -14074,6 +14065,8 @@ class VideoConfig extends ComponentConfig {
|
|
|
14074
14065
|
], VideoSource.YouTube),
|
|
14075
14066
|
new TraitConfig(VideoTrait.Src, 'Video address', TraitInputType.Media, { mode: 'compact' }, ''),
|
|
14076
14067
|
new TraitConfig(VideoTrait.Poster, 'Poster', TraitInputType.Media, { mode: 'compact' }, ''),
|
|
14068
|
+
// Pictures the scroll plays (SC4): the Scene group writes it, so the Bindings panel lists no control for it.
|
|
14069
|
+
new TraitConfig(VideoTrait.Frames, 'Frames', TraitInputType.Text, undefined, null),
|
|
14077
14070
|
// ── Behaviour ─────────────────────────────────────────────────
|
|
14078
14071
|
new TraitConfig('__behaviourLabel', 'Behaviour', TraitInputType.SectionLabel),
|
|
14079
14072
|
new TraitConfig(VideoTrait.Mode, 'Mode', TraitInputType.Select, [
|