@vectoriox/iox-ui 5.42.0 → 5.44.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.
@@ -6,12 +6,15 @@ import { Subject, fromEvent } from 'rxjs';
6
6
  import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
7
7
  import * as i1 from '@angular/common';
8
8
  import { CommonModule, isPlatformBrowser } from '@angular/common';
9
+ import { SPEC_AXES, resolveDesignMotion } from '@vectoriox/iox-ui/design-core';
10
+ export * from '@vectoriox/iox-ui/design-core';
9
11
  import Lenis from 'lenis';
10
12
  import { SLIDER_WORDS, sliderPartElement, SliderRole, sliderWords, attachCarouselA11y, isSliderPart } from '@vectoriox/iox-ui/composite-core';
13
+ import { getByPath } from '@vectoriox/iox-ui/data-core';
14
+ export * from '@vectoriox/iox-ui/data-core';
11
15
  import { dialogOpenerAttributes, dialogDomId } from '@vectoriox/iox-ui/actions-core';
12
16
  import { planVideo, videoRootAttributes, videoInnerHtml, videoWords, VideoAttribute, attachVideoAt, VideoClass } from '@vectoriox/iox-ui/media-core';
13
17
  import * as i1$1 from '@angular/platform-browser';
14
- export * from '@vectoriox/iox-ui/design-core';
15
18
 
16
19
  class ViewPositionDirective {
17
20
  constructor(_elr) {
@@ -384,51 +387,144 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
384
387
  }]
385
388
  }] });
386
389
 
390
+ /**
391
+ * Reduced motion (CC1, R1 — complex-components plan §2d). The token sheet already collapses the
392
+ * motion tokens under `prefers-reduced-motion`; everything that moves through SCRIPT must ask the
393
+ * same question, and ask it HERE: the interaction engines (builder canvas + live site), the Slider's
394
+ * autoplay and the Gallery's crossfade loop. Publishable gate #6: reduced motion = motion dial 0.
395
+ */
396
+ const REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';
397
+ function defaultHost() {
398
+ return typeof window !== 'undefined' ? window : null;
399
+ }
400
+ /** True when the visitor asked their system for reduced motion. No `matchMedia` (SSR) → false. */
401
+ function prefersReducedMotion(host = defaultHost()) {
402
+ try {
403
+ return !!host?.matchMedia?.(REDUCED_MOTION_QUERY)?.matches;
404
+ }
405
+ catch {
406
+ return false;
407
+ }
408
+ }
409
+ /** True when script may animate. The ONE question every runtime asks before moving anything. */
410
+ function motionAllowed(host = defaultHost()) {
411
+ return !prefersReducedMotion(host);
412
+ }
413
+
414
+ /**
415
+ * Scrolling (AI plan rev 3.1 §3p, MO-D1/MO-D7): the look's `scroll` choice → the options the ONE page
416
+ * scroller starts Lenis with, or `null` for the browser's own scrolling. The table is the contract's
417
+ * `axes.scrolls`; this only turns its named easing into the function Lenis wants. Pure: the caller asks the
418
+ * visitor's reduced-motion preference (`prefersReducedMotion`) and passes the answer in.
419
+ */
420
+ var ScrollEasing;
421
+ (function (ScrollEasing) {
422
+ ScrollEasing["ExpoOut"] = "expo-out";
423
+ })(ScrollEasing || (ScrollEasing = {}));
424
+ /** The curves `axes.scrolls[].lenis.easing` may name. Expo-out is Lenis's own default curve. */
425
+ const SCROLL_EASINGS = {
426
+ [ScrollEasing.ExpoOut]: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
427
+ };
428
+ function planScroll(scroll, ctx) {
429
+ if (ctx.reducedMotion)
430
+ return null;
431
+ // An absent or unknown choice plays PRE_MOTION's Smooth — what every site glided with before rev 3.1.
432
+ const lenis = SPEC_AXES.scrolls[resolveDesignMotion({ scroll }).scroll].lenis;
433
+ if (!lenis)
434
+ return null;
435
+ return {
436
+ duration: lenis.duration,
437
+ easing: SCROLL_EASINGS[lenis.easing],
438
+ wheelMultiplier: lenis.wheelMultiplier,
439
+ syncTouch: lenis.syncTouch,
440
+ };
441
+ }
442
+
443
+ /**
444
+ * The ONE page scroller (AI plan rev 3.1 §3p). `IoxPageComponent` starts it with the plan of the look's
445
+ * Scrolling choice (`planScroll`); `scrollTo` actions and the dialog lock go through it whether or not
446
+ * Lenis runs. Never on the server: there is no window to scroll.
447
+ */
387
448
  class PageScrollProvider {
388
449
  constructor() {
389
- // inject() (not a ctor param) so subclasses like SsrSafePageScrollProvider keep `super()`.
450
+ // inject() (not a ctor param) so subclasses like the engine's document-scrolling provider keep `super()`.
390
451
  this.zone = inject(NgZone);
452
+ this.lenis = null;
453
+ this.wrapper = null;
454
+ this.lockedOverflow = null;
391
455
  }
392
- init(options) {
393
- if (this.lenis) {
394
- this.lenis.destroy();
395
- }
396
- if (this.rafId != null) {
397
- cancelAnimationFrame(this.rafId);
398
- }
399
- this.lenis = new Lenis(options || {});
456
+ init(start) {
457
+ this.destroy();
458
+ if (typeof window === 'undefined' || typeof requestAnimationFrame === 'undefined')
459
+ return;
460
+ this.wrapper = start.wrapper ?? null;
461
+ if (!start.lenis)
462
+ return;
463
+ this.lenis = new Lenis({ ...start.lenis, ...(start.wrapper ? { wrapper: start.wrapper } : {}), ...(start.content ? { content: start.content } : {}) });
400
464
  this.startLoop();
401
465
  }
466
+ /** Stop Lenis and its loop; the page falls back to the browser's own scrolling. */
467
+ destroy() {
468
+ if (this.rafId != null)
469
+ cancelAnimationFrame(this.rafId);
470
+ this.rafId = undefined;
471
+ this.lenis?.destroy();
472
+ this.lenis = null;
473
+ this.unlock();
474
+ }
402
475
  /** Hard-stop page scroll (dialog open, A1b): wheel/touch frozen until start(). */
403
476
  stop() {
404
- this.lenis?.stop();
477
+ if (this.lenis) {
478
+ this.lenis.stop();
479
+ return;
480
+ }
481
+ const el = this.scrollElement();
482
+ if (!el || this.lockedOverflow !== null)
483
+ return;
484
+ this.lockedOverflow = el.style.overflow;
485
+ el.style.overflow = 'hidden';
405
486
  }
406
487
  /** Resume after stop() — the dialog's close path, incl. native Esc/backdrop closes. */
407
488
  start() {
408
- this.lenis?.start();
489
+ if (this.lenis) {
490
+ this.lenis.start();
491
+ return;
492
+ }
493
+ this.unlock();
409
494
  }
410
495
  scrollTo(y, options) {
411
- this.instance.scrollTo(y, options);
496
+ if (this.lenis) {
497
+ this.lenis.scrollTo(y, options);
498
+ return;
499
+ }
500
+ const behavior = options?.immediate || prefersReducedMotion() ? 'auto' : 'smooth';
501
+ (this.wrapper ?? (typeof window !== 'undefined' ? window : null))?.scrollTo({ top: y, behavior });
412
502
  }
413
503
  scrollToTop(options) {
414
504
  this.scrollTo(0, options);
415
505
  }
506
+ /** The running Lenis, or null when the page scrolls natively (Normal, reduced motion, the server). */
416
507
  get instance() {
417
- if (!this.lenis) {
418
- throw new Error('PageScrollProvider: call init() before accessing the instance.');
419
- }
420
508
  return this.lenis;
421
509
  }
422
- startLoop() {
423
- if (!this.lenis) {
510
+ scrollElement() {
511
+ return this.wrapper ?? (typeof document !== 'undefined' ? document.documentElement : null);
512
+ }
513
+ unlock() {
514
+ if (this.lockedOverflow === null)
424
515
  return;
425
- }
516
+ const el = this.scrollElement();
517
+ if (el)
518
+ el.style.overflow = this.lockedOverflow;
519
+ this.lockedOverflow = null;
520
+ }
521
+ startLoop() {
426
522
  // Run the perpetual rAF loop OUTSIDE Angular. In-zone, a never-ending requestAnimationFrame
427
523
  // keeps ApplicationRef.isStable() permanently false, so SSR hydration never completes
428
524
  // (NG0506: "hydration expected isStable() to emit true ... didn't happen within 10000ms").
429
525
  this.zone.runOutsideAngular(() => {
430
526
  const loop = (time) => {
431
- this.lenis.raf(time);
527
+ this.lenis?.raf(time);
432
528
  this.rafId = requestAnimationFrame(loop);
433
529
  };
434
530
  this.rafId = requestAnimationFrame(loop);
@@ -445,6 +541,7 @@ class IoxPageComponent {
445
541
  constructor(pageScrollProvider) {
446
542
  this.pageScrollProvider = pageScrollProvider;
447
543
  this.class = '';
544
+ this.started = false;
448
545
  this.scrollEvent = new EventEmitter();
449
546
  }
450
547
  ngAfterViewInit() {
@@ -452,14 +549,13 @@ class IoxPageComponent {
452
549
  this.scrollSubscription = fromEvent(this.page.nativeElement, 'scroll').subscribe((event) => {
453
550
  this.onScroll(event);
454
551
  });
455
- this.pageScrollProvider.init({
456
- wrapper: this.page.nativeElement,
457
- content: this.page.nativeElement.querySelector('.page-mask'),
458
- duration: 1.2,
459
- easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
460
- });
552
+ this.startScroller();
461
553
  }
462
554
  }
555
+ ngOnChanges(changes) {
556
+ if (changes['scroll'] && this.started)
557
+ this.startScroller();
558
+ }
463
559
  onScroll(event) {
464
560
  const target = event.target;
465
561
  const scrollTop = target.scrollTop;
@@ -476,14 +572,24 @@ class IoxPageComponent {
476
572
  this.scrollSubscription.unsubscribe();
477
573
  }
478
574
  }
575
+ startScroller() {
576
+ this.started = true;
577
+ this.pageScrollProvider.init({
578
+ wrapper: this.page.nativeElement,
579
+ content: this.page.nativeElement.querySelector('.page-mask') ?? undefined,
580
+ lenis: planScroll(this.scroll, { reducedMotion: prefersReducedMotion() }),
581
+ });
582
+ }
479
583
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxPageComponent, deps: [{ token: PageScrollProvider }], target: i0.ɵɵFactoryTarget.Component }); }
480
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: IoxPageComponent, isStandalone: false, selector: "iox-page-component", inputs: { class: "class" }, outputs: { scrollEvent: "scrollEvent" }, viewQueries: [{ propertyName: "page", first: true, predicate: ["page"], descendants: true }], ngImport: i0, template: "<div #page [class]=\"class\" class=\"iox-page-wrapper\">\n <div class=\"page-mask\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{position:absolute;inset:0}.iox-page-wrapper{position:relative;width:100%;height:100%;overflow:auto}.page-mask{min-height:100%}\n"] }); }
584
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: IoxPageComponent, isStandalone: false, selector: "iox-page-component", inputs: { class: "class", scroll: "scroll" }, outputs: { scrollEvent: "scrollEvent" }, viewQueries: [{ propertyName: "page", first: true, predicate: ["page"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #page [class]=\"class\" class=\"iox-page-wrapper\">\n <div class=\"page-mask\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{position:absolute;inset:0}.iox-page-wrapper{position:relative;width:100%;height:100%;overflow:auto}.page-mask{min-height:100%}\n"] }); }
481
585
  }
482
586
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxPageComponent, decorators: [{
483
587
  type: Component,
484
588
  args: [{ selector: 'iox-page-component', standalone: false, template: "<div #page [class]=\"class\" class=\"iox-page-wrapper\">\n <div class=\"page-mask\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{position:absolute;inset:0}.iox-page-wrapper{position:relative;width:100%;height:100%;overflow:auto}.page-mask{min-height:100%}\n"] }]
485
589
  }], ctorParameters: () => [{ type: PageScrollProvider }], propDecorators: { class: [{
486
590
  type: Input
591
+ }], scroll: [{
592
+ type: Input
487
593
  }], page: [{
488
594
  type: ViewChild,
489
595
  args: ['page']
@@ -1400,30 +1506,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
1400
1506
  args: ['childrenHost', { read: ViewContainerRef, static: true }]
1401
1507
  }] } });
1402
1508
 
1403
- /**
1404
- * Reduced motion (CC1, R1 — complex-components plan §2d). The token sheet already collapses the
1405
- * motion tokens under `prefers-reduced-motion`; everything that moves through SCRIPT must ask the
1406
- * same question, and ask it HERE: the interaction engines (builder canvas + live site), the Slider's
1407
- * autoplay and the Gallery's crossfade loop. Publishable gate #6: reduced motion = motion dial 0.
1408
- */
1409
- const REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';
1410
- function defaultHost() {
1411
- return typeof window !== 'undefined' ? window : null;
1412
- }
1413
- /** True when the visitor asked their system for reduced motion. No `matchMedia` (SSR) → false. */
1414
- function prefersReducedMotion(host = defaultHost()) {
1415
- try {
1416
- return !!host?.matchMedia?.(REDUCED_MOTION_QUERY)?.matches;
1417
- }
1418
- catch {
1419
- return false;
1420
- }
1421
- }
1422
- /** True when script may animate. The ONE question every runtime asks before moving anything. */
1423
- function motionAllowed(host = defaultHost()) {
1424
- return !prefersReducedMotion(host);
1425
- }
1426
-
1427
1509
  // Virtual trait → composed CSS property helpers.
1428
1510
  //
1429
1511
  // Several style traits are "virtual" — they don't map 1:1 to a CSS property but
@@ -3190,309 +3272,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
3190
3272
  args: ['childrenHost', { read: ViewContainerRef, static: true }]
3191
3273
  }] } });
3192
3274
 
3193
- /**
3194
- * Shared data-source resolving pattern — the SINGLE source of truth for how an IoxDataSource
3195
- * becomes a backend fetch, consumed by BOTH the page builder (iox-cms-client bindings panel) and
3196
- * the SSR client engine (iox-client-engine DataSourceResolverService). There must be no second
3197
- * copy of this decision logic; only the transport differs between the two:
3198
- *
3199
- * builder → authenticated org-scoped controllers (admin session):
3200
- * single by id → GET admin.../resources/:type/:id (ContentService.getContentById)
3201
- * collection → GET admin.../resources/:type (ContentService.getContent)
3202
- * engine → @Public() controllers (no auth, isPublished filter applied server-side):
3203
- * single by id → GET api/:type/:id (UserResourcesController)
3204
- * collection → GET api/:type?filters (UserResourcesController)
3205
- *
3206
- * The DECISION (by-id vs collection, which id, which filters, how to pick the single result) is
3207
- * identical for both — that's what this module owns. Each app maps the returned {@link DataSourcePlan}
3208
- * onto its own transport. A single item is ALWAYS fetched by its id as a path segment — never a
3209
- * `?_id=` query — to match the builder's getContentById.
3210
- */
3211
- /** The order a query source returns its rows in (CC2, board 4 "Sort" — the data source popover). */
3212
- var DataSourceSortDir;
3213
- (function (DataSourceSortDir) {
3214
- DataSourceSortDir["Asc"] = "asc";
3215
- DataSourceSortDir["Desc"] = "desc";
3216
- })(DataSourceSortDir || (DataSourceSortDir = {}));
3217
- /** The query parameter carrying the order: `sort=order` ascending, `sort=-order` descending. A CONTROL like
3218
- * `limit`, not a field filter — the public controllers split it out (iox-cms `query-controls.ts`). */
3219
- const SORT_PARAM = 'sort';
3220
- const SORT_FIELD = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
3221
- /** `sort`'s wire value, or null when the source sets no (valid) order. */
3222
- function sortParamValue(sort) {
3223
- const field = sort?.field?.trim();
3224
- if (!field || !SORT_FIELD.test(field))
3225
- return null;
3226
- return sort?.dir === DataSourceSortDir.Desc ? `-${field}` : field;
3227
- }
3228
- /**
3229
- * Match a page route template against an actual path and extract named params.
3230
- * matchRouteParams('/project/:projectId', 'project/68abc') → { projectId: '68abc' }
3231
- * Both sides are normalised (leading slash stripped) and split on '/'; values are URL-decoded.
3232
- */
3233
- function matchRouteParams(template, actual) {
3234
- const t = (template ?? '').replace(/^\/+/, '').split('/');
3235
- const a = (actual ?? '').replace(/^\/+/, '').split('/');
3236
- const params = {};
3237
- for (let i = 0; i < t.length; i++) {
3238
- const seg = t[i];
3239
- if (seg && seg.startsWith(':'))
3240
- params[seg.slice(1)] = decodeURIComponent(a[i] ?? '');
3241
- }
3242
- return params;
3243
- }
3244
- /**
3245
- * Build the query filter for a data-source request from its filterByRouteParam / filterByQueryParams
3246
- * config. `field` is filtered by the route-param value (falling back to `defaultId`); query filters
3247
- * map each `field` to a query-param value (falling back to `defaultValue`), and a filter with NO
3248
- * `queryParam` is a constant on `defaultValue`. Empty values are omitted so the source isn't
3249
- * accidentally filtered to nothing.
3250
- */
3251
- function buildDataSourceFilter(req, routeParams = {}, queryParams = {}) {
3252
- const params = {};
3253
- const byRoute = req?.filterByRouteParam;
3254
- if (byRoute?.field && byRoute?.routeParam) {
3255
- const value = routeParams[byRoute.routeParam] ?? byRoute.defaultId;
3256
- if (value !== undefined && value !== null && value !== '')
3257
- params[byRoute.field] = value;
3258
- }
3259
- for (const q of req?.filterByQueryParams ?? []) {
3260
- if (!q?.field)
3261
- continue;
3262
- // No queryParam → a CONSTANT filter: defaultValue is the value, in the builder preview and
3263
- // on the live site alike. With a queryParam the URL wins and defaultValue is the fallback.
3264
- const value = q.queryParam ? (queryParams[q.queryParam] ?? q.defaultValue) : q.defaultValue;
3265
- if (value !== undefined && value !== null && value !== '')
3266
- params[q.field] = value;
3267
- }
3268
- return params;
3269
- }
3270
- /**
3271
- * Mirrors the builder's getContentById decision. When a SINGLE source is filtered by the item id
3272
- * (`_id`) via a route param, the item is fetched by PATH (`.../:type/:id`), not a `?_id=` query.
3273
- * Returns that id (route-param value, else `defaultId`), or `null` when the source isn't a
3274
- * single-by-id fetch — in which case the caller uses the collection endpoint + filters. The
3275
- * path-based form only applies to the id field; a single source filtered by any other field still
3276
- * goes through the collection endpoint.
3277
- */
3278
- function resolveSingleItemId(req, routeParams = {}) {
3279
- const byRoute = req?.filterByRouteParam;
3280
- if (!byRoute?.routeParam)
3281
- return null;
3282
- if (byRoute.field && byRoute.field !== '_id')
3283
- return null;
3284
- const value = routeParams[byRoute.routeParam] ?? byRoute.defaultId;
3285
- return value !== undefined && value !== null && value !== '' ? String(value) : null;
3286
- }
3287
- /**
3288
- * Resolve an IoxDataSource into a transport-agnostic {@link DataSourcePlan}. This is the shared
3289
- * decision both the builder and the SSR engine run; each then executes the plan with its own
3290
- * HTTP layer. Single sources with a route-param id resolve to a `by-id` (path) fetch — exactly like
3291
- * the builder's getContentById.
3292
- */
3293
- function planDataSource(ds, routeParams = {}, queryParams = {}) {
3294
- const mode = ds?.mode === 'single' ? 'single' : 'list';
3295
- switch (ds?.type) {
3296
- case 'cms':
3297
- case 'shop': {
3298
- const domain = ds.type;
3299
- const req = domain === 'cms' ? ds.request?.cms : ds.request?.shop;
3300
- const resource = req?.contentType;
3301
- if (!resource)
3302
- return { kind: 'none' };
3303
- const id = mode === 'single' ? resolveSingleItemId(req, routeParams) : null;
3304
- if (id)
3305
- return { kind: 'by-id', domain, resource, id, mode };
3306
- const filter = buildDataSourceFilter(req, routeParams, queryParams);
3307
- const plan = { kind: 'collection', domain, resource, filter, mode };
3308
- if (req?.limit)
3309
- plan.limit = req.limit;
3310
- const sort = sortParamValue(req?.sort);
3311
- if (sort)
3312
- plan.sort = sort;
3313
- return plan;
3314
- }
3315
- case 'external-api': {
3316
- const endpoint = ds.request?.endpoint;
3317
- return endpoint ? { kind: 'external', endpoint, mode } : { kind: 'none' };
3318
- }
3319
- case 'static':
3320
- return { kind: 'static', data: ds.request?.data ?? null, mode };
3321
- case 'derived': {
3322
- const d = ds.request?.derived;
3323
- return d?.from ? { kind: 'derived', from: d.from, path: d.path ?? '', mode } : { kind: 'none' };
3324
- }
3325
- case 'variable':
3326
- // A VARIABLE is a page-local resource whose value is WRITTEN at runtime by an interaction
3327
- // (setContext), never fetched. It resolves to nothing here on purpose: the page renders
3328
- // its empty state until something writes it. `request.variable.itemsFrom` only names the
3329
- // source whose items it holds, so the bind picker can suggest fields.
3330
- return { kind: 'none' };
3331
- default:
3332
- return { kind: 'none' };
3333
- }
3334
- }
3335
- /**
3336
- * The aliases on a page that are VARIABLES — runtime-written resources, not fetched data.
3337
- *
3338
- * Shared so the builder and the SSR engine agree on which aliases start empty and are filled by
3339
- * interactions. See element-context-state-plan.md.
3340
- */
3341
- function variableAliases(dataSources) {
3342
- const out = new Set();
3343
- for (const ds of dataSources ?? []) {
3344
- if (ds?.type === 'variable' && ds.alias)
3345
- out.add(ds.alias);
3346
- }
3347
- return out;
3348
- }
3349
- /** The source alias whose items a variable holds, if it declares one (for field suggestions). */
3350
- function variableItemsFrom(dataSources, alias) {
3351
- for (const ds of dataSources ?? []) {
3352
- if (ds?.type === 'variable' && ds.alias === alias)
3353
- return ds.request?.variable?.itemsFrom || undefined;
3354
- }
3355
- return undefined;
3356
- }
3357
- /**
3358
- * Normalise a collection response into the shape a source expects: unwraps `{items}`/`{data}`
3359
- * envelopes, then returns the first item for a `single` source or the whole array for a `list`.
3360
- * A `by-id` response is already the item, so callers pass it through unchanged.
3361
- */
3362
- function normalizeCollectionResult(mode, data) {
3363
- const items = Array.isArray(data) ? data : (data?.items ?? data?.data ?? []);
3364
- return mode === 'single' ? (items[0] ?? null) : items;
3365
- }
3366
- /** Navigate a dot/bracket path into an object, e.g. `gallery`, `details.images`, `variants[0].skus`.
3367
- * Returns undefined if any segment is missing. Kept minimal + self-contained so it is shareable by
3368
- * both the builder and the SSR engine (the two have divergent local `resolvePath` copies). */
3369
- function getByPath(obj, path) {
3370
- if (obj == null || !path)
3371
- return obj;
3372
- // Turn `a[0].b` into ['a','0','b'].
3373
- const segments = path.replace(/\[(\w+)\]/g, '.$1').split('.').filter(Boolean);
3374
- let cur = obj;
3375
- for (const seg of segments) {
3376
- if (cur == null)
3377
- return undefined;
3378
- cur = cur[seg];
3379
- }
3380
- return cur;
3381
- }
3382
- /**
3383
- * The array a Repeater (or a repeating Slider) iterates over — the SHARED decision so the builder
3384
- * canvas and the SSR engine agree (see data-source-resolving.md).
3385
- * - No `sourcePath`: the resolved source IS the list. An array passes through; a lone object degrades
3386
- * to a single-row list (back-compat with the old `fetchItems`); null/undefined → `[]`.
3387
- * - With `sourcePath`: the source resolved to a SINGLE resource (e.g. a product); dive into the
3388
- * nested array property (e.g. `gallery`). Non-array / missing → `[]`.
3389
- */
3390
- /**
3391
- * Fill in `derived` aliases in an already-resolved map. Given the data sources and a map of resolved
3392
- * NON-derived values (by alias), compute each `type:'derived'` alias as `getByPath(parent, path)` in
3393
- * dependency order (chains resolved by iterating until stable). Mutates + returns the map. Used by the
3394
- * SSR engine after it resolves the root sources; the builder resolves derived lazily per alias.
3395
- */
3396
- function resolveDerivedInto(dataSources, resolved) {
3397
- const derived = (dataSources ?? []).filter(d => d?.type === 'derived' && !!d.alias);
3398
- let changed = true, guard = 0;
3399
- while (changed && guard++ < 25) {
3400
- changed = false;
3401
- for (const d of derived) {
3402
- if (d.alias in resolved)
3403
- continue;
3404
- const from = d.request?.derived?.from;
3405
- if (from && from in resolved) {
3406
- resolved[d.alias] = getByPath(resolved[from], d.request.derived.path ?? '');
3407
- changed = true;
3408
- }
3409
- }
3410
- }
3411
- return resolved;
3412
- }
3413
- function resolveRepeaterItems(resolved, sourcePath) {
3414
- if (sourcePath) {
3415
- const nested = getByPath(resolved, sourcePath);
3416
- return Array.isArray(nested) ? nested : [];
3417
- }
3418
- if (Array.isArray(resolved))
3419
- return resolved;
3420
- return resolved == null ? [] : [resolved];
3421
- }
3422
- // ── Referenced data sources (shared: builder-save + SSR resolve) ─────────────────────────────────
3423
- // Which data-source aliases a node tree uses, so a consumer resolves ONLY what a page/global needs
3424
- // (not the whole org library). Used by cms-client (persist globals' sources) and the SSR engine
3425
- // (resolve the referenced subset per page). See org-data-sources-plan.md.
3426
- /** Aliases referenced anywhere in a node tree: a repeater/slider `source` (a `bindings` entry with
3427
- * `prop === 'source'`, or `props.source` for the slider) plus every binding's `source`. */
3428
- function collectReferencedAliases(nodes, acc = new Set()) {
3429
- for (const n of nodes ?? []) {
3430
- for (const b of n?.bindings ?? []) {
3431
- if (b?.source)
3432
- acc.add(b.source);
3433
- }
3434
- if (n?.props?.source)
3435
- acc.add(n.props.source);
3436
- if (n?.children?.length)
3437
- collectReferencedAliases(n.children, acc);
3438
- }
3439
- return acc;
3440
- }
3441
- /** The subset of `all` whose `alias` is referenced by `nodes` (shallow — direct references only). */
3442
- function referencedDataSources(nodes, all) {
3443
- const aliases = collectReferencedAliases(nodes);
3444
- return (all ?? []).filter(ds => aliases.has(ds?.alias));
3445
- }
3446
- /** Like `referencedDataSources`, but also pulls in a referenced source's DEPENDENCIES (transitively),
3447
- * none of which the layout names directly:
3448
- * - a `derived` alias needs its `request.derived.from` parent;
3449
- * - a `relative` (route-context) alias needs its `request.relative.subjectFrom` (the current item)
3450
- * and `request.relative.from` (the collection it navigates).
3451
- * Use this when RESOLVING (the engine) so derived views and siblings/related don't resolve to nothing. */
3452
- function referencedDataSourcesDeep(nodes, all) {
3453
- const byAlias = new Map((all ?? []).map(d => [d?.alias, d]));
3454
- const wanted = collectReferencedAliases(nodes);
3455
- const queue = [...wanted];
3456
- const enqueue = (alias) => {
3457
- if (alias && !wanted.has(alias)) {
3458
- wanted.add(alias);
3459
- queue.push(alias);
3460
- }
3461
- };
3462
- while (queue.length) {
3463
- const ds = byAlias.get(queue.pop());
3464
- enqueue(ds?.request?.derived?.from);
3465
- enqueue(ds?.request?.relative?.subjectFrom);
3466
- enqueue(ds?.request?.relative?.from);
3467
- }
3468
- return (all ?? []).filter(d => wanted.has(d?.alias));
3469
- }
3470
- /**
3471
- * Turn a resolved {@link DataSourcePlan} into the concrete public HTTP request (url + params) — the
3472
- * SINGLE place that decides the URL shape, shared by the builder binding preview and the SSR engine
3473
- * so both hit the SAME public endpoints (no admin, no duplication). Returns `null` for `static` /
3474
- * `none` plans (no HTTP call). A single item is a PATH segment (`/:resource/:id`), never `?_id=`.
3475
- */
3476
- function dataSourcePlanToRequest(plan, endpoints) {
3477
- const baseFor = (domain) => (domain === 'shop' ? endpoints.shopBase : endpoints.cmsBase);
3478
- switch (plan.kind) {
3479
- case 'by-id':
3480
- return { url: `${baseFor(plan.domain)}${plan.resource}/${encodeURIComponent(plan.id)}`, params: {} };
3481
- case 'collection': {
3482
- const params = { ...plan.filter };
3483
- if (plan.limit)
3484
- params['limit'] = plan.limit;
3485
- if (plan.sort)
3486
- params[SORT_PARAM] = plan.sort;
3487
- return { url: `${baseFor(plan.domain)}${plan.resource}`, params };
3488
- }
3489
- case 'external':
3490
- return { url: plan.endpoint, params: {} };
3491
- default:
3492
- return null;
3493
- }
3494
- }
3495
-
3496
3275
  /**
3497
3276
  * Gallery — data model + the SHARED "what are the image URLs" resolver.
3498
3277
  *
@@ -6623,177 +6402,6 @@ function compileOwnStyle(style) {
6623
6402
  return css;
6624
6403
  }
6625
6404
 
6626
- /**
6627
- * Shared RELATIVE (route-context) data resolving — the SINGLE source of truth for how a detail page
6628
- * derives values FROM its current route item, consumed by BOTH the page builder (iox-cms-client) and
6629
- * the SSR client engine (iox-client-engine). Companion to `data-source-resolver.ts`.
6630
- *
6631
- * These are the pure, transport-agnostic pieces behind the Route binding scope
6632
- * (`$route` / `$current` / `$siblings` / `$related`). Resolution is a DEPENDENT SECOND PASS: the
6633
- * consumer resolves `$current` first (the existing single by-id fetch via `planDataSource`), then
6634
- * calls these to derive the relative values — there is NO new `DataSourcePlan` kind (`$related` still
6635
- * feeds a normal `collection` plan built from {@link buildRelatedFilter}). See
6636
- * `architecture/builder/relative-data-sources-plan.md`.
6637
- *
6638
- * There must be no second copy of this decision logic; only the transport (which HTTP layer fetches
6639
- * the ordered collection / related list) differs between the two consumers.
6640
- */
6641
- /** Aliases in the Route scope are platform-owned and start with this prefix; a USER alias may never
6642
- * start with it, which keeps the Route scope structurally collision-proof with Local/Global. Used to
6643
- * validate new/renamed aliases and to render the reserved (read-only) item state in the bind picker. */
6644
- const RESERVED_ALIAS_PREFIX = '$';
6645
- /** True for a platform-owned Route-scope alias (`$route`, `$current`, `$siblings`, `$related`, …). */
6646
- function isReservedAlias(alias) {
6647
- return typeof alias === 'string' && alias.startsWith(RESERVED_ALIAS_PREFIX);
6648
- }
6649
- const EMPTY_SIBLINGS = { prev: null, next: null, index: -1, count: 0, isFirst: false, isLast: false };
6650
- /** Generic, deterministic comparator: numbers numerically, Dates by time, everything else by
6651
- * locale-aware string compare (ISO date strings sort correctly this way). Nullish sorts first. */
6652
- function compareValues(a, b) {
6653
- if (a == null && b == null)
6654
- return 0;
6655
- if (a == null)
6656
- return -1;
6657
- if (b == null)
6658
- return 1;
6659
- if (typeof a === 'number' && typeof b === 'number')
6660
- return a - b;
6661
- const da = a instanceof Date ? a.getTime() : NaN;
6662
- const db = b instanceof Date ? b.getTime() : NaN;
6663
- if (!isNaN(da) && !isNaN(db))
6664
- return da - db;
6665
- return String(a).localeCompare(String(b));
6666
- }
6667
- /**
6668
- * Locate the current item within an ordered set and return its neighbours + position. Pure: the input
6669
- * list is never mutated (sorting works on a shallow copy). `currentId` is compared to each item's
6670
- * `idField` via string equality (route-param values are strings). When the current id isn't found,
6671
- * `index` is `-1` and `prev`/`next` are `null` (but `count` still reflects the set size).
6672
- */
6673
- function resolveSiblings(items, currentId, options = {}) {
6674
- const list = Array.isArray(items) ? items.slice() : [];
6675
- const count = list.length;
6676
- if (count === 0)
6677
- return { ...EMPTY_SIBLINGS };
6678
- const idField = options.idField ?? '_id';
6679
- if (options.sortBy) {
6680
- const dir = options.sortDir === 'desc' ? -1 : 1;
6681
- list.sort((a, b) => dir * compareValues(getByPath(a, options.sortBy), getByPath(b, options.sortBy)));
6682
- }
6683
- const cid = currentId == null ? null : String(currentId);
6684
- const index = cid == null ? -1 : list.findIndex(it => String(getByPath(it, idField)) === cid);
6685
- if (index === -1)
6686
- return { prev: null, next: null, index: -1, count, isFirst: false, isLast: false };
6687
- const canWrap = !!options.wrap && count > 1;
6688
- const prev = index > 0 ? list[index - 1] : (canWrap ? list[count - 1] : null);
6689
- const next = index < count - 1 ? list[index + 1] : (canWrap ? list[0] : null);
6690
- return { prev, next, index, count, isFirst: index === 0, isLast: index === count - 1 };
6691
- }
6692
- /** A value usable as an equality filter param: a non-empty scalar. Objects/arrays/nullish are skipped
6693
- * so a related query isn't built from an unresolved rel object (surfaced as a config issue in the UI
6694
- * rather than silently matching everything). Multi-value match is a v2 concern. */
6695
- function isScalarFilterValue(v) {
6696
- if (v == null)
6697
- return false;
6698
- if (typeof v === 'string')
6699
- return v !== '';
6700
- if (typeof v === 'number')
6701
- return Number.isFinite(v);
6702
- return typeof v === 'boolean';
6703
- }
6704
- /**
6705
- * Build the collection filter for `$related` from the resolved current item: an equality match on
6706
- * each `matchField`'s value (e.g. same `category`). Feeds a normal `collection` plan — no new plan
6707
- * kind. Fields whose value is not a scalar (or is empty) are omitted, matching
6708
- * `buildDataSourceFilter`'s "don't over-filter" rule. Exclude-self is applied to the RESULT via
6709
- * {@link excludeSelf} (the public query controllers are equality-only, so it can't be a `$ne` param).
6710
- */
6711
- function buildRelatedFilter(current, options) {
6712
- const fields = Array.isArray(options.matchFields) ? options.matchFields : [options.matchFields];
6713
- const filter = {};
6714
- for (const field of fields) {
6715
- if (!field)
6716
- continue;
6717
- const value = getByPath(current, field);
6718
- if (isScalarFilterValue(value))
6719
- filter[field] = value;
6720
- }
6721
- return filter;
6722
- }
6723
- /**
6724
- * Drop the current item from a list by `idField` (default `_id`). Used to exclude self from a
6725
- * `$related` result after fetch. A nullish/empty `currentId` leaves the list unchanged.
6726
- */
6727
- function excludeSelf(items, currentId, idField = '_id') {
6728
- if (!Array.isArray(items))
6729
- return [];
6730
- if (currentId == null || currentId === '')
6731
- return items;
6732
- const cid = String(currentId);
6733
- return items.filter(it => String(getByPath(it, idField)) !== cid);
6734
- }
6735
- /** Resolve kinds in a fixed order so a `siblings`/`related` source may reference `$current` (or any
6736
- * earlier relative alias) via `subjectFrom` and still see it resolved. */
6737
- const KIND_ORDER = { route: 0, current: 1, siblings: 2, related: 3 };
6738
- /** Does an item satisfy every field in an equality predicate map (string-compared)? */
6739
- function matchesFilter(item, filter) {
6740
- return Object.keys(filter).every(k => String(getByPath(item, k)) === String(filter[k]));
6741
- }
6742
- /**
6743
- * Compute ONE relative source's value from its already-resolved {@link RelativeInputs} — the SHARED
6744
- * kind→computation decision, so the batch pass ({@link resolveRelativeInto}) and the builder's async
6745
- * per-alias resolver produce identical results with no forked switch. `route` → the route params;
6746
- * `current` → the subject; `siblings` → {@link resolveSiblings} over the collection; `related` → the
6747
- * collection filtered by {@link buildRelatedFilter}'s predicate (+ {@link excludeSelf}).
6748
- */
6749
- function computeRelative(spec, inputs) {
6750
- const idField = spec.idField ?? '_id';
6751
- switch (spec.kind) {
6752
- case 'route':
6753
- return inputs.routeParams ?? {};
6754
- case 'current':
6755
- return inputs.subject ?? null;
6756
- case 'siblings': {
6757
- const siblings = resolveSiblings(inputs.collection, getByPath(inputs.subject, idField), {
6758
- idField, sortBy: spec.sortBy, sortDir: spec.sortDir, wrap: spec.wrap,
6759
- });
6760
- // `pick` resolves the source directly to that neighbour item (named-source shape,
6761
- // e.g. `nextProject`); without it the caller binds a sub-path of the whole object.
6762
- return spec.pick ? siblings[spec.pick] : siblings;
6763
- }
6764
- case 'related': {
6765
- const filter = buildRelatedFilter(inputs.subject, { matchFields: spec.matchFields ?? [] });
6766
- const pool = Array.isArray(inputs.collection) ? inputs.collection : [];
6767
- const items = pool.filter(it => matchesFilter(it, filter));
6768
- return spec.excludeSelf !== false ? excludeSelf(items, getByPath(inputs.subject, idField), idField) : items;
6769
- }
6770
- default:
6771
- return null;
6772
- }
6773
- }
6774
- /**
6775
- * Compute every `type:'relative'` source into `resolved` (keyed by alias), IN PLACE. Pure w.r.t. HTTP
6776
- * — it only reads already-resolved roots + the route params, so both consumers run it identically as
6777
- * a second pass. Delegates each source to {@link computeRelative}. `current`'s subject is `from`;
6778
- * `siblings`/`related` take `collection` = `from` and `subject` = `subjectFrom ?? from`. Mutates and
6779
- * returns `resolved`.
6780
- */
6781
- function resolveRelativeInto(dataSources, resolved, routeParams = {}) {
6782
- const relatives = (dataSources ?? [])
6783
- .filter(d => d?.type === 'relative' && !!d.alias && !!d.request?.relative)
6784
- .sort((a, b) => KIND_ORDER[a.request.relative.kind] - KIND_ORDER[b.request.relative.kind]);
6785
- for (const d of relatives) {
6786
- const spec = d.request.relative;
6787
- const subjectAlias = spec.kind === 'current' ? spec.from : (spec.subjectFrom ?? spec.from);
6788
- resolved[d.alias] = computeRelative(spec, {
6789
- subject: subjectAlias ? resolved[subjectAlias] : undefined,
6790
- collection: spec.from ? resolved[spec.from] : undefined,
6791
- routeParams,
6792
- });
6793
- }
6794
- return resolved;
6795
- }
6796
-
6797
6405
  /**
6798
6406
  * Binding pipes — render-time value transforms (UI label: "Filters").
6799
6407
  *
@@ -8399,6 +8007,51 @@ function effectiveTransitionId(anim) {
8399
8007
  return anim.transition;
8400
8008
  return legacyEnterToTransition(anim.enter);
8401
8009
  }
8010
+ const NO_PAGE_TRANSITION = 'none';
8011
+ /** The widest viewport a page change treats as a phone (MO-D5): the Mobile landscape breakpoint. */
8012
+ const PHONE_TRANSITION_QUERY = `(max-width: ${breakpointDef(Breakpoint.Mobile).maxWidth}px)`;
8013
+ /**
8014
+ * The part of the context only the browser knows — is this a phone, does the page read right to left —
8015
+ * read the same way by every runtime that plays a page change (the engine, Preview). No window → neither.
8016
+ */
8017
+ function viewportTransitionContext(view, el) {
8018
+ return {
8019
+ phone: !!view?.matchMedia?.(PHONE_TRANSITION_QUERY)?.matches,
8020
+ rtl: !!el && view?.getComputedStyle?.(el)?.direction === 'rtl',
8021
+ };
8022
+ }
8023
+ /** The page set its own transition (a preset id, or a legacy `enter` that migrates to one). */
8024
+ function hasOwnPageTransition(anim) {
8025
+ return !!(anim?.transition || anim?.enter);
8026
+ }
8027
+ /**
8028
+ * The ONE decision of what plays when a page arrives, for the engine and every builder preview:
8029
+ * • a page with its own Route animation plays it, exactly as before (an unflagged page too: with none set
8030
+ * it keeps the platform default, `effectiveTransitionId`);
8031
+ * • a design-system page with none follows the look's Between pages — never on its initial load (MO-D6:
8032
+ * no IN half, no server pre-state), as Fade on a phone for Slide and Cinematic (MO-D5), mirrored in RTL.
8033
+ * Reduced motion is the runtime's own question (`motionAllowed`), asked before anything plays.
8034
+ */
8035
+ function pageTransitionOf(anim, ctx = {}) {
8036
+ if (!ctx.designSystem || hasOwnPageTransition(anim)) {
8037
+ return {
8038
+ transition: effectiveTransitionId(anim),
8039
+ duration: anim?.duration, easing: anim?.easing, perspective: anim?.perspective, curtainColor: anim?.curtainColor,
8040
+ fromLook: false,
8041
+ };
8042
+ }
8043
+ if (ctx.initial)
8044
+ return { transition: NO_PAGE_TRANSITION, fromLook: true };
8045
+ let choice = SPEC_AXES.betweens[resolveDesignMotion({ between: ctx.between }).between];
8046
+ if (ctx.phone && choice.phone)
8047
+ choice = SPEC_AXES.betweens[choice.phone];
8048
+ const feel = choice.feel ? applyFeel(choice.feel) : undefined;
8049
+ return {
8050
+ transition: ctx.rtl && choice.rtl ? choice.rtl : choice.transition,
8051
+ ...(feel ?? {}),
8052
+ fromLook: true,
8053
+ };
8054
+ }
8402
8055
 
8403
8056
  /*
8404
8057
  * Public API Surface of iox-ui
@@ -8408,5 +8061,5 @@ function effectiveTransitionId(anim) {
8408
8061
  * Generated bundle index. Do not edit.
8409
8062
  */
8410
8063
 
8411
- 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, DataSourceSortDir, 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, ON_STATE_ROLES, PAGE_STYLE_TOKENS, PAGE_TOKEN_FALLBACKS, PAGE_TRANSITION_CATEGORIES, PAGE_TRANSITION_PRESETS, PART_CLASS_NAMES, PART_PAGINATION_MODIFIER, PIPE_DESCRIPTORS, PIPE_REGISTRY, PageScrollProvider, PageStyleField, PageStyleSource, REDUCED_MOTION_QUERY, RESERVED_ALIAS_PREFIX, SLIDER_INPUTS_ATTRIBUTE, SLIDER_INPUT_NAMES, SORT_PARAM, STATE_PSEUDO_CLASS, SUPPRESSED_STYLE_PROPS_BY_TYPE, SWIPER_A11Y_OPTIONS, SWIPER_RESPONSIVE_TRAITS, SWIPER_TRIGGER_EVENTS, 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, buildDataSourceFilter, buildInteractionKeyframes, buildPartSelector, buildRelatedFilter, buildSwiperBreakpoints, buildTargetedStateSelector, buildTargetedSuffixSelector, buildTransitionTimeline, cascadeChain, clearInputOverride, clearOverride, closeAboveMediaQuery, collectContextSlotKeys, collectReferencedAliases, compileDeclarations, compilePageStyle, componentStatesFor, composeVirtualTraits, computeRelative, containerHtmlTag, contextActionEffect, contextSlotKeys, countOverrides, dataSourcePlanToRequest, declaredInputNames, decomposeBackdropFilter, defaultHoverTransition, defaultMessageResolver, deriveSeoFromContent, describePageStyle, describeSeoFields, dialogCloseAboveMinWidth, domHasSliderParts, effectiveActionType, effectiveTransitionId, entrancePreStateStyle, excludeSelf, feelFor, finalKeyframe, getByPath, getSeoValue, hasHoverState, hasOwnTransition, initialSlotValues, isActionEnabled, isContextAction, isCurrentLink, isExternalOrFragment, isGradientPaint, isInputOverriddenAt, isLastEmittedStateKey, isOverriddenAt, isReservedAlias, isValidSlotKey, isWholeBackdropSet, keyframePropertyName, keyframeStyleEntries, legacyEnterToTransition, matchRouteParams, mediaQueryFor, mergeSwiperBreakpoints, migrateLegacyDirection, migrateLegacyTextAlign, motionAllowed, nearestCommonAncestorId, needsAccessibleName, needsGroupName, nodeA11yAttributes, nodeCssId, nodeTraitValue, nodeUsesContext, normalizeAppPath, normalizeCollectionResult, normalizeGalleryImage, normalizeIconClass, orderStatesForEmit, parentBreakpoint, parseUrlList, partClassName, planDataSource, planResponsiveRules, planSwiperOptions, prefersReducedMotion, referencedDataSources, referencedDataSourcesDeep, renderDefaultDeclarations, resetPageStyleField, resetSeoField, resolveBoundValue, resolveContextValue, resolveDerivedInto, resolveGalleryEffect, resolveGalleryUrls, resolveInputChain, resolveInputs, resolvePageTransition, resolvePath, resolveRelativeInto, resolveRepeaterItems, resolveSeo, resolveSiblings, resolveSingleItemId, resolveStateStyles, resolveStyleProps, resolveToggleVisibility, resolveValueChain, rewriteViewportUnits, safeSetInput, serializeA11yAttributes, setInputOverride, setOverride, setSeoAuto, setSeoBinding, setSeoOverride, setSeoValue, sliderControlElements, sliderInputsFromProps, sliderInputsOf, sortParamValue, stateNamesIn, statePseudoClass, stateSelectorSuffix, stripSuppressedProps, swiperAutoplayAllowed, swiperLoopOptions, swiperModuleNames, syncNodeA11yAttributes, targetedStateSelector, variableAliases, variableItemsFrom, withContextSlots, withDefaultHoverTransition, wrapInBreakpointQuery, wrapInMediaQuery };
8064
+ 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, 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 };
8412
8065
  //# sourceMappingURL=vectoriox-iox-ui.mjs.map