@vectoriox/iox-ui 4.4.3 → 4.5.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.
|
@@ -1940,14 +1940,19 @@ function styleKeyToKebab(key) {
|
|
|
1940
1940
|
* - border-* — the initial `medium` width + interaction with border-style makes it non-trivial.
|
|
1941
1941
|
*/
|
|
1942
1942
|
const NOOP_INITIAL_VALUES = {
|
|
1943
|
-
'width': 'auto', 'height': 'auto',
|
|
1944
|
-
'min-width': 'auto', 'min-height': 'auto',
|
|
1945
|
-
'max-width': 'none', 'max-height': 'none',
|
|
1946
|
-
'position': 'static',
|
|
1947
|
-
'top': 'auto', 'right': 'auto', 'bottom': 'auto', 'left': 'auto',
|
|
1948
|
-
'opacity': '1', 'z-index': 'auto',
|
|
1949
|
-
'flex-grow': '0', 'flex-shrink': '1', 'flex-basis': 'auto',
|
|
1950
|
-
'
|
|
1943
|
+
'width': ['auto'], 'height': ['auto'],
|
|
1944
|
+
'min-width': ['auto'], 'min-height': ['auto'],
|
|
1945
|
+
'max-width': ['none', 'auto'], 'max-height': ['none', 'auto'], // `auto` is invalid for max-* → inert
|
|
1946
|
+
'position': ['static'],
|
|
1947
|
+
'top': ['auto'], 'right': ['auto'], 'bottom': ['auto'], 'left': ['auto'],
|
|
1948
|
+
'opacity': ['1'], 'z-index': ['auto'],
|
|
1949
|
+
'flex-grow': ['0'], 'flex-shrink': ['1'], 'flex-basis': ['auto'],
|
|
1950
|
+
'flex-direction': ['row'], 'flex-wrap': ['nowrap'],
|
|
1951
|
+
'gap': ['0', '0px', 'normal'],
|
|
1952
|
+
'border-radius': ['0', '0px'],
|
|
1953
|
+
'aspect-ratio': ['auto'],
|
|
1954
|
+
'mix-blend-mode': ['normal'],
|
|
1955
|
+
'transform': ['none'], 'box-shadow': ['none'],
|
|
1951
1956
|
};
|
|
1952
1957
|
/**
|
|
1953
1958
|
* Compile a flat, camelCase style map into an array of `"prop: value"` CSS
|
|
@@ -1968,7 +1973,7 @@ function compileDeclarations(props, importantProps) {
|
|
|
1968
1973
|
const prop = styleKeyToKebab(k);
|
|
1969
1974
|
const val = rewriteViewportUnits(String(v));
|
|
1970
1975
|
const isImportant = importantProps?.has(k) ?? false;
|
|
1971
|
-
if (!isImportant && NOOP_INITIAL_VALUES[prop]
|
|
1976
|
+
if (!isImportant && NOOP_INITIAL_VALUES[prop]?.includes(val.trim().toLowerCase()))
|
|
1972
1977
|
continue;
|
|
1973
1978
|
out.push(`${prop}: ${val}${isImportant ? ' !important' : ''}`);
|
|
1974
1979
|
}
|
|
@@ -2062,6 +2067,123 @@ function renderDefaultDeclarations(type, styleProps, hasHoverState) {
|
|
|
2062
2067
|
return out;
|
|
2063
2068
|
}
|
|
2064
2069
|
|
|
2070
|
+
// Virtual trait → composed CSS property helpers.
|
|
2071
|
+
//
|
|
2072
|
+
// Several style traits are "virtual" — they don't map 1:1 to a CSS property but
|
|
2073
|
+
// are components of a multi-function CSS value. composeVirtualTraits() strips
|
|
2074
|
+
// these virtual keys from the style map and replaces them with the correctly
|
|
2075
|
+
// composed CSS properties (filter, backdrop-filter, transform, transition).
|
|
2076
|
+
//
|
|
2077
|
+
// SHARED (iox-ui): consumed by BOTH the builder (render.directive + style panel)
|
|
2078
|
+
// and the SSR engine (LayoutRendererService). It MUST live here, not in iox-builder,
|
|
2079
|
+
// because the engine does not depend on iox-builder — without it the engine emitted
|
|
2080
|
+
// the raw virtual keys (`translate-x`, `filter-blur`, `scale-x`…) as invalid CSS.
|
|
2081
|
+
// Run this BEFORE compileDeclarations so the CSS output is identical on both sides.
|
|
2082
|
+
// ─── Filter ──────────────────────────────────────────────────────────────────
|
|
2083
|
+
const FILTER_FUNS = [
|
|
2084
|
+
['filterBlur', 'blur', '0px'],
|
|
2085
|
+
['filterBrightness', 'brightness', '1'],
|
|
2086
|
+
['filterContrast', 'contrast', '1'],
|
|
2087
|
+
['filterGrayscale', 'grayscale', '0'],
|
|
2088
|
+
['filterSaturate', 'saturate', '1'],
|
|
2089
|
+
['filterHueRotate', 'hue-rotate', '0deg'],
|
|
2090
|
+
['filterSepia', 'sepia', '0'],
|
|
2091
|
+
['filterInvert', 'invert', '0'],
|
|
2092
|
+
];
|
|
2093
|
+
// ─── Backdrop-filter ─────────────────────────────────────────────────────────
|
|
2094
|
+
const BACKDROP_FUNS = [
|
|
2095
|
+
['backdropBlur', 'blur', '0px'],
|
|
2096
|
+
['backdropBrightness', 'brightness', '1'],
|
|
2097
|
+
['backdropContrast', 'contrast', '1'],
|
|
2098
|
+
['backdropSaturate', 'saturate', '1'],
|
|
2099
|
+
];
|
|
2100
|
+
// ─── Transform ───────────────────────────────────────────────────────────────
|
|
2101
|
+
const TRANSFORM_FUNS = [
|
|
2102
|
+
['translateX', 'translateX', '0px'],
|
|
2103
|
+
['translateY', 'translateY', '0px'],
|
|
2104
|
+
['scaleX', 'scaleX', '1'],
|
|
2105
|
+
['scaleY', 'scaleY', '1'],
|
|
2106
|
+
['rotate', 'rotate', '0deg'],
|
|
2107
|
+
['skewX', 'skewX', '0deg'],
|
|
2108
|
+
['skewY', 'skewY', '0deg'],
|
|
2109
|
+
];
|
|
2110
|
+
// ─── ::marker pseudo-element ─────────────────────────────────────────────────
|
|
2111
|
+
const MARKER_FUNS = [
|
|
2112
|
+
['markerColor', 'color'],
|
|
2113
|
+
['markerFontSize', 'fontSize'],
|
|
2114
|
+
];
|
|
2115
|
+
// ─── All virtual trait names ──────────────────────────────────────────────────
|
|
2116
|
+
const VIRTUAL_TRAIT_KEYS = new Set([
|
|
2117
|
+
...FILTER_FUNS.map(([t]) => t),
|
|
2118
|
+
...BACKDROP_FUNS.map(([t]) => t),
|
|
2119
|
+
...TRANSFORM_FUNS.map(([t]) => t),
|
|
2120
|
+
'transitionDuration', 'transitionTimingFunction', 'transitionDelay',
|
|
2121
|
+
...MARKER_FUNS.map(([t]) => t),
|
|
2122
|
+
]);
|
|
2123
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
2124
|
+
function buildFns(funs, src) {
|
|
2125
|
+
return funs
|
|
2126
|
+
.filter(([t, , d]) => src[t] != null && src[t] !== '' && src[t] !== d)
|
|
2127
|
+
.map(([t, fn]) => `${fn}(${src[t]})`)
|
|
2128
|
+
.join(' ');
|
|
2129
|
+
}
|
|
2130
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
2131
|
+
/**
|
|
2132
|
+
* Strip virtual trait keys from `raw` and emit their composed CSS equivalents.
|
|
2133
|
+
*
|
|
2134
|
+
* When composing a partial state-override map (hover, active…), pass the full
|
|
2135
|
+
* base style map as `base` so non-overridden components (e.g. filterBrightness
|
|
2136
|
+
* when only filterBlur is overridden) are preserved in the composed output.
|
|
2137
|
+
* When operating on a complete style map, omit `base` — it defaults to `raw`.
|
|
2138
|
+
*/
|
|
2139
|
+
function composeVirtualTraits(raw, base = raw) {
|
|
2140
|
+
// Copy all non-virtual properties as-is
|
|
2141
|
+
const result = {};
|
|
2142
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
2143
|
+
if (!VIRTUAL_TRAIT_KEYS.has(k))
|
|
2144
|
+
result[k] = v;
|
|
2145
|
+
}
|
|
2146
|
+
// Merge base values for any virtual key absent from the partial override map
|
|
2147
|
+
const merged = (funs) => {
|
|
2148
|
+
const m = {};
|
|
2149
|
+
for (const [t] of funs)
|
|
2150
|
+
m[t] = raw[t] ?? base[t];
|
|
2151
|
+
return m;
|
|
2152
|
+
};
|
|
2153
|
+
// filter
|
|
2154
|
+
const filterStr = buildFns(FILTER_FUNS, merged(FILTER_FUNS));
|
|
2155
|
+
if (filterStr)
|
|
2156
|
+
result['filter'] = filterStr;
|
|
2157
|
+
// backdrop-filter
|
|
2158
|
+
const backdropStr = buildFns(BACKDROP_FUNS, merged(BACKDROP_FUNS));
|
|
2159
|
+
if (backdropStr)
|
|
2160
|
+
result['backdropFilter'] = backdropStr;
|
|
2161
|
+
// transform
|
|
2162
|
+
const transformStr = buildFns(TRANSFORM_FUNS, merged(TRANSFORM_FUNS));
|
|
2163
|
+
if (transformStr)
|
|
2164
|
+
result['transform'] = transformStr;
|
|
2165
|
+
// transition — only emit when duration is non-zero
|
|
2166
|
+
const dur = raw['transitionDuration'] ?? base['transitionDuration'];
|
|
2167
|
+
const ease = raw['transitionTimingFunction'] ?? base['transitionTimingFunction'];
|
|
2168
|
+
const del = raw['transitionDelay'] ?? base['transitionDelay'];
|
|
2169
|
+
if (dur && ease && dur !== '0ms' && dur !== '0s') {
|
|
2170
|
+
const delPart = del && del !== '0ms' && del !== '0s' ? ` ${del}` : '';
|
|
2171
|
+
result['transition'] = `all ${dur} ${ease}${delPart}`;
|
|
2172
|
+
}
|
|
2173
|
+
// ::marker pseudo-element — collected into __markerStyles so StyleRegistryService
|
|
2174
|
+
// can emit a separate `.iox-node-{id}::marker { … }` rule.
|
|
2175
|
+
const markerStyles = {};
|
|
2176
|
+
for (const [trait, cssProp] of MARKER_FUNS) {
|
|
2177
|
+
const val = raw[trait] ?? base[trait];
|
|
2178
|
+
if (val != null && val !== '')
|
|
2179
|
+
markerStyles[cssProp] = val;
|
|
2180
|
+
}
|
|
2181
|
+
if (Object.keys(markerStyles).length) {
|
|
2182
|
+
result['__markerStyles'] = markerStyles;
|
|
2183
|
+
}
|
|
2184
|
+
return result;
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2065
2187
|
/**
|
|
2066
2188
|
* Shared data-source resolving pattern — the SINGLE source of truth for how an IoxDataSource
|
|
2067
2189
|
* becomes a backend fetch, consumed by BOTH the page builder (iox-cms-client bindings panel) and
|
|
@@ -2204,6 +2326,239 @@ function dataSourcePlanToRequest(plan, endpoints) {
|
|
|
2204
2326
|
}
|
|
2205
2327
|
}
|
|
2206
2328
|
|
|
2329
|
+
/**
|
|
2330
|
+
* Cinematic page-transition presets — the SINGLE SOURCE OF TRUTH shared by the page builder
|
|
2331
|
+
* (preview) and the SSR client engine (production). Pure, transport-agnostic: this module only
|
|
2332
|
+
* describes WAAPI keyframe pairs + timing/ordering. It never touches the DOM.
|
|
2333
|
+
*
|
|
2334
|
+
* A page transition plays TWO synchronized WAAPI animations at once — an `out` animation on a
|
|
2335
|
+
* snapshot of the outgoing page and an `in` animation on the incoming page — inside a shared
|
|
2336
|
+
* `perspective` container, gated on BOTH finishing (the "cinematic" feel, à la Codrops
|
|
2337
|
+
* PageTransitions). The consumer supplies the DOM (snapshot layer + live page) and calls
|
|
2338
|
+
* `element.animate(frames, options)`; it does NOT redefine the frames.
|
|
2339
|
+
*
|
|
2340
|
+
* @see architecture/builder/page-transitions.md
|
|
2341
|
+
*/
|
|
2342
|
+
/** Perspective (px) applied to the transition container unless a preset overrides it. */
|
|
2343
|
+
const DEFAULT_PAGE_TRANSITION_PERSPECTIVE = 1200;
|
|
2344
|
+
/** Default transition duration (ms) when the page does not specify one. */
|
|
2345
|
+
const DEFAULT_PAGE_TRANSITION_DURATION = 600;
|
|
2346
|
+
// ── Keyframe helpers ────────────────────────────────────────────────────────
|
|
2347
|
+
const FADE_OUT = [{ opacity: 1 }, { opacity: 0 }];
|
|
2348
|
+
const FADE_IN = [{ opacity: 0 }, { opacity: 1 }];
|
|
2349
|
+
const move = (from, to) => [{ transform: from }, { transform: to }];
|
|
2350
|
+
// ── The preset catalog ──────────────────────────────────────────────────────
|
|
2351
|
+
// Keyed by a stable preset id persisted in pageSettings.routeAnimation.transition.
|
|
2352
|
+
const PAGE_TRANSITION_PRESETS = {
|
|
2353
|
+
// ── Move (both pages slide; no fade — the classic Codrops "move") ──────────
|
|
2354
|
+
'move-left': {
|
|
2355
|
+
category: 'move', label: 'Move left / from right',
|
|
2356
|
+
outKeyframes: move('translateX(0)', 'translateX(-100%)'),
|
|
2357
|
+
inKeyframes: move('translateX(100%)', 'translateX(0)'),
|
|
2358
|
+
},
|
|
2359
|
+
'move-right': {
|
|
2360
|
+
category: 'move', label: 'Move right / from left',
|
|
2361
|
+
outKeyframes: move('translateX(0)', 'translateX(100%)'),
|
|
2362
|
+
inKeyframes: move('translateX(-100%)', 'translateX(0)'),
|
|
2363
|
+
},
|
|
2364
|
+
'move-up': {
|
|
2365
|
+
category: 'move', label: 'Move up / from bottom',
|
|
2366
|
+
outKeyframes: move('translateY(0)', 'translateY(-100%)'),
|
|
2367
|
+
inKeyframes: move('translateY(100%)', 'translateY(0)'),
|
|
2368
|
+
},
|
|
2369
|
+
'move-down': {
|
|
2370
|
+
category: 'move', label: 'Move down / from top',
|
|
2371
|
+
outKeyframes: move('translateY(0)', 'translateY(100%)'),
|
|
2372
|
+
inKeyframes: move('translateY(-100%)', 'translateY(0)'),
|
|
2373
|
+
},
|
|
2374
|
+
// ── Fade (incoming sits on top; outgoing dissolves or holds) ───────────────
|
|
2375
|
+
'fade': {
|
|
2376
|
+
category: 'fade', label: 'Fade',
|
|
2377
|
+
outKeyframes: FADE_OUT, inKeyframes: FADE_IN, ontop: 'in',
|
|
2378
|
+
},
|
|
2379
|
+
'fade-from-right': {
|
|
2380
|
+
category: 'fade', label: 'Fade / from right',
|
|
2381
|
+
outKeyframes: FADE_OUT,
|
|
2382
|
+
inKeyframes: [{ transform: 'translateX(100%)', opacity: 0 }, { transform: 'translateX(0)', opacity: 1 }],
|
|
2383
|
+
ontop: 'in',
|
|
2384
|
+
},
|
|
2385
|
+
'fade-from-left': {
|
|
2386
|
+
category: 'fade', label: 'Fade / from left',
|
|
2387
|
+
outKeyframes: FADE_OUT,
|
|
2388
|
+
inKeyframes: [{ transform: 'translateX(-100%)', opacity: 0 }, { transform: 'translateX(0)', opacity: 1 }],
|
|
2389
|
+
ontop: 'in',
|
|
2390
|
+
},
|
|
2391
|
+
'fade-from-bottom': {
|
|
2392
|
+
category: 'fade', label: 'Fade / from bottom',
|
|
2393
|
+
outKeyframes: FADE_OUT,
|
|
2394
|
+
inKeyframes: [{ transform: 'translateY(100%)', opacity: 0 }, { transform: 'translateY(0)', opacity: 1 }],
|
|
2395
|
+
ontop: 'in',
|
|
2396
|
+
},
|
|
2397
|
+
// ── Scale ──────────────────────────────────────────────────────────────────
|
|
2398
|
+
'scale-down-up': {
|
|
2399
|
+
category: 'scale', label: 'Scale down / scale up',
|
|
2400
|
+
outKeyframes: [{ transform: 'scale(1)', opacity: 1 }, { transform: 'scale(0.8)', opacity: 0 }],
|
|
2401
|
+
inKeyframes: [{ transform: 'scale(1.2)', opacity: 0 }, { transform: 'scale(1)', opacity: 1 }],
|
|
2402
|
+
ontop: 'in',
|
|
2403
|
+
},
|
|
2404
|
+
'scale-down': {
|
|
2405
|
+
category: 'scale', label: 'Scale down / from right',
|
|
2406
|
+
outKeyframes: [{ transform: 'scale(1)', opacity: 1 }, { transform: 'scale(0.8)', opacity: 0 }],
|
|
2407
|
+
inKeyframes: move('translateX(100%)', 'translateX(0)'),
|
|
2408
|
+
ontop: 'in',
|
|
2409
|
+
},
|
|
2410
|
+
'scale-up': {
|
|
2411
|
+
category: 'scale', label: 'Move to left / scale up',
|
|
2412
|
+
outKeyframes: move('translateX(0)', 'translateX(-100%)'),
|
|
2413
|
+
inKeyframes: [{ transform: 'scale(0.8)', opacity: 0 }, { transform: 'scale(1)', opacity: 1 }],
|
|
2414
|
+
ontop: 'out',
|
|
2415
|
+
},
|
|
2416
|
+
// ── Rotate / 3D (the cinematic "wow" family) ───────────────────────────────
|
|
2417
|
+
'flip': {
|
|
2418
|
+
category: 'rotate', label: 'Flip',
|
|
2419
|
+
outKeyframes: [{ transform: 'rotateY(0deg)', opacity: 1 }, { transform: 'rotateY(-180deg)', opacity: 0 }],
|
|
2420
|
+
inKeyframes: [{ transform: 'rotateY(180deg)', opacity: 0 }, { transform: 'rotateY(0deg)', opacity: 1 }],
|
|
2421
|
+
outTransformOrigin: '50% 50%', inTransformOrigin: '50% 50%',
|
|
2422
|
+
},
|
|
2423
|
+
'cube-left': {
|
|
2424
|
+
category: 'rotate', label: 'Cube / to left',
|
|
2425
|
+
outKeyframes: [{ transform: 'translateZ(0) rotateY(0deg)', opacity: 1 }, { transform: 'translateZ(-800px) rotateY(-90deg)', opacity: 0.3 }],
|
|
2426
|
+
inKeyframes: [{ transform: 'translateZ(-800px) rotateY(90deg)', opacity: 0.3 }, { transform: 'translateZ(0) rotateY(0deg)', opacity: 1 }],
|
|
2427
|
+
outTransformOrigin: '50% 50%', inTransformOrigin: '50% 50%',
|
|
2428
|
+
},
|
|
2429
|
+
'cube-right': {
|
|
2430
|
+
category: 'rotate', label: 'Cube / to right',
|
|
2431
|
+
outKeyframes: [{ transform: 'translateZ(0) rotateY(0deg)', opacity: 1 }, { transform: 'translateZ(-800px) rotateY(90deg)', opacity: 0.3 }],
|
|
2432
|
+
inKeyframes: [{ transform: 'translateZ(-800px) rotateY(-90deg)', opacity: 0.3 }, { transform: 'translateZ(0) rotateY(0deg)', opacity: 1 }],
|
|
2433
|
+
outTransformOrigin: '50% 50%', inTransformOrigin: '50% 50%',
|
|
2434
|
+
},
|
|
2435
|
+
'carousel-left': {
|
|
2436
|
+
category: 'rotate', label: 'Carousel / to left',
|
|
2437
|
+
outKeyframes: [{ transform: 'translateX(0) scale(1)', opacity: 1 }, { transform: 'translateX(-150%) scale(0.4)', opacity: 0.3 }],
|
|
2438
|
+
inKeyframes: [{ transform: 'translateX(200%) scale(0.4)', opacity: 0.3 }, { transform: 'translateX(0) scale(1)', opacity: 1 }],
|
|
2439
|
+
ontop: 'in',
|
|
2440
|
+
},
|
|
2441
|
+
'carousel-right': {
|
|
2442
|
+
category: 'rotate', label: 'Carousel / to right',
|
|
2443
|
+
outKeyframes: [{ transform: 'translateX(0) scale(1)', opacity: 1 }, { transform: 'translateX(150%) scale(0.4)', opacity: 0.3 }],
|
|
2444
|
+
inKeyframes: [{ transform: 'translateX(-200%) scale(0.4)', opacity: 0.3 }, { transform: 'translateX(0) scale(1)', opacity: 1 }],
|
|
2445
|
+
ontop: 'in',
|
|
2446
|
+
},
|
|
2447
|
+
'fall': {
|
|
2448
|
+
category: 'rotate', label: 'Fall',
|
|
2449
|
+
outKeyframes: [{ transform: 'translateZ(0) rotateX(0deg)', opacity: 1 }, { transform: 'translateZ(-500px) rotateX(90deg)', opacity: 0 }],
|
|
2450
|
+
inKeyframes: FADE_IN,
|
|
2451
|
+
outTransformOrigin: '50% 50%', ontop: 'out', inDelayRatio: 0.3,
|
|
2452
|
+
},
|
|
2453
|
+
'newspaper': {
|
|
2454
|
+
category: 'rotate', label: 'Newspaper',
|
|
2455
|
+
outKeyframes: [{ transform: 'scale(1) rotate(0deg)', opacity: 1 }, { transform: 'scale(0) rotate(720deg)', opacity: 0 }],
|
|
2456
|
+
inKeyframes: [{ transform: 'scale(0) rotate(-720deg)', opacity: 0 }, { transform: 'scale(1) rotate(0deg)', opacity: 1 }],
|
|
2457
|
+
ontop: 'in', inDelayRatio: 0.5,
|
|
2458
|
+
},
|
|
2459
|
+
'fold-left': {
|
|
2460
|
+
category: 'rotate', label: 'Fold / unfold',
|
|
2461
|
+
outKeyframes: [{ transform: 'translateX(0) rotateY(0deg)', opacity: 1 }, { transform: 'translateX(-100%) rotateY(-90deg)', opacity: 0.6 }],
|
|
2462
|
+
inKeyframes: [{ transform: 'translateX(100%) rotateY(90deg)', opacity: 0.6 }, { transform: 'translateX(0) rotateY(0deg)', opacity: 1 }],
|
|
2463
|
+
outTransformOrigin: '0% 50%', inTransformOrigin: '100% 50%', ontop: 'in',
|
|
2464
|
+
},
|
|
2465
|
+
'room-left': {
|
|
2466
|
+
category: 'rotate', label: 'Room / to left',
|
|
2467
|
+
outKeyframes: [{ transform: 'translateX(0) rotateY(0deg)', opacity: 1 }, { transform: 'translateX(-100%) rotateY(90deg)', opacity: 0.4 }],
|
|
2468
|
+
inKeyframes: [{ transform: 'translateX(100%) rotateY(-90deg)', opacity: 0.4 }, { transform: 'translateX(0) rotateY(0deg)', opacity: 1 }],
|
|
2469
|
+
outTransformOrigin: '100% 50%', inTransformOrigin: '0% 50%',
|
|
2470
|
+
},
|
|
2471
|
+
};
|
|
2472
|
+
/** Built from PAGE_TRANSITION_PRESETS so the two lists can never drift apart. */
|
|
2473
|
+
const PAGE_TRANSITION_CATEGORIES = (() => {
|
|
2474
|
+
const order = [
|
|
2475
|
+
{ value: 'move', label: 'Move' },
|
|
2476
|
+
{ value: 'fade', label: 'Fade' },
|
|
2477
|
+
{ value: 'scale', label: 'Scale' },
|
|
2478
|
+
{ value: 'rotate', label: 'Rotate / 3D' },
|
|
2479
|
+
];
|
|
2480
|
+
return order.map(cat => ({
|
|
2481
|
+
...cat,
|
|
2482
|
+
presets: Object.entries(PAGE_TRANSITION_PRESETS)
|
|
2483
|
+
.filter(([, p]) => p.category === cat.value)
|
|
2484
|
+
.map(([value, p]) => ({ value, label: p.label })),
|
|
2485
|
+
}));
|
|
2486
|
+
})();
|
|
2487
|
+
/**
|
|
2488
|
+
* Resolve a persisted preset id + timing into the two WAAPI animations the consumer runs.
|
|
2489
|
+
* Returns `null` for unknown / 'none' presets (caller should skip the transition).
|
|
2490
|
+
*/
|
|
2491
|
+
function resolvePageTransition(name, opts = {}) {
|
|
2492
|
+
if (!name || name === 'none')
|
|
2493
|
+
return null;
|
|
2494
|
+
const preset = PAGE_TRANSITION_PRESETS[name];
|
|
2495
|
+
if (!preset)
|
|
2496
|
+
return null;
|
|
2497
|
+
const duration = opts.duration ?? DEFAULT_PAGE_TRANSITION_DURATION;
|
|
2498
|
+
const easing = opts.easing ?? 'ease';
|
|
2499
|
+
const perspective = preset.perspective ?? opts.perspective ?? DEFAULT_PAGE_TRANSITION_PERSPECTIVE;
|
|
2500
|
+
const clampRatio = (r) => Math.max(0, Math.min(1, r ?? 0));
|
|
2501
|
+
const outDelay = clampRatio(preset.outDelayRatio) * duration;
|
|
2502
|
+
const inDelay = clampRatio(preset.inDelayRatio) * duration;
|
|
2503
|
+
return {
|
|
2504
|
+
outFrames: preset.outKeyframes,
|
|
2505
|
+
inFrames: preset.inKeyframes,
|
|
2506
|
+
// fill:'both' holds keyframe[0] during the delay and keyframe[last] after — no flash.
|
|
2507
|
+
outOptions: { duration, easing, delay: outDelay, fill: 'both' },
|
|
2508
|
+
inOptions: { duration, easing, delay: inDelay, fill: 'both' },
|
|
2509
|
+
ontop: preset.ontop ?? 'in',
|
|
2510
|
+
perspective,
|
|
2511
|
+
outTransformOrigin: preset.outTransformOrigin,
|
|
2512
|
+
inTransformOrigin: preset.inTransformOrigin,
|
|
2513
|
+
};
|
|
2514
|
+
}
|
|
2515
|
+
/**
|
|
2516
|
+
* The ordered phases a navigation runs, given what is present. The order is INVARIANT:
|
|
2517
|
+
* every element `leave` animation finishes before the page `transition` starts, and the page
|
|
2518
|
+
* `transition` finishes before any element `enter` animation begins. Phases with nothing to
|
|
2519
|
+
* play are omitted. The engine iterates this list and `await`s each phase's completion.
|
|
2520
|
+
*/
|
|
2521
|
+
function buildTransitionTimeline(input) {
|
|
2522
|
+
const phases = [];
|
|
2523
|
+
if (input.hasLeave)
|
|
2524
|
+
phases.push('leave');
|
|
2525
|
+
if (input.hasTransition)
|
|
2526
|
+
phases.push('transition');
|
|
2527
|
+
if (input.hasEnter)
|
|
2528
|
+
phases.push('enter');
|
|
2529
|
+
return phases;
|
|
2530
|
+
}
|
|
2531
|
+
// ── Back-compat migration from the legacy single-page route-animation presets ─
|
|
2532
|
+
/**
|
|
2533
|
+
* Map a legacy `enter` preset (none/fade/slideUp/slideDown/zoomIn/zoomOut/blurIn/flip) to the
|
|
2534
|
+
* nearest cinematic paired `transition` id, so pages saved before this system keep animating.
|
|
2535
|
+
* Returns 'fade' for anything unmapped, and 'none' for 'none'.
|
|
2536
|
+
*/
|
|
2537
|
+
function legacyEnterToTransition(enter) {
|
|
2538
|
+
switch (enter) {
|
|
2539
|
+
case 'none': return 'none';
|
|
2540
|
+
case 'slideUp': return 'fade-from-bottom';
|
|
2541
|
+
case 'slideDown': return 'fade';
|
|
2542
|
+
case 'zoomIn': return 'scale-down-up';
|
|
2543
|
+
case 'zoomOut': return 'scale-down-up';
|
|
2544
|
+
case 'blurIn': return 'fade';
|
|
2545
|
+
case 'flip': return 'flip';
|
|
2546
|
+
case 'fade': return 'fade';
|
|
2547
|
+
default: return 'fade';
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
/**
|
|
2551
|
+
* Resolve the effective transition id for a page's route-animation settings: the explicit
|
|
2552
|
+
* `transition` when present, otherwise migrated from the legacy `enter` preset.
|
|
2553
|
+
*/
|
|
2554
|
+
function effectiveTransitionId(anim) {
|
|
2555
|
+
if (!anim)
|
|
2556
|
+
return 'fade';
|
|
2557
|
+
if (anim.transition)
|
|
2558
|
+
return anim.transition;
|
|
2559
|
+
return legacyEnterToTransition(anim.enter);
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2207
2562
|
/*
|
|
2208
2563
|
* Public API Surface of iox-ui
|
|
2209
2564
|
*/
|
|
@@ -2212,5 +2567,5 @@ function dataSourcePlanToRequest(plan, endpoints) {
|
|
|
2212
2567
|
* Generated bundle index. Do not edit.
|
|
2213
2568
|
*/
|
|
2214
2569
|
|
|
2215
|
-
export { AOSService, AnalyticsService, BuilderButtonComponent, BuilderDividerComponent, BuilderHeadingComponent, BuilderIconComponent, BuilderImageComponent, BuilderLinkComponent, BuilderSpacerComponent, ButtonBlockComponent, CMSClientInfraModule, CardComponent, ClientListComponent, ClientListItemComponent, ClientRepeaterComponent, ClientSliderContainerComponent, ClientSliderSlideComponent, ComponentInstanceRegistryService, ConsentService, ContainerComponent, ContentService, DEFAULT_WIDTH_BY_TYPE, ENVIRONMENT, IOX_BUILDER_EVENTS, IS_PREVIEW, IoxAnimateContainer, IoxAosDirective, IoxAosModule, IoxBuilderComponentsModule, IoxComponentRegistryService, IoxPageComponent, IoxPageModule, IoxUiModule, LinkedContainerComponent, PageScrollProvider, PrivacyModalComponent, PrivacyModalService, PrivacyModelEvent, SectionComponent, TextBlockComponent, ViewPositionDirective, ViewPositionModule, WebSettingsService, buildDataSourceFilter, compileDeclarations, dataSourcePlanToRequest, matchRouteParams, normalizeCollectionResult, planDataSource, renderDefaultDeclarations, resolveSingleItemId, rewriteViewportUnits, styleKeyToKebab };
|
|
2570
|
+
export { AOSService, AnalyticsService, BuilderButtonComponent, BuilderDividerComponent, BuilderHeadingComponent, BuilderIconComponent, BuilderImageComponent, BuilderLinkComponent, BuilderSpacerComponent, ButtonBlockComponent, CMSClientInfraModule, CardComponent, ClientListComponent, ClientListItemComponent, ClientRepeaterComponent, ClientSliderContainerComponent, ClientSliderSlideComponent, ComponentInstanceRegistryService, ConsentService, ContainerComponent, ContentService, DEFAULT_PAGE_TRANSITION_DURATION, DEFAULT_PAGE_TRANSITION_PERSPECTIVE, DEFAULT_WIDTH_BY_TYPE, ENVIRONMENT, IOX_BUILDER_EVENTS, IS_PREVIEW, IoxAnimateContainer, IoxAosDirective, IoxAosModule, IoxBuilderComponentsModule, IoxComponentRegistryService, IoxPageComponent, IoxPageModule, IoxUiModule, LinkedContainerComponent, PAGE_TRANSITION_CATEGORIES, PAGE_TRANSITION_PRESETS, PageScrollProvider, PrivacyModalComponent, PrivacyModalService, PrivacyModelEvent, SectionComponent, TextBlockComponent, VIRTUAL_TRAIT_KEYS, ViewPositionDirective, ViewPositionModule, WebSettingsService, buildDataSourceFilter, buildTransitionTimeline, compileDeclarations, composeVirtualTraits, dataSourcePlanToRequest, effectiveTransitionId, legacyEnterToTransition, matchRouteParams, normalizeCollectionResult, planDataSource, renderDefaultDeclarations, resolvePageTransition, resolveSingleItemId, rewriteViewportUnits, styleKeyToKebab };
|
|
2216
2571
|
//# sourceMappingURL=vectoriox-iox-ui.mjs.map
|