@vectoriox/iox-ui 4.17.3 → 4.19.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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, HostListener, Output, Input, Directive, NgModule, Injectable, ViewChild, Component, Host, Optional, inject, NgZone, Inject, InjectionToken, PLATFORM_ID, ChangeDetectionStrategy, ViewContainerRef, reflectComponentType } from '@angular/core';
|
|
2
|
+
import { EventEmitter, HostListener, Output, Input, Directive, NgModule, Injectable, ViewChild, Component, Host, Optional, inject, NgZone, Inject, InjectionToken, PLATFORM_ID, ChangeDetectionStrategy, ViewContainerRef, reflectComponentType, signal, computed } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/animations';
|
|
4
4
|
import { style, animate } from '@angular/animations';
|
|
5
5
|
import { Subject, fromEvent, of } from 'rxjs';
|
|
@@ -3260,6 +3260,226 @@ function safeSetInput(ref, name, value) {
|
|
|
3260
3260
|
return false;
|
|
3261
3261
|
}
|
|
3262
3262
|
|
|
3263
|
+
/**
|
|
3264
|
+
* THE binding path resolver — one implementation, shared by every renderer.
|
|
3265
|
+
*
|
|
3266
|
+
* Resolves a dot-notation path with optional array brackets against a data object:
|
|
3267
|
+
* `title`, `author.name`, `tags[0]`, `items[2].title`.
|
|
3268
|
+
*
|
|
3269
|
+
* This lived in three places before (iox-builder's binding-path.util, the engine's string
|
|
3270
|
+
* renderer, and the engine's component renderer) and had already drifted: the component-renderer
|
|
3271
|
+
* copy was missing the `$` case below, so a repeater over a primitive array rendered in the SSR
|
|
3272
|
+
* HTML and then blanked on hydration. See render-parity.md.
|
|
3273
|
+
*/
|
|
3274
|
+
function resolvePath(obj, path) {
|
|
3275
|
+
// Empty path (or `$`) means "the value itself" — used to bind to an item that IS a primitive
|
|
3276
|
+
// (e.g. a Repeater over `gallery: string[]`, where each item is the URL string). See
|
|
3277
|
+
// binding-panel-redesign-plan.md.
|
|
3278
|
+
if (path === '' || path === '$' || path == null)
|
|
3279
|
+
return obj;
|
|
3280
|
+
return path.split('.').reduce((current, key) => {
|
|
3281
|
+
if (current == null)
|
|
3282
|
+
return undefined;
|
|
3283
|
+
const bracketMatch = key.match(/^(\w+)\[(\d+)]$/);
|
|
3284
|
+
if (bracketMatch) {
|
|
3285
|
+
const arr = current[bracketMatch[1]];
|
|
3286
|
+
return Array.isArray(arr) ? arr[parseInt(bracketMatch[2], 10)] : undefined;
|
|
3287
|
+
}
|
|
3288
|
+
return current[key];
|
|
3289
|
+
}, obj);
|
|
3290
|
+
}
|
|
3291
|
+
|
|
3292
|
+
/**
|
|
3293
|
+
* Element context state — shared types.
|
|
3294
|
+
*
|
|
3295
|
+
* A **context slot** is a data-source alias whose value is WRITTEN at runtime (by an interaction)
|
|
3296
|
+
* instead of fetched. That is the whole trick: bindings need no new grammar, because a slot is just
|
|
3297
|
+
* another key in the `resolvedData` map both renderers already resolve against.
|
|
3298
|
+
*
|
|
3299
|
+
* See architecture/builder/element-context-state-plan.md.
|
|
3300
|
+
*/
|
|
3301
|
+
|
|
3302
|
+
/**
|
|
3303
|
+
* Turn a `setContext` value spec into the value to store.
|
|
3304
|
+
*
|
|
3305
|
+
* Returns `undefined` when the spec cannot be satisfied (e.g. `$item` on an element that is not in
|
|
3306
|
+
* a loop), which the store treats as "don't write" rather than "write empty".
|
|
3307
|
+
*/
|
|
3308
|
+
function resolveContextValue(spec, scope = {}) {
|
|
3309
|
+
if (!spec)
|
|
3310
|
+
return undefined;
|
|
3311
|
+
switch (spec.kind) {
|
|
3312
|
+
case 'item':
|
|
3313
|
+
return scope.item;
|
|
3314
|
+
case 'literal':
|
|
3315
|
+
return spec.value;
|
|
3316
|
+
case 'source': {
|
|
3317
|
+
const data = scope.resolvedData?.[spec.source];
|
|
3318
|
+
if (data == null)
|
|
3319
|
+
return undefined;
|
|
3320
|
+
return spec.path ? resolvePath(data, spec.path) : data;
|
|
3321
|
+
}
|
|
3322
|
+
default:
|
|
3323
|
+
return undefined;
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
/**
|
|
3327
|
+
* The value each slot holds before any interaction.
|
|
3328
|
+
*
|
|
3329
|
+
* `'first'` pre-fills from the resolved source so the page is never empty; `'none'` (the default)
|
|
3330
|
+
* leaves the key ABSENT — not set to undefined — so `resolvedData` looks exactly as it does for a
|
|
3331
|
+
* source that returned nothing, and bindings simply don't resolve.
|
|
3332
|
+
*/
|
|
3333
|
+
function initialSlotValues(slots, resolvedData = {}) {
|
|
3334
|
+
const out = {};
|
|
3335
|
+
for (const slot of slots ?? []) {
|
|
3336
|
+
if (slot?.default !== 'first')
|
|
3337
|
+
continue;
|
|
3338
|
+
const items = resolvedData[slot.source];
|
|
3339
|
+
if (Array.isArray(items) && items.length)
|
|
3340
|
+
out[slot.key] = items[0];
|
|
3341
|
+
}
|
|
3342
|
+
return out;
|
|
3343
|
+
}
|
|
3344
|
+
/**
|
|
3345
|
+
* Merge live slot values over the page's resolved data, producing the map bindings resolve against.
|
|
3346
|
+
*
|
|
3347
|
+
* Slot keys share the data-source namespace, so a slot deliberately shadows a source of the same
|
|
3348
|
+
* name — the same way a repeater row shadows its own source alias with the single item.
|
|
3349
|
+
*/
|
|
3350
|
+
function withContextSlots(resolvedData, slotValues) {
|
|
3351
|
+
return { ...(resolvedData ?? {}), ...(slotValues ?? {}) };
|
|
3352
|
+
}
|
|
3353
|
+
/** The set of declared slot keys — what marks a binding as "live". */
|
|
3354
|
+
function contextSlotKeys(slots) {
|
|
3355
|
+
return new Set((slots ?? []).map(s => s?.key).filter((k) => !!k));
|
|
3356
|
+
}
|
|
3357
|
+
/**
|
|
3358
|
+
* Does this node read a context slot? Nodes that do must be REGISTERED at render time and
|
|
3359
|
+
* re-applied when the store changes — they are the only ones whose props are not final after the
|
|
3360
|
+
* first render.
|
|
3361
|
+
*/
|
|
3362
|
+
function nodeUsesContext(node, slotKeys) {
|
|
3363
|
+
if (!slotKeys.size)
|
|
3364
|
+
return false;
|
|
3365
|
+
const bindings = node?.bindings;
|
|
3366
|
+
if (!Array.isArray(bindings))
|
|
3367
|
+
return false;
|
|
3368
|
+
return bindings.some(b => !!b?.source && slotKeys.has(b.source));
|
|
3369
|
+
}
|
|
3370
|
+
/**
|
|
3371
|
+
* Is a slot key a legal user alias?
|
|
3372
|
+
*
|
|
3373
|
+
* Slots live in the page's data-source alias namespace, so uniqueness is the existing rule. The one
|
|
3374
|
+
* extra constraint is the reserved `$` prefix (system aliases — `$route`, `$current`, …).
|
|
3375
|
+
*/
|
|
3376
|
+
function isValidSlotKey(key) {
|
|
3377
|
+
if (!key)
|
|
3378
|
+
return false;
|
|
3379
|
+
const trimmed = key.trim();
|
|
3380
|
+
if (!trimmed || trimmed.startsWith('$'))
|
|
3381
|
+
return false;
|
|
3382
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(trimmed);
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
/**
|
|
3386
|
+
* The runtime context channel: named slots an interaction writes and bindings read.
|
|
3387
|
+
*
|
|
3388
|
+
* Signal-backed because writes are HOT — a hover fires on every row crossing. A write must cost a
|
|
3389
|
+
* signal set and re-apply one input on the registered nodes; it must never re-clone a repeater or
|
|
3390
|
+
* re-render the loop. See element-context-state-plan.md (trap T2).
|
|
3391
|
+
*
|
|
3392
|
+
* Provided in root and reset by the consumer on page navigation — slots are page-level state.
|
|
3393
|
+
*/
|
|
3394
|
+
class ContextStore {
|
|
3395
|
+
constructor() {
|
|
3396
|
+
this._values = signal({}, ...(ngDevMode ? [{ debugName: "_values" }] : /* istanbul ignore next */ []));
|
|
3397
|
+
/** All live slot values. Merge over `resolvedData` with `withContextSlots` to resolve bindings. */
|
|
3398
|
+
this.values = this._values.asReadonly();
|
|
3399
|
+
/** The keys currently holding a value — what the "is this slot populated?" CSS state keys off. */
|
|
3400
|
+
this.populatedKeys = computed(() => new Set(Object.keys(this._values())), ...(ngDevMode ? [{ debugName: "populatedKeys" }] : /* istanbul ignore next */ []));
|
|
3401
|
+
}
|
|
3402
|
+
/**
|
|
3403
|
+
* Write a slot. An `undefined` value is IGNORED rather than stored: a spec that could not be
|
|
3404
|
+
* satisfied (e.g. `$item` outside a loop) must not silently blank a populated slot.
|
|
3405
|
+
*/
|
|
3406
|
+
set(key, value) {
|
|
3407
|
+
if (!key || value === undefined)
|
|
3408
|
+
return;
|
|
3409
|
+
const current = this._values();
|
|
3410
|
+
if (Object.is(current[key], value))
|
|
3411
|
+
return; // no-op writes must not wake subscribers
|
|
3412
|
+
this._values.set({ ...current, [key]: value });
|
|
3413
|
+
}
|
|
3414
|
+
/** Remove a slot's value entirely, so the key is ABSENT (not undefined) for binding resolution. */
|
|
3415
|
+
clear(key) {
|
|
3416
|
+
if (!key)
|
|
3417
|
+
return;
|
|
3418
|
+
const current = this._values();
|
|
3419
|
+
if (!(key in current))
|
|
3420
|
+
return;
|
|
3421
|
+
const next = { ...current };
|
|
3422
|
+
delete next[key];
|
|
3423
|
+
this._values.set(next);
|
|
3424
|
+
}
|
|
3425
|
+
/** Drop every slot — call on page navigation; context is page-level state. */
|
|
3426
|
+
resetAll() {
|
|
3427
|
+
if (!Object.keys(this._values()).length)
|
|
3428
|
+
return;
|
|
3429
|
+
this._values.set({});
|
|
3430
|
+
}
|
|
3431
|
+
/** Seed the initial values (from `initialSlotValues`) without clobbering later writes. */
|
|
3432
|
+
seed(values) {
|
|
3433
|
+
const incoming = Object.entries(values ?? {}).filter(([, v]) => v !== undefined);
|
|
3434
|
+
if (!incoming.length)
|
|
3435
|
+
return;
|
|
3436
|
+
this._values.set({ ...Object.fromEntries(incoming), ...this._values() });
|
|
3437
|
+
}
|
|
3438
|
+
/** Non-reactive read — for imperative code that must not create a dependency. */
|
|
3439
|
+
peek(key) {
|
|
3440
|
+
return this._values()[key];
|
|
3441
|
+
}
|
|
3442
|
+
/** Whether a slot currently holds a value. */
|
|
3443
|
+
has(key) {
|
|
3444
|
+
return key in this._values();
|
|
3445
|
+
}
|
|
3446
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ContextStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3447
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ContextStore, providedIn: 'root' }); }
|
|
3448
|
+
}
|
|
3449
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ContextStore, decorators: [{
|
|
3450
|
+
type: Injectable,
|
|
3451
|
+
args: [{ providedIn: 'root' }]
|
|
3452
|
+
}] });
|
|
3453
|
+
|
|
3454
|
+
/** Action types this module handles. Anything else is not a context action. */
|
|
3455
|
+
const CONTEXT_ACTION_TYPES = ['setContext', 'clearContext'];
|
|
3456
|
+
function isContextAction(action) {
|
|
3457
|
+
return !!action?.type && CONTEXT_ACTION_TYPES.includes(action.type);
|
|
3458
|
+
}
|
|
3459
|
+
/**
|
|
3460
|
+
* Resolve an action + pass into the store operation to perform, or `null` for "do nothing".
|
|
3461
|
+
*
|
|
3462
|
+
* Returning `null` (rather than throwing or guessing) is what lets a runtime call this for every
|
|
3463
|
+
* action on every pass and simply skip the misses.
|
|
3464
|
+
*/
|
|
3465
|
+
function contextActionEffect(action, pass = 'forward') {
|
|
3466
|
+
if (!isContextAction(action))
|
|
3467
|
+
return null;
|
|
3468
|
+
const params = (action.params ?? {});
|
|
3469
|
+
const slot = typeof params.slot === 'string' ? params.slot.trim() : '';
|
|
3470
|
+
if (!slot)
|
|
3471
|
+
return null;
|
|
3472
|
+
if (action.type === 'clearContext') {
|
|
3473
|
+
// A clear has no meaningful reverse — leaving the element must not re-populate the slot.
|
|
3474
|
+
return pass === 'forward' ? { op: 'clear', slot } : null;
|
|
3475
|
+
}
|
|
3476
|
+
// setContext
|
|
3477
|
+
if (pass === 'forward') {
|
|
3478
|
+
return params.value ? { op: 'set', slot, value: params.value } : null;
|
|
3479
|
+
}
|
|
3480
|
+
return params.noReverse ? null : { op: 'clear', slot };
|
|
3481
|
+
}
|
|
3482
|
+
|
|
3263
3483
|
/**
|
|
3264
3484
|
* Cinematic page-transition presets — the SINGLE SOURCE OF TRUTH shared by the page builder
|
|
3265
3485
|
* (preview) and the SSR client engine (production). Pure, transport-agnostic: this module only
|
|
@@ -3694,5 +3914,5 @@ function effectiveTransitionId(anim) {
|
|
|
3694
3914
|
* Generated bundle index. Do not edit.
|
|
3695
3915
|
*/
|
|
3696
3916
|
|
|
3697
|
-
export { AOSService, AnalyticsService, BuilderButtonComponent, BuilderDividerComponent, BuilderHeadingComponent, BuilderIconComponent, BuilderImageComponent, BuilderLinkComponent, BuilderSpacerComponent, ButtonBlockComponent, CMSClientInfraModule, CardComponent, ClientGalleryComponent, ClientListComponent, ClientListItemComponent, ClientRepeaterComponent, ClientSliderContainerComponent, ClientSliderSlideComponent, ComponentInstanceRegistryService, ConsentService, ContainerComponent, ContentService, DEFAULT_GALLERY_SCHEDULER, DEFAULT_PAGE_TRANSITION, DEFAULT_PAGE_TRANSITION_DURATION, DEFAULT_PAGE_TRANSITION_EASING, DEFAULT_PAGE_TRANSITION_PERSPECTIVE, DEFAULT_WIDTH_BY_TYPE, ENVIRONMENT, GALLERY_EFFECTS, GALLERY_EFFECT_DESCRIPTORS, GalleryLoop, IOX_BUILDER_EVENTS, IS_PREVIEW, IoxAnimateContainer, IoxAosDirective, IoxAosModule, IoxBuilderComponentsModule, IoxComponentRegistryService, IoxPageComponent, IoxPageModule, IoxUiModule, LinkedContainerComponent, PAGE_TRANSITION_CATEGORIES, PAGE_TRANSITION_PRESETS, PIPE_DESCRIPTORS, PIPE_REGISTRY, PageScrollProvider, PrivacyModalComponent, PrivacyModalService, PrivacyModelEvent, RESERVED_ALIAS_PREFIX, SUPPRESSED_STYLE_PROPS_BY_TYPE, SectionComponent, TRANSITION_FEELS, TextBlockComponent, VIRTUAL_TRAIT_KEYS, ViewPositionDirective, ViewPositionModule, WebSettingsService, applyBindingPipes, applyFeel, buildDataSourceFilter, buildRelatedFilter, buildTargetedStateSelector, buildTransitionTimeline, collectReferencedAliases, compileDeclarations, composeVirtualTraits, computeRelative, dataSourcePlanToRequest, declaredInputNames, effectiveTransitionId, excludeSelf, feelFor, getByPath, isReservedAlias, legacyEnterToTransition, matchRouteParams, nearestCommonAncestorId, nodeCssId, normalizeCollectionResult, parseUrlList, planDataSource, referencedDataSources, referencedDataSourcesDeep, renderDefaultDeclarations, resolveDerivedInto, resolveGalleryEffect, resolveGalleryUrls, resolvePageTransition, resolveRelativeInto, resolveRepeaterItems, resolveSiblings, resolveSingleItemId, rewriteViewportUnits, safeSetInput, stripSuppressedProps, styleKeyToKebab };
|
|
3917
|
+
export { AOSService, AnalyticsService, BuilderButtonComponent, BuilderDividerComponent, BuilderHeadingComponent, BuilderIconComponent, BuilderImageComponent, BuilderLinkComponent, BuilderSpacerComponent, ButtonBlockComponent, CMSClientInfraModule, CONTEXT_ACTION_TYPES, CardComponent, ClientGalleryComponent, ClientListComponent, ClientListItemComponent, ClientRepeaterComponent, ClientSliderContainerComponent, ClientSliderSlideComponent, ComponentInstanceRegistryService, ConsentService, ContainerComponent, ContentService, ContextStore, DEFAULT_GALLERY_SCHEDULER, DEFAULT_PAGE_TRANSITION, DEFAULT_PAGE_TRANSITION_DURATION, DEFAULT_PAGE_TRANSITION_EASING, DEFAULT_PAGE_TRANSITION_PERSPECTIVE, DEFAULT_WIDTH_BY_TYPE, ENVIRONMENT, GALLERY_EFFECTS, GALLERY_EFFECT_DESCRIPTORS, GalleryLoop, IOX_BUILDER_EVENTS, IS_PREVIEW, IoxAnimateContainer, IoxAosDirective, IoxAosModule, IoxBuilderComponentsModule, IoxComponentRegistryService, IoxPageComponent, IoxPageModule, IoxUiModule, LinkedContainerComponent, PAGE_TRANSITION_CATEGORIES, PAGE_TRANSITION_PRESETS, PIPE_DESCRIPTORS, PIPE_REGISTRY, PageScrollProvider, PrivacyModalComponent, PrivacyModalService, PrivacyModelEvent, RESERVED_ALIAS_PREFIX, SUPPRESSED_STYLE_PROPS_BY_TYPE, SectionComponent, TRANSITION_FEELS, TextBlockComponent, VIRTUAL_TRAIT_KEYS, ViewPositionDirective, ViewPositionModule, WebSettingsService, applyBindingPipes, applyFeel, buildDataSourceFilter, buildRelatedFilter, buildTargetedStateSelector, buildTransitionTimeline, collectReferencedAliases, compileDeclarations, composeVirtualTraits, computeRelative, contextActionEffect, contextSlotKeys, dataSourcePlanToRequest, declaredInputNames, effectiveTransitionId, excludeSelf, feelFor, getByPath, initialSlotValues, isContextAction, isReservedAlias, isValidSlotKey, legacyEnterToTransition, matchRouteParams, nearestCommonAncestorId, nodeCssId, nodeUsesContext, normalizeCollectionResult, parseUrlList, planDataSource, referencedDataSources, referencedDataSourcesDeep, renderDefaultDeclarations, resolveContextValue, resolveDerivedInto, resolveGalleryEffect, resolveGalleryUrls, resolvePageTransition, resolvePath, resolveRelativeInto, resolveRepeaterItems, resolveSiblings, resolveSingleItemId, rewriteViewportUnits, safeSetInput, stripSuppressedProps, styleKeyToKebab, withContextSlots };
|
|
3698
3918
|
//# sourceMappingURL=vectoriox-iox-ui.mjs.map
|