@vectoriox/iox-builder 11.13.0 → 11.14.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.
@@ -17,12 +17,13 @@ import { TooltipModule } from 'primeng/tooltip';
17
17
  import * as i20 from 'primeng/dialog';
18
18
  import { DialogModule } from 'primeng/dialog';
19
19
  import * as i1$1 from '@vectoriox/iox-ui';
20
- import { nodeCssId, needsGroupName, resolveBoundValue, STRUCTURAL_STATES as STRUCTURAL_STATES$1, VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, TEXT_DIRECTION_KEY, TEXT_ALIGN_KEY, TextAlign, COLOR_SCHEME_TRAIT, COLOR_SCHEMES, ColorScheme, LinkType, MAX_LINES_KEY, A11yTrait, BREAKPOINTS, Breakpoint, withSchemeInk, stripSuppressedProps, DeclarationContext, planPartRule, gateHoverRule, planResponsiveRules, resolveStyleProps, planStateRule, splitOuterProps, OUTER_STYLE_PROPS, compileTokenCssBlocks, catalogFontId, fontsForTokens, GOOGLE_FONTS_FILE_ORIGIN, googleFontHref, compileDeclarations, isLastEmittedStateKey, wrapInBreakpointQuery, BreakpointQueryKind, NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, applyElementStyle, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, ContextStore, ENTRANCE_ACTION_TYPES, EXIT_ACTION_TYPES, ComponentInstanceRegistryService, entranceStartsHidden, isActionEnabled, splitPressFeedback, isHoverPointer, isContextAction, contextActionEffect, resolveContextValue, effectiveActionType, INTERACTION_HIDDEN_ATTRIBUTE, motionAllowed, settleInteraction, settleModeFor, playInteraction, resolveInteractionEasing, entranceDelay, repeatedRowIndex, entrancePreStateStyle, buildInteractionKeyframes, cascadeChain, declaredInputNames, emptyImagePlaceholder, syncNodeDesignClasses, nodeTraitValue, syncNodeA11yAttributes, nodeA11yAttributes, safeSetInput, colorSchemeOf, withStateTransitions, composeVirtualTraits, stateNamesIn, partClassName, switchElementStyle, releaseElementStyle, countOverrides, setOverride, breakpointDef, breakpointForWidth, FormRenderState, needsAccessibleName, resolveInputs, setInputOverride, barReserveClass, collectContextSlotKeys, withContextSlots, compilePageStyle, nodeUsesContext, isScrolled, SCROLLED_ATTRIBUTE, syncSubmitButtons, IS_PREVIEW, buttonBlockHref, bootSlider, IoxPageModule, PALETTE_PRESETS, elementStyleById, PART_CLASS_NAMES } from '@vectoriox/iox-ui';
20
+ import { nodeCssId, needsGroupName, resolveBoundValue, STRUCTURAL_STATES as STRUCTURAL_STATES$1, VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, TEXT_DIRECTION_KEY, TEXT_ALIGN_KEY, TextAlign, COLOR_SCHEME_TRAIT, COLOR_SCHEMES, ColorScheme, LinkType, MAX_LINES_KEY, A11yTrait, BREAKPOINTS, Breakpoint, withSchemeInk, stripSuppressedProps, DeclarationContext, planPartRule, gateHoverRule, planResponsiveRules, resolveStyleProps, planStateRule, splitOuterProps, OUTER_STYLE_PROPS, compileTokenCssBlocks, catalogFontId, fontsForTokens, GOOGLE_FONTS_FILE_ORIGIN, googleFontHref, compileDeclarations, isLastEmittedStateKey, wrapInBreakpointQuery, BreakpointQueryKind, NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, applyElementStyle, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, ContextStore, ENTRANCE_ACTION_TYPES, EXIT_ACTION_TYPES, ComponentInstanceRegistryService, entranceStartsHidden, isActionEnabled, splitPressFeedback, isHoverPointer, isContextAction, contextActionEffect, resolveContextValue, effectiveActionType, INTERACTION_HIDDEN_ATTRIBUTE, motionAllowed, settleInteraction, settleModeFor, playInteraction, resolveInteractionEasing, entranceDelay, repeatedRowIndex, entrancePreStateStyle, buildInteractionKeyframes, cascadeChain, declaredInputNames, emptyImagePlaceholder, syncNodeDesignClasses, nodeTraitValue, syncNodeA11yAttributes, nodeA11yAttributes, safeSetInput, colorSchemeOf, withStateTransitions, composeVirtualTraits, stateNamesIn, partClassName, switchElementStyle, releaseElementStyle, countOverrides, setOverride, breakpointDef, breakpointForWidth, FormRenderState, needsAccessibleName, resolveInputs, setInputOverride, barReserveClass, collectContextSlotKeys, withContextSlots, compilePageStyle, nodeUsesContext, hidingHeadersIn, HeaderRuntime, isScrolled, SCROLLED_ATTRIBUTE, syncSubmitButtons, IS_PREVIEW, buttonBlockHref, bootSlider, IoxPageModule, PALETTE_PRESETS, elementStyleById, PART_CLASS_NAMES } from '@vectoriox/iox-ui';
21
21
  export { ComponentInstanceRegistryService, VIRTUAL_TRAIT_KEYS, composeVirtualTraits } from '@vectoriox/iox-ui';
22
- import { StructureEdit, isAccordionPart, isDisclosurePart, isSliderPart, isTabsPart, isSegmentedPart, structureRefusal, StructureRefusal, SegmentedRole, SEGMENTED_MAX_OPTIONS, AccordionRole, SEGMENTED_MIN_OPTIONS, isExclusiveItemPart, TabsRole, ITEM_OPEN_STATE, readStyle, isSegmentedRoot, segmentedDefaultOn, segmentedOptions, isTabsRoot, isTabsFromContent, tabsTriggers, isAccordionRoot, isAccordionFromContent, accordionItems, initialAccordionOpen, accordionBehaviour, exclusiveItemLabel, exclusiveRootOf, tabTriggerOf, tabLabel, removeTabPair, tabPanelOf, tabsListOf, tabsPanelsOf, nextTabKey, CompositeBehaviourTrait, ACCORDION_DEFAULT_ONS, TabsBehaviourTrait, TABS_ACTIVATE_ONS, TABS_ORIENTATIONS, onCompositeItemState, isCompositeItemOn, runCompositeItemAction, shouldScrollToItem, rowIndexOf as rowIndexOf$1, slideIndexForRow, DisclosureRole, isExclusiveTrigger, compositeScopeId, compositeRowKeys, isExclusiveRoot, ExclusiveRuntime, exclusiveDefaultOf, exclusiveLabelOf, exclusiveBehaviourOf, exclusiveKindOf, compositeKindOfRole, AccordionRuntime, isToggleKind, closestAccordionItem, isAnyCompositeRoot, SceneRole, isExclusiveList, buildCardRecipe, buildBadge, buildChip, buildAccordionRecipe, buildDisclosureRecipe, buildTabsRecipe, buildSegmentedRecipe, buildLightboxRecipe, NO_ELEMENT_STYLE, CompositeKind, SliderRole, accordionItemLabel, segmentedOptionLabel, isExclusivePanels, isLockedPart, accordionRootOf, accordionItemOf, addAccordionItem, addTabPair, segmentedAddRefusal, addSegmentedOption, isCompositeItem, accordionHeadingLevel, isCompositePanel, isCompositeTrigger, splitSliderChildren, hasSliderParts } from '@vectoriox/iox-ui/composite-core';
22
+ import { StructureEdit, isAccordionPart, isDisclosurePart, isSliderPart, isTabsPart, isSegmentedPart, structureRefusal, StructureRefusal, SegmentedRole, SEGMENTED_MAX_OPTIONS, AccordionRole, SEGMENTED_MIN_OPTIONS, isExclusiveItemPart, TabsRole, ITEM_OPEN_STATE, readStyle, isSegmentedRoot, segmentedDefaultOn, segmentedOptions, isTabsRoot, isTabsFromContent, tabsTriggers, isAccordionRoot, isAccordionFromContent, accordionItems, initialAccordionOpen, accordionBehaviour, exclusiveItemLabel, exclusiveRootOf, tabTriggerOf, tabLabel, removeTabPair, tabPanelOf, tabsListOf, tabsPanelsOf, nextTabKey, CompositeBehaviourTrait, ACCORDION_DEFAULT_ONS, TabsBehaviourTrait, TABS_ACTIVATE_ONS, TABS_ORIENTATIONS, onCompositeItemState, isCompositeItemOn, runCompositeItemAction, shouldScrollToItem, rowIndexOf as rowIndexOf$1, slideIndexForRow, DisclosureRole, isExclusiveTrigger, compositeScopeId, compositeRowKeys, isExclusiveRoot, ExclusiveRuntime, exclusiveDefaultOf, exclusiveLabelOf, exclusiveBehaviourOf, exclusiveKindOf, compositeKindOfRole, AccordionRuntime, isToggleKind, closestAccordionItem, isAnyCompositeRoot, SceneRole, isExclusiveList, buildCardRecipe, buildBadge, buildChip, buildAccordionRecipe, buildDisclosureRecipe, buildTabsRecipe, buildSegmentedRecipe, buildLightboxRecipe, NO_ELEMENT_STYLE, CompositeKind, SliderRole, accordionItemLabel, segmentedOptionLabel, isExclusivePanels, isLockedPart, accordionRootOf, accordionItemOf, addAccordionItem, addTabPair, segmentedAddRefusal, addSegmentedOption, isCompositeItem, accordionHeadingLevel, isCompositePanel, isCompositeTrigger, splitSliderChildren, hasSliderParts, SLIDE_CAPTION_TRAIT, SLIDER_SCROLL_PLAYS_TRAIT, SLIDER_PLACEMENT_TRAIT, SliderPlacement, SliderFlag } from '@vectoriox/iox-ui/composite-core';
23
23
  import { formContentInHost, isInteractiveHost, findFormContentInHosts, FORM_CHANNEL_ROLE, channelHref, channelOpensNewTab, FORM_ACTIONS_ROLE, SUBMIT_BUTTON_NODE_TYPE } from '@vectoriox/iox-ui/forms-core';
24
24
  import { Subject, BehaviorSubject, of, forkJoin } from 'rxjs';
25
25
  import interact from 'interactjs';
26
+ import { HeaderTrait, HeaderBehaviour, HeaderEdge } from '@vectoriox/iox-ui/design-core';
26
27
  import { map, catchError } from 'rxjs/operators';
27
28
  import * as i1 from '@angular/common/http';
28
29
  import { itemActionOf, BEHAVIOUR_ACTION_TYPES, SERVER_ELEMENT_ACTION_TYPES, CONSENT_ACTION_TYPES, opensAtClickedItem, openedDialogId, DIALOG_CLOSING_ATTRIBUTE, cancelExit, runExitMotion } from '@vectoriox/iox-ui/actions-core';
@@ -1941,6 +1942,24 @@ function buildCompositeBehaviourTraits() {
1941
1942
  new TraitConfig(TabsBehaviourTrait.Label, 'Accessible name', TraitInputType.Text),
1942
1943
  ];
1943
1944
  }
1945
+ /**
1946
+ * How a header behaves as the page scrolls (premium components T2, M4) — on the Navigation bar's root. No default: a
1947
+ * plain Container saves none; edited in the Navigation bar's Header section, never as generic rows.
1948
+ */
1949
+ function buildHeaderBehaviourTraits() {
1950
+ return [
1951
+ new TraitConfig(HeaderTrait.Behaviour, 'Header behaviour', TraitInputType.Select, [
1952
+ { label: 'Scrolls away', value: HeaderBehaviour.Scrolls },
1953
+ { label: 'Stays at the top', value: HeaderBehaviour.Stays },
1954
+ { label: 'Hides while scrolling down', value: HeaderBehaviour.Hides },
1955
+ ]),
1956
+ new TraitConfig(HeaderTrait.Edge, 'Edge when scrolled', TraitInputType.Select, [
1957
+ { label: 'Fade', value: HeaderEdge.Fade },
1958
+ { label: 'Line', value: HeaderEdge.Line },
1959
+ { label: 'None', value: HeaderEdge.None },
1960
+ ]),
1961
+ ];
1962
+ }
1944
1963
  const LINK_TARGETS = [
1945
1964
  { label: 'Same tab', value: '_self' },
1946
1965
  { label: 'New tab', value: '_blank' },
@@ -9774,6 +9793,8 @@ class BuilderComponent {
9774
9793
  if (target?.closest?.('a[href]'))
9775
9794
  event.preventDefault();
9776
9795
  };
9796
+ /** The canvas's hiding headers (premium M4, T2) — the SAME runtime the live site runs, fed the canvas's scroll. */
9797
+ this.headerRuntimes = new Map();
9777
9798
  this._scrollbarTimer = null;
9778
9799
  }
9779
9800
  ngOnInit() {
@@ -9974,6 +9995,9 @@ class BuilderComponent {
9974
9995
  this.moveableCanvas.destroy();
9975
9996
  this.selectoCanvas.destroy();
9976
9997
  this.destroyLenis();
9998
+ for (const runtime of this.headerRuntimes.values())
9999
+ runtime.destroy();
10000
+ this.headerRuntimes.clear();
9977
10001
  this.canvasRo?.disconnect();
9978
10002
  this.previewFrameRo?.disconnect();
9979
10003
  this.beforeGlobalsRo?.disconnect();
@@ -10015,6 +10039,30 @@ class BuilderComponent {
10015
10039
  this.globalOverlayRef?.nativeElement?.style.setProperty('--preview-vw', vwVal);
10016
10040
  this.canvasFrameHeight = Math.round(frameH);
10017
10041
  }
10042
+ /**
10043
+ * A header that hides on the canvas steps aside as the author scrolls down and comes back on the way up, exactly as
10044
+ * on the live site. The headers live in the global overlay (outside Lenis); Lenis's scroll is visual px, so it is
10045
+ * divided by the zoom. A header that went (a re-render, its behaviour changed) has its runtime dropped.
10046
+ */
10047
+ syncHeaderRuntimes(visualOffset) {
10048
+ const overlay = this.globalOverlayRef?.nativeElement;
10049
+ const live = new Set(overlay ? hidingHeadersIn(overlay) : []);
10050
+ for (const [el, runtime] of this.headerRuntimes) {
10051
+ if (!live.has(el)) {
10052
+ runtime.destroy();
10053
+ this.headerRuntimes.delete(el);
10054
+ }
10055
+ }
10056
+ const offset = visualOffset / (this.viewportService.getState().scale || 1);
10057
+ for (const el of live) {
10058
+ let runtime = this.headerRuntimes.get(el);
10059
+ if (!runtime) {
10060
+ runtime = new HeaderRuntime(el);
10061
+ this.headerRuntimes.set(el, runtime);
10062
+ }
10063
+ runtime.update(offset);
10064
+ }
10065
+ }
10018
10066
  /** Keep the Scrolled attribute (iox-ui SCROLLED_ATTRIBUTE) on the canvas page and the header overlay — written only
10019
10067
  * when it changes, so the overlay's mutation observers never wake for a scroll tick. */
10020
10068
  syncScrolled(offset) {
@@ -10040,6 +10088,7 @@ class BuilderComponent {
10040
10088
  this.sceneCanvas?.pinNow();
10041
10089
  // The Scrolled state (G4) on the canvas: the page and its header globals know the canvas has moved.
10042
10090
  this.syncScrolled(instance.scroll);
10091
+ this.syncHeaderRuntimes(instance.scroll);
10043
10092
  const clientH = this.previewScrollRef.nativeElement.clientHeight;
10044
10093
  this.onPageScroll({
10045
10094
  scrollTop: instance.scroll,
@@ -11964,12 +12013,28 @@ class SliderContainerComponent {
11964
12013
  // override the dir-driven direction with the generic Layout default → RTL wouldn't apply.
11965
12014
  // Rebuild cached objects so ngStyle only re-applies on real input changes (avoids MO spam).
11966
12015
  const { direction: _dropDirection, ...rest } = v || {};
11967
- this._previewStyle = rest;
11968
- this._editShellStyle = { ...rest, position: 'relative' };
12016
+ this._restStyle = rest;
12017
+ this.composeStageStyles();
12018
+ }
12019
+ /** A slider the scroll plays is a sticky stage (it never engages on the canvas, where the driver pins it, so its top
12020
+ * never offsets the shell; in Preview it holds the slider mid-screen). */
12021
+ composeStageStyles() {
12022
+ const stage = this.scrollPlays ? { position: 'sticky' } : null;
12023
+ this._previewStyle = stage ? { ...this._restStyle, ...stage } : this._restStyle;
12024
+ this._editShellStyle = { ...this._restStyle, position: stage ? 'sticky' : 'relative' };
11969
12025
  }
11970
12026
  get style() { return this._style; }
11971
12027
  get previewStyle() { return this._previewStyle; }
11972
12028
  get editShellStyle() { return this._editShellStyle; }
12029
+ /** Premium M4: the page's scroll plays it (held mid-screen, resting on each picture). */
12030
+ set scrollPlays(value) {
12031
+ const on = value === true || value === 'true';
12032
+ if (on === this._scrollPlays)
12033
+ return;
12034
+ this._scrollPlays = on;
12035
+ this.composeStageStyles();
12036
+ }
12037
+ get scrollPlays() { return this._scrollPlays; }
11973
12038
  get source() { return this._source; }
11974
12039
  set source(value) {
11975
12040
  if (value === this._source)
@@ -12012,6 +12077,7 @@ class SliderContainerComponent {
12012
12077
  this._style = {};
12013
12078
  this._previewStyle = {};
12014
12079
  this._editShellStyle = { position: 'relative' };
12080
+ this._restStyle = {};
12015
12081
  this.nodeId = '';
12016
12082
  this.dropListId = '';
12017
12083
  // ── Parameters ─────────────────────────────────────────────────────────────
@@ -12030,6 +12096,7 @@ class SliderContainerComponent {
12030
12096
  // ── Effects ────────────────────────────────────────────────────────────────
12031
12097
  this.effect = 'slide';
12032
12098
  this.speed = 300;
12099
+ this._scrollPlays = false;
12033
12100
  // ── Navigation ─────────────────────────────────────────────────────────────
12034
12101
  this.enableNavigation = false;
12035
12102
  this.navigationColor = '';
@@ -12071,6 +12138,9 @@ class SliderContainerComponent {
12071
12138
  this.instanceRegistry = inject(ComponentInstanceRegistryService);
12072
12139
  this.interactionEngine = inject(InteractionEngineService);
12073
12140
  this.ngZone = inject(NgZone);
12141
+ /** The canvas's (and Preview's) ONE scene driver — it plays a slider the scroll plays. */
12142
+ this.sceneCanvas = inject(SceneCanvasService, { optional: true });
12143
+ this.sceneAttached = null;
12074
12144
  this.isPreview = !!isPreview;
12075
12145
  }
12076
12146
  ngOnInit() {
@@ -12112,7 +12182,7 @@ class SliderContainerComponent {
12112
12182
  'enableScrollbar', 'enableAutoplay',
12113
12183
  'enableKeyboard', 'enableMousewheel', 'enableZoom', 'enableGrid', 'enableParallax',
12114
12184
  'autoplayDelay', 'autoplayPauseOnMouseEnter', 'autoplayDisableOnInteraction',
12115
- 'gridRows',
12185
+ 'gridRows', 'scrollPlays',
12116
12186
  ]);
12117
12187
  // Edit mode also reinits when children change (new slide added or removed)
12118
12188
  const editKeys = new Set([...previewKeys, 'children']);
@@ -12128,8 +12198,21 @@ class SliderContainerComponent {
12128
12198
  ngOnDestroy() {
12129
12199
  cancelAnimationFrame(this._initRafId);
12130
12200
  this._destroySwiper();
12201
+ this.syncSceneDriver(false);
12131
12202
  this._bindingSub?.unsubscribe();
12132
12203
  }
12204
+ /** Hand the runway to the scene driver while the scroll plays the slider, and take it back when it stops. */
12205
+ syncSceneDriver(on) {
12206
+ const runway = this.runwayEl?.nativeElement ?? null;
12207
+ if (this.sceneAttached && (!on || this.sceneAttached !== runway)) {
12208
+ this.sceneCanvas?.detach(this.sceneAttached);
12209
+ this.sceneAttached = null;
12210
+ }
12211
+ if (on && runway && !this.sceneAttached) {
12212
+ this.sceneCanvas?.attach(runway, !this.isPreview, this.nodeId);
12213
+ this.sceneAttached = runway;
12214
+ }
12215
+ }
12133
12216
  trackByNodeId(_index, node) {
12134
12217
  return node.id ?? String(_index);
12135
12218
  }
@@ -12226,6 +12309,7 @@ class SliderContainerComponent {
12226
12309
  return;
12227
12310
  this._swiper = swiper;
12228
12311
  this.instanceRegistry.register(this.nodeId, this._swiper);
12312
+ this.syncSceneDriver(this.scrollPlays);
12229
12313
  }
12230
12314
  swiperInputs() {
12231
12315
  return {
@@ -12237,7 +12321,7 @@ class SliderContainerComponent {
12237
12321
  enableZoom: this.enableZoom, enableGrid: this.enableGrid, enableParallax: this.enableParallax, autoplayDelay: this.autoplayDelay,
12238
12322
  autoplayPauseOnMouseEnter: this.autoplayPauseOnMouseEnter, autoplayDisableOnInteraction: this.autoplayDisableOnInteraction,
12239
12323
  paginationType: this.paginationType, paginationClickable: this.paginationClickable, paginationDynamicBullets: this.paginationDynamicBullets,
12240
- gridRows: this.gridRows, breakpoints: this.breakpoints,
12324
+ gridRows: this.gridRows, breakpoints: this.breakpoints, scrollPlays: this.scrollPlays,
12241
12325
  };
12242
12326
  }
12243
12327
  _destroySwiper() {
@@ -12262,7 +12346,11 @@ class SliderContainerComponent {
12262
12346
  }
12263
12347
  }
12264
12348
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SliderContainerComponent, deps: [{ token: DragEngineService }, { token: i0.ChangeDetectorRef }, { token: IS_PREVIEW, optional: true }, { token: OverlayService, optional: true }, { token: BuilderDataSourceService, optional: true }, { token: DataSourceRegistryService, optional: true }, { token: PanelEventService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
12265
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: SliderContainerComponent, isStandalone: false, selector: "app-slider-container", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", dir: "dir", direction: "direction", slidesPerView: "slidesPerView", slidesPerGroup: "slidesPerGroup", loop: "loop", centeredSlides: "centeredSlides", spaceBetween: "spaceBetween", initialSlide: "initialSlide", autoHeight: "autoHeight", grabCursor: "grabCursor", slideToClickedSlide: "slideToClickedSlide", effect: "effect", speed: "speed", enableNavigation: "enableNavigation", navigationColor: "navigationColor", navigationSize: "navigationSize", enablePagination: "enablePagination", paginationColor: "paginationColor", paginationType: "paginationType", paginationClickable: "paginationClickable", paginationDynamicBullets: "paginationDynamicBullets", enableAutoplay: "enableAutoplay", autoplayDelay: "autoplayDelay", autoplayPauseOnMouseEnter: "autoplayPauseOnMouseEnter", autoplayDisableOnInteraction: "autoplayDisableOnInteraction", enableScrollbar: "enableScrollbar", freeMode: "freeMode", enableKeyboard: "enableKeyboard", enableMousewheel: "enableMousewheel", enableZoom: "enableZoom", enableParallax: "enableParallax", enableGrid: "enableGrid", gridRows: "gridRows", breakpoints: "breakpoints", source: "source", limit: "limit" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, viewQueries: [{ propertyName: "swiperEl", first: true, predicate: ["swiperEl"], descendants: true }, { propertyName: "editSwiperEl", first: true, predicate: ["editSwiperEl"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
12349
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: SliderContainerComponent, isStandalone: false, selector: "app-slider-container", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", dir: "dir", direction: "direction", slidesPerView: "slidesPerView", slidesPerGroup: "slidesPerGroup", loop: "loop", centeredSlides: "centeredSlides", spaceBetween: "spaceBetween", initialSlide: "initialSlide", autoHeight: "autoHeight", grabCursor: "grabCursor", slideToClickedSlide: "slideToClickedSlide", effect: "effect", speed: "speed", scrollPlays: "scrollPlays", enableNavigation: "enableNavigation", navigationColor: "navigationColor", navigationSize: "navigationSize", enablePagination: "enablePagination", paginationColor: "paginationColor", paginationType: "paginationType", paginationClickable: "paginationClickable", paginationDynamicBullets: "paginationDynamicBullets", enableAutoplay: "enableAutoplay", autoplayDelay: "autoplayDelay", autoplayPauseOnMouseEnter: "autoplayPauseOnMouseEnter", autoplayDisableOnInteraction: "autoplayDisableOnInteraction", enableScrollbar: "enableScrollbar", freeMode: "freeMode", enableKeyboard: "enableKeyboard", enableMousewheel: "enableMousewheel", enableZoom: "enableZoom", enableParallax: "enableParallax", enableGrid: "enableGrid", gridRows: "gridRows", breakpoints: "breakpoints", source: "source", limit: "limit" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, viewQueries: [{ propertyName: "runwayEl", first: true, predicate: ["runwayEl"], descendants: true, static: true }, { propertyName: "swiperEl", first: true, predicate: ["swiperEl"], descendants: true }, { propertyName: "editSwiperEl", first: true, predicate: ["editSwiperEl"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
12350
+ <!-- Premium M4: a slider the SCROLL plays sits in its runway — the Scene root the ONE scene driver drives (pinned
12351
+ with translate on the canvas, sticky in Preview). Otherwise the wrapper is display: contents. -->
12352
+ <div #runwayEl [class.iox-slider-runway]="scrollPlays" [attr.data-iox-scene]="scrollPlays ? '' : null"
12353
+ [style.display]="scrollPlays ? null : 'contents'">
12266
12354
  <!-- EDIT MODE: shell wraps swiper + nav buttons so arrows position relative to slide area -->
12267
12355
  <div *ngIf="!isPreview"
12268
12356
  class="slider-edit-shell"
@@ -12432,11 +12520,16 @@ class SliderContainerComponent {
12432
12520
  <div *ngIf="legacyControls && enablePagination" class="swiper-pagination"></div>
12433
12521
  <div *ngIf="enableScrollbar" class="swiper-scrollbar"></div>
12434
12522
  </div>
12523
+ </div>
12435
12524
  `, isInline: true, styles: [":host{display:block}.swiper-wrapper{height:auto}.slider-edit-shell{position:relative;display:block}.swiper-edit{width:100%}.swiper-edit .swiper-slide{position:relative}.slider-edit-nav{position:absolute;top:50%;transform:translateY(-50%);width:32px;height:32px;border-radius:50%;border:1px solid rgba(255,255,255,.5);background:#00000038;color:#fff;font-size:16px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:10;transition:background .15s}.slider-edit-nav:hover{background:#00000073}.slider-edit-nav--prev{left:8px}.slider-edit-nav--next{right:8px}.slider-edit-placeholder{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none}.slider-edit-placeholder i{font-size:22px}.slider-repeat-badge{position:absolute;top:0;left:0;z-index:10;display:flex;align-items:center;gap:.4rem;padding:4px 8px;font-size:11px;color:#cb9090;background:#cb909014;border:1px solid rgba(203,144,144,.5);border-radius:0 0 4px;opacity:0;transition:opacity .15s;-webkit-user-select:none;user-select:none;pointer-events:none}.slider-edit-shell:hover .slider-repeat-badge{opacity:1}.slider-repeat-badge-count{font-weight:600}.slider-badge-spin{animation:slider-badge-spin 1s linear infinite}@keyframes slider-badge-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.slider-preview-slide{opacity:.55;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId", "ioxPhrasing"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDraggableDirective, selector: "[ioxDraggable]", inputs: ["ioxDragData", "ioxDragSourceId", "ioxDragDisabled"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
12436
12525
  }
12437
12526
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SliderContainerComponent, decorators: [{
12438
12527
  type: Component,
12439
12528
  args: [{ selector: 'app-slider-container', template: `
12529
+ <!-- Premium M4: a slider the SCROLL plays sits in its runway — the Scene root the ONE scene driver drives (pinned
12530
+ with translate on the canvas, sticky in Preview). Otherwise the wrapper is display: contents. -->
12531
+ <div #runwayEl [class.iox-slider-runway]="scrollPlays" [attr.data-iox-scene]="scrollPlays ? '' : null"
12532
+ [style.display]="scrollPlays ? null : 'contents'">
12440
12533
  <!-- EDIT MODE: shell wraps swiper + nav buttons so arrows position relative to slide area -->
12441
12534
  <div *ngIf="!isPreview"
12442
12535
  class="slider-edit-shell"
@@ -12606,6 +12699,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
12606
12699
  <div *ngIf="legacyControls && enablePagination" class="swiper-pagination"></div>
12607
12700
  <div *ngIf="enableScrollbar" class="swiper-scrollbar"></div>
12608
12701
  </div>
12702
+ </div>
12609
12703
  `, standalone: false, styles: [":host{display:block}.swiper-wrapper{height:auto}.slider-edit-shell{position:relative;display:block}.swiper-edit{width:100%}.swiper-edit .swiper-slide{position:relative}.slider-edit-nav{position:absolute;top:50%;transform:translateY(-50%);width:32px;height:32px;border-radius:50%;border:1px solid rgba(255,255,255,.5);background:#00000038;color:#fff;font-size:16px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:10;transition:background .15s}.slider-edit-nav:hover{background:#00000073}.slider-edit-nav--prev{left:8px}.slider-edit-nav--next{right:8px}.slider-edit-placeholder{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none}.slider-edit-placeholder i{font-size:22px}.slider-repeat-badge{position:absolute;top:0;left:0;z-index:10;display:flex;align-items:center;gap:.4rem;padding:4px 8px;font-size:11px;color:#cb9090;background:#cb909014;border:1px solid rgba(203,144,144,.5);border-radius:0 0 4px;opacity:0;transition:opacity .15s;-webkit-user-select:none;user-select:none;pointer-events:none}.slider-edit-shell:hover .slider-repeat-badge{opacity:1}.slider-repeat-badge-count{font-weight:600}.slider-badge-spin{animation:slider-badge-spin 1s linear infinite}@keyframes slider-badge-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.slider-preview-slide{opacity:.55;pointer-events:none}\n"] }]
12610
12704
  }], ctorParameters: () => [{ type: DragEngineService }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
12611
12705
  type: Optional
@@ -12654,6 +12748,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
12654
12748
  type: Input
12655
12749
  }], speed: [{
12656
12750
  type: Input
12751
+ }], scrollPlays: [{
12752
+ type: Input
12657
12753
  }], enableNavigation: [{
12658
12754
  type: Input
12659
12755
  }], navigationColor: [{
@@ -12706,6 +12802,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
12706
12802
  type: Output
12707
12803
  }], childMouseLeave: [{
12708
12804
  type: Output
12805
+ }], runwayEl: [{
12806
+ type: ViewChild,
12807
+ args: ['runwayEl', { static: true }]
12709
12808
  }], swiperEl: [{
12710
12809
  type: ViewChild,
12711
12810
  args: ['swiperEl', { static: false }]
@@ -14156,6 +14255,7 @@ class BuilderContainerComponentConfig extends ComponentConfig {
14156
14255
  new TraitConfig('htmlTag', 'HTML Tag', TraitInputType.Select, ['div', 'section', 'article', 'header', 'footer', 'main', 'nav', 'ul', 'ol', 'li'], 'div'),
14157
14256
  buildColorSchemeTrait(),
14158
14257
  ...buildCompositeBehaviourTraits(),
14258
+ ...buildHeaderBehaviourTraits(),
14159
14259
  ];
14160
14260
  this.styleTraits = buildFullStyleTraits();
14161
14261
  this.applyStyleDefaults({
@@ -14815,7 +14915,10 @@ class SliderSlideConfig extends ComponentConfig {
14815
14915
  { value: 'swiperSlideActive', label: 'This Slide Becomes Active', icon: 'ph-thin ph-eye' },
14816
14916
  { value: 'swiperSlideInactive', label: 'This Slide Becomes Inactive', icon: 'ph-thin ph-eye-slash' },
14817
14917
  ];
14818
- this.traits = [];
14918
+ // Premium M4 (M1.3): the words the Slider's Caption part shows while this slide is in view (bindable per row).
14919
+ this.traits = [
14920
+ new TraitConfig(SLIDE_CAPTION_TRAIT, 'Caption', TraitInputType.Text, undefined, ''),
14921
+ ];
14819
14922
  this.styleTraits = [
14820
14923
  new PositionGroupStyleConfig(),
14821
14924
  new LayoutGroupStyleConfig(),
@@ -14906,8 +15009,16 @@ class SliderContainerConfig extends ComponentConfig {
14906
15009
  { label: 'Creative', value: 'creative' },
14907
15010
  ], 'slide'),
14908
15011
  new TraitConfig('speed', 'Transition duration (ms)', TraitInputType.Scrub, undefined, 300),
15012
+ // Premium M4: the page's scroll plays it — held mid-screen, resting on each picture (laptop and phone).
15013
+ new TraitConfig(SLIDER_SCROLL_PLAYS_TRAIT, 'Scroll plays it', TraitInputType.Checkbox, undefined, false),
14909
15014
  // ── Navigation ────────────────────────────────────────────────────
14910
15015
  new TraitConfig('__navLabel', 'Navigation', TraitInputType.SectionLabel),
15016
+ // Premium M4 (M1.3): where the controls sit — in a bar UNDER the picture (caption · count · arrows, the new
15017
+ // Slider's default) or over it (every slider saved before M4). Once a slider has controls, its structure
15018
+ // decides (composite-core sliderPlacementOf); changing it moves the same parts (setSliderPlacement).
15019
+ new TraitConfig(SLIDER_PLACEMENT_TRAIT, 'Controls', TraitInputType.SelectButton, [{ label: 'Under the picture', value: SliderPlacement.Under }, { label: 'Over the picture', value: SliderPlacement.Over }], SliderPlacement.Under),
15020
+ new TraitConfig(SliderFlag.Caption, 'Caption', TraitInputType.Checkbox, undefined, false, undefined, { trait: SLIDER_PLACEMENT_TRAIT, values: SliderPlacement.Under }),
15021
+ new TraitConfig(SliderFlag.Count, 'Count (1 / 3)', TraitInputType.Checkbox, undefined, false, undefined, { trait: SLIDER_PLACEMENT_TRAIT, values: SliderPlacement.Under }),
14911
15022
  new TraitConfig('enableNavigation', 'Navigation arrows', TraitInputType.Checkbox, undefined, false),
14912
15023
  new TraitConfig('navigationColor', 'Color', TraitInputType.Color, undefined, '#ffffff', undefined, { trait: 'enableNavigation', values: 'true' }),
14913
15024
  new TraitConfig('navigationSize', 'Size (px)', TraitInputType.Scrub, undefined, 44, undefined, { trait: 'enableNavigation', values: 'true' }),