@vectoriox/iox-builder 1.9.2 → 2.0.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.
|
@@ -12,18 +12,19 @@ import { ButtonModule } from 'primeng/button';
|
|
|
12
12
|
import * as i2$1 from 'primeng/popover';
|
|
13
13
|
import { PopoverModule } from 'primeng/popover';
|
|
14
14
|
import { InputTextModule } from 'primeng/inputtext';
|
|
15
|
-
import * as i5
|
|
15
|
+
import * as i5 from 'primeng/select';
|
|
16
16
|
import { SelectModule } from 'primeng/select';
|
|
17
17
|
import { TooltipModule } from 'primeng/tooltip';
|
|
18
18
|
import { DialogModule } from 'primeng/dialog';
|
|
19
19
|
import * as i15 from '@vectoriox/iox-ui';
|
|
20
|
-
import { ComponentInstanceRegistryService, DEFAULT_WIDTH_BY_TYPE, compileDeclarations, composeVirtualTraits, IS_PREVIEW, IoxPageModule } from '@vectoriox/iox-ui';
|
|
20
|
+
import { ComponentInstanceRegistryService, DEFAULT_WIDTH_BY_TYPE, compileDeclarations, composeVirtualTraits, IS_PREVIEW, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, IoxPageModule } from '@vectoriox/iox-ui';
|
|
21
21
|
export { ComponentInstanceRegistryService, VIRTUAL_TRAIT_KEYS, composeVirtualTraits } from '@vectoriox/iox-ui';
|
|
22
22
|
import Lenis from 'lenis';
|
|
23
|
-
import { Subject, BehaviorSubject } from 'rxjs';
|
|
23
|
+
import { Subject, BehaviorSubject, of } from 'rxjs';
|
|
24
24
|
import interact from 'interactjs';
|
|
25
25
|
import Moveable from 'moveable';
|
|
26
|
-
import
|
|
26
|
+
import { map, catchError } from 'rxjs/operators';
|
|
27
|
+
import * as i1 from '@angular/common/http';
|
|
27
28
|
|
|
28
29
|
var PanelEventTypes;
|
|
29
30
|
(function (PanelEventTypes) {
|
|
@@ -5404,13 +5405,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
5404
5405
|
type: Output
|
|
5405
5406
|
}] } });
|
|
5406
5407
|
|
|
5407
|
-
/** Optional CMS content fetcher. Provide from the host app to enable Repeater data preview. */
|
|
5408
|
-
const IOX_CONTENT_SERVICE = new InjectionToken('IOX_CONTENT_SERVICE');
|
|
5409
|
-
/** Optional shop content fetcher. Provide from the host app to enable Repeater shop data preview. */
|
|
5410
|
-
const IOX_SHOP_SERVICE = new InjectionToken('IOX_SHOP_SERVICE');
|
|
5411
|
-
/** Optional font manager. Provide from the host app to populate the fontFamily dropdown. */
|
|
5412
|
-
const IOX_FONT_MANAGER = new InjectionToken('IOX_FONT_MANAGER');
|
|
5413
|
-
|
|
5414
5408
|
/**
|
|
5415
5409
|
* Resolves a dot-notation path (with optional array bracket notation) against an object.
|
|
5416
5410
|
* Examples: 'title', 'author.name', 'tags[0]', 'items[2].title'
|
|
@@ -5467,6 +5461,76 @@ function cloneNodesForItem(nodes, item) {
|
|
|
5467
5461
|
});
|
|
5468
5462
|
}
|
|
5469
5463
|
|
|
5464
|
+
/**
|
|
5465
|
+
* Public content bases the builder canvas resolves data against — the SAME `@Public()` controllers
|
|
5466
|
+
* the live storefront (SSR engine) hits, so the canvas preview shows what the published page shows.
|
|
5467
|
+
* Provide from the host app, e.g. `{ cmsBase: config.host + 'api/', shopBase: config.host + 'api/shop/' }`.
|
|
5468
|
+
*/
|
|
5469
|
+
const IOX_DATA_SOURCE_ENDPOINTS = new InjectionToken('IOX_DATA_SOURCE_ENDPOINTS');
|
|
5470
|
+
/**
|
|
5471
|
+
* THE data fetch for every canvas component that renders a data source (Repeater, SliderContainer)
|
|
5472
|
+
* and for the bindings preview.
|
|
5473
|
+
*
|
|
5474
|
+
* Before this existed, each of those fetched by itself through an injected admin content service
|
|
5475
|
+
* (`getContent(contentType, orgId)` → `api/org/:orgId/resources/:type`), which takes NO filters:
|
|
5476
|
+
* the data source's `filterByQueryParams` / `filterByRouteParam` were silently ignored, so the
|
|
5477
|
+
* canvas always showed the whole unfiltered collection, and the live SSR site — which does apply
|
|
5478
|
+
* them — rendered something different. Every caller now runs the SHARED `planDataSource` from
|
|
5479
|
+
* `@vectoriox/iox-ui` against the public controllers, exactly like the SSR engine.
|
|
5480
|
+
*/
|
|
5481
|
+
class BuilderDataSourceService {
|
|
5482
|
+
constructor(http, endpoints) {
|
|
5483
|
+
this.http = http;
|
|
5484
|
+
this.endpoints = endpoints;
|
|
5485
|
+
}
|
|
5486
|
+
/** True when the host app wired the public endpoints — without them nothing can be fetched. */
|
|
5487
|
+
get isConfigured() { return !!this.endpoints; }
|
|
5488
|
+
/**
|
|
5489
|
+
* Resolve a data source to the value its MODE describes: the item for a `single` source, the
|
|
5490
|
+
* array for a `list`. The builder is design time — there are no live route or query params — so
|
|
5491
|
+
* a route filter falls back to `defaultId` and a query filter to its `defaultValue`, which is
|
|
5492
|
+
* exactly what `planDataSource` does with empty params.
|
|
5493
|
+
*
|
|
5494
|
+
* Callers pass the source itself (resolved from their own page-scoped
|
|
5495
|
+
* `DataSourceRegistryService`) rather than an alias: this service is module-scoped and must not
|
|
5496
|
+
* capture a registry from the wrong injector. Emits `null` when the source resolves to no
|
|
5497
|
+
* request or the fetch fails — the canvas degrades to an empty preview, it never throws.
|
|
5498
|
+
*/
|
|
5499
|
+
fetch(ds) {
|
|
5500
|
+
if (!ds)
|
|
5501
|
+
return of(null);
|
|
5502
|
+
const plan = planDataSource(ds);
|
|
5503
|
+
if (plan.kind === 'static')
|
|
5504
|
+
return of(plan.data);
|
|
5505
|
+
if (plan.kind === 'none' || !this.endpoints)
|
|
5506
|
+
return of(null);
|
|
5507
|
+
const request = dataSourcePlanToRequest(plan, this.endpoints);
|
|
5508
|
+
if (!request)
|
|
5509
|
+
return of(null);
|
|
5510
|
+
const { kind, mode } = plan;
|
|
5511
|
+
return this.http.get(request.url, { params: request.params }).pipe(
|
|
5512
|
+
// A by-id response is already the item; anything else goes through the shared
|
|
5513
|
+
// unwrap-and-pick so `single` yields one item and `list` the whole array.
|
|
5514
|
+
map((data) => kind === 'by-id'
|
|
5515
|
+
? (Array.isArray(data) ? (data[0] ?? null) : data)
|
|
5516
|
+
: normalizeCollectionResult(mode, data)), catchError(() => of(null)));
|
|
5517
|
+
}
|
|
5518
|
+
/** Same fetch, always as an array — for the canvas components that repeat over the source. */
|
|
5519
|
+
fetchItems(ds) {
|
|
5520
|
+
return this.fetch(ds).pipe(map(value => Array.isArray(value) ? value : (value === null || value === undefined ? [] : [value])));
|
|
5521
|
+
}
|
|
5522
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderDataSourceService, deps: [{ token: i1.HttpClient }, { token: IOX_DATA_SOURCE_ENDPOINTS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5523
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderDataSourceService }); }
|
|
5524
|
+
}
|
|
5525
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderDataSourceService, decorators: [{
|
|
5526
|
+
type: Injectable
|
|
5527
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
|
|
5528
|
+
type: Optional
|
|
5529
|
+
}, {
|
|
5530
|
+
type: Inject,
|
|
5531
|
+
args: [IOX_DATA_SOURCE_ENDPOINTS]
|
|
5532
|
+
}] }] });
|
|
5533
|
+
|
|
5470
5534
|
class BuilderRepeaterComponent {
|
|
5471
5535
|
get source() { return this._source; }
|
|
5472
5536
|
set source(value) {
|
|
@@ -5490,14 +5554,12 @@ class BuilderRepeaterComponent {
|
|
|
5490
5554
|
this.fetchData();
|
|
5491
5555
|
}
|
|
5492
5556
|
}
|
|
5493
|
-
constructor(dragEngine, overlayService,
|
|
5557
|
+
constructor(dragEngine, overlayService, dataSourceService, dsRegistry, panelEventService, cdr) {
|
|
5494
5558
|
this.dragEngine = dragEngine;
|
|
5495
5559
|
this.overlayService = overlayService;
|
|
5496
|
-
this.
|
|
5497
|
-
this.shopContentService = shopContentService;
|
|
5560
|
+
this.dataSourceService = dataSourceService;
|
|
5498
5561
|
this.dsRegistry = dsRegistry;
|
|
5499
5562
|
this.panelEventService = panelEventService;
|
|
5500
|
-
this.activatedRoute = activatedRoute;
|
|
5501
5563
|
this.cdr = cdr;
|
|
5502
5564
|
this.children = [];
|
|
5503
5565
|
this.style = {};
|
|
@@ -5513,10 +5575,8 @@ class BuilderRepeaterComponent {
|
|
|
5513
5575
|
this.refreshPreviewsBound = () => { setTimeout(() => this.refreshPreviews()); };
|
|
5514
5576
|
this._source = '';
|
|
5515
5577
|
this._limit = 10;
|
|
5516
|
-
this.orgId = 'default';
|
|
5517
5578
|
}
|
|
5518
5579
|
ngOnInit() {
|
|
5519
|
-
this.orgId = this.activatedRoute.snapshot.paramMap.get('orgId') || 'default';
|
|
5520
5580
|
this.bindingSub = this.panelEventService.subscribe(event => {
|
|
5521
5581
|
if (event.type !== PanelEventTypes.BINDING_CHANGED)
|
|
5522
5582
|
return;
|
|
@@ -5535,29 +5595,18 @@ class BuilderRepeaterComponent {
|
|
|
5535
5595
|
this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr, () => { if (this.items.length > 0)
|
|
5536
5596
|
setTimeout(() => this.refreshPreviews()); });
|
|
5537
5597
|
}
|
|
5598
|
+
/** Data comes from the SHARED resolver (public controllers + the source's own filters) — the
|
|
5599
|
+
* same decision the SSR engine runs, so the canvas preview matches the published page. */
|
|
5538
5600
|
fetchData() {
|
|
5539
5601
|
if (!this._source)
|
|
5540
5602
|
return;
|
|
5541
|
-
const ds = this.dsRegistry.findByAlias(this._source);
|
|
5542
|
-
const isShop = ds?.type === DataSourceType.Shop;
|
|
5543
|
-
const contentType = isShop ? ds?.request?.shop?.contentType : ds?.request?.cms?.contentType;
|
|
5544
|
-
const service = isShop ? this.shopContentService : this.contentService;
|
|
5545
|
-
if (!contentType || !service)
|
|
5546
|
-
return;
|
|
5547
5603
|
this.isLoading = true;
|
|
5548
5604
|
this.cdr.markForCheck();
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
this.isLoading = false;
|
|
5555
|
-
this.cdr.markForCheck();
|
|
5556
|
-
},
|
|
5557
|
-
error: () => {
|
|
5558
|
-
this.isLoading = false;
|
|
5559
|
-
this.cdr.markForCheck();
|
|
5560
|
-
}
|
|
5605
|
+
this.dataSourceService.fetchItems(this.dsRegistry.findByAlias(this._source)).subscribe(items => {
|
|
5606
|
+
this.items = items.slice(0, this._limit);
|
|
5607
|
+
this.refreshPreviews();
|
|
5608
|
+
this.isLoading = false;
|
|
5609
|
+
this.cdr.markForCheck();
|
|
5561
5610
|
});
|
|
5562
5611
|
}
|
|
5563
5612
|
isInTemplate(target) {
|
|
@@ -5594,7 +5643,7 @@ class BuilderRepeaterComponent {
|
|
|
5594
5643
|
ref.componentRef.changeDetectorRef.detectChanges();
|
|
5595
5644
|
}
|
|
5596
5645
|
}
|
|
5597
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderRepeaterComponent, deps: [{ token: DragEngineService }, { token: OverlayService }, { token:
|
|
5646
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderRepeaterComponent, deps: [{ token: DragEngineService }, { token: OverlayService }, { token: BuilderDataSourceService }, { token: DataSourceRegistryService }, { token: PanelEventService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5598
5647
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: BuilderRepeaterComponent, isStandalone: false, selector: "app-builder-repeater", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", source: "source", limit: "limit" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
|
|
5599
5648
|
<ng-template #badgeContent>
|
|
5600
5649
|
<i class="ph-thin ph-repeat"></i>
|
|
@@ -5748,17 +5797,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
5748
5797
|
</div>
|
|
5749
5798
|
</div>
|
|
5750
5799
|
`, standalone: false, styles: [".repeater-wrapper{position:relative;box-sizing:border-box}.repeater-badge{display:flex;align-items:center;gap:.4rem;padding:4px 8px;font-size:11px;color:#cb9090;background:#cb909014;border:1px dashed rgba(203,144,144,.4);border-bottom:none;border-radius:4px 4px 0 0;-webkit-user-select:none;user-select:none}.repeater-wrapper.has-children>.repeater-badge{position:absolute;top:0;left:0;z-index:10;border-radius:0 0 4px;border:1px solid rgba(203,144,144,.5);opacity:0;cursor:pointer;transition:opacity .15s}.repeater-wrapper.has-children:hover>.repeater-badge{opacity:1}.repeater-badge i{font-size:13px}.repeater-badge-empty{opacity:.55}.repeater-badge-count{margin-left:auto;font-weight:600}.repeater-badge-loading i{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.repeater-root{box-sizing:border-box}.repeater-wrapper:not(.has-children) .repeater-root{border:1px dashed rgba(203,144,144,.4);border-top:none;border-radius:0 0 4px 4px;min-height:40px}.repeater-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1.5rem 1rem;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none}.repeater-placeholder i{font-size:20px}.repeater-item-template{min-width:0}.repeater-preview-child{opacity:.55;pointer-events:none;min-width:0}\n"] }]
|
|
5751
|
-
}], ctorParameters: () => [{ type: DragEngineService }, { type: OverlayService }, { type:
|
|
5752
|
-
type: Optional
|
|
5753
|
-
}, {
|
|
5754
|
-
type: Inject,
|
|
5755
|
-
args: [IOX_CONTENT_SERVICE]
|
|
5756
|
-
}] }, { type: undefined, decorators: [{
|
|
5757
|
-
type: Optional
|
|
5758
|
-
}, {
|
|
5759
|
-
type: Inject,
|
|
5760
|
-
args: [IOX_SHOP_SERVICE]
|
|
5761
|
-
}] }, { type: DataSourceRegistryService }, { type: PanelEventService }, { type: i5.ActivatedRoute }, { type: i0.ChangeDetectorRef }], propDecorators: { children: [{
|
|
5800
|
+
}], ctorParameters: () => [{ type: DragEngineService }, { type: OverlayService }, { type: BuilderDataSourceService }, { type: DataSourceRegistryService }, { type: PanelEventService }, { type: i0.ChangeDetectorRef }], propDecorators: { children: [{
|
|
5762
5801
|
type: Input
|
|
5763
5802
|
}], style: [{
|
|
5764
5803
|
type: Input
|
|
@@ -5918,16 +5957,14 @@ class SliderContainerComponent {
|
|
|
5918
5957
|
this.fetchData();
|
|
5919
5958
|
}
|
|
5920
5959
|
}
|
|
5921
|
-
constructor(dragEngine, cdr, isPreview, overlayService,
|
|
5960
|
+
constructor(dragEngine, cdr, isPreview, overlayService, dataSourceService, dsRegistry, panelEventService) {
|
|
5922
5961
|
this.dragEngine = dragEngine;
|
|
5923
5962
|
this.cdr = cdr;
|
|
5924
5963
|
this.isPreview = isPreview;
|
|
5925
5964
|
this.overlayService = overlayService;
|
|
5926
|
-
this.
|
|
5927
|
-
this.shopContentService = shopContentService;
|
|
5965
|
+
this.dataSourceService = dataSourceService;
|
|
5928
5966
|
this.dsRegistry = dsRegistry;
|
|
5929
5967
|
this.panelEventService = panelEventService;
|
|
5930
|
-
this.activatedRoute = activatedRoute;
|
|
5931
5968
|
this.children = [];
|
|
5932
5969
|
this._style = {};
|
|
5933
5970
|
this._previewStyle = {};
|
|
@@ -5988,14 +6025,12 @@ class SliderContainerComponent {
|
|
|
5988
6025
|
this.childMouseLeave = new EventEmitter();
|
|
5989
6026
|
this._swiper = null;
|
|
5990
6027
|
this._initRafId = 0;
|
|
5991
|
-
this._orgId = 'default';
|
|
5992
6028
|
this.instanceRegistry = inject(ComponentInstanceRegistryService);
|
|
5993
6029
|
this.interactionEngine = inject(InteractionEngineService);
|
|
5994
6030
|
this.ngZone = inject(NgZone);
|
|
5995
6031
|
this.isPreview = !!isPreview;
|
|
5996
6032
|
}
|
|
5997
6033
|
ngOnInit() {
|
|
5998
|
-
this._orgId = this.activatedRoute?.snapshot.paramMap.get('orgId') || 'default';
|
|
5999
6034
|
if (this.panelEventService) {
|
|
6000
6035
|
this._bindingSub = this.panelEventService.subscribe(event => {
|
|
6001
6036
|
if (event.type !== PanelEventTypes.BINDING_CHANGED)
|
|
@@ -6066,29 +6101,18 @@ class SliderContainerComponent {
|
|
|
6066
6101
|
}
|
|
6067
6102
|
}
|
|
6068
6103
|
// ── Data fetching ───────────────────────────────────────────────────────────
|
|
6104
|
+
/** Slides come from the SHARED resolver (public controllers + the source's own filters) — the
|
|
6105
|
+
* same decision the SSR engine runs, so the canvas preview matches the published page. */
|
|
6069
6106
|
fetchData() {
|
|
6070
|
-
if (!this._source || !this.dsRegistry)
|
|
6071
|
-
return;
|
|
6072
|
-
const ds = this.dsRegistry.findByAlias(this._source);
|
|
6073
|
-
const isShop = ds?.type === DataSourceType.Shop;
|
|
6074
|
-
const contentType = isShop ? ds?.request?.shop?.contentType : ds?.request?.cms?.contentType;
|
|
6075
|
-
const service = isShop ? this.shopContentService : this.contentService;
|
|
6076
|
-
if (!contentType || !service)
|
|
6107
|
+
if (!this._source || !this.dataSourceService || !this.dsRegistry)
|
|
6077
6108
|
return;
|
|
6078
6109
|
this.isLoading = true;
|
|
6079
6110
|
this.cdr.markForCheck();
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
this.isLoading = false;
|
|
6086
|
-
this.cdr.markForCheck();
|
|
6087
|
-
},
|
|
6088
|
-
error: () => {
|
|
6089
|
-
this.isLoading = false;
|
|
6090
|
-
this.cdr.markForCheck();
|
|
6091
|
-
},
|
|
6111
|
+
this.dataSourceService.fetchItems(this.dsRegistry.findByAlias(this._source)).subscribe(items => {
|
|
6112
|
+
this.items = items.slice(0, this._limit);
|
|
6113
|
+
this.refreshPreviews();
|
|
6114
|
+
this.isLoading = false;
|
|
6115
|
+
this.cdr.markForCheck();
|
|
6092
6116
|
});
|
|
6093
6117
|
}
|
|
6094
6118
|
refreshPreviews() {
|
|
@@ -6284,7 +6308,7 @@ class SliderContainerComponent {
|
|
|
6284
6308
|
}
|
|
6285
6309
|
}
|
|
6286
6310
|
}
|
|
6287
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SliderContainerComponent, deps: [{ token: DragEngineService }, { token: i0.ChangeDetectorRef }, { token: IS_PREVIEW, optional: true }, { token: OverlayService, optional: true }, { token:
|
|
6311
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", 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 }); }
|
|
6288
6312
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", 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: `
|
|
6289
6313
|
<!-- EDIT MODE: shell wraps swiper + nav buttons so arrows position relative to slide area -->
|
|
6290
6314
|
<div *ngIf="!isPreview"
|
|
@@ -6591,22 +6615,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
6591
6615
|
args: [IS_PREVIEW]
|
|
6592
6616
|
}] }, { type: OverlayService, decorators: [{
|
|
6593
6617
|
type: Optional
|
|
6594
|
-
}] }, { type:
|
|
6595
|
-
type: Optional
|
|
6596
|
-
}, {
|
|
6597
|
-
type: Inject,
|
|
6598
|
-
args: [IOX_CONTENT_SERVICE]
|
|
6599
|
-
}] }, { type: undefined, decorators: [{
|
|
6618
|
+
}] }, { type: BuilderDataSourceService, decorators: [{
|
|
6600
6619
|
type: Optional
|
|
6601
|
-
}, {
|
|
6602
|
-
type: Inject,
|
|
6603
|
-
args: [IOX_SHOP_SERVICE]
|
|
6604
6620
|
}] }, { type: DataSourceRegistryService, decorators: [{
|
|
6605
6621
|
type: Optional
|
|
6606
6622
|
}] }, { type: PanelEventService, decorators: [{
|
|
6607
6623
|
type: Optional
|
|
6608
|
-
}] }, { type: i5.ActivatedRoute, decorators: [{
|
|
6609
|
-
type: Optional
|
|
6610
6624
|
}] }], propDecorators: { children: [{
|
|
6611
6625
|
type: Input
|
|
6612
6626
|
}], style: [{
|
|
@@ -7146,7 +7160,7 @@ class InteractionsPanelComponent {
|
|
|
7146
7160
|
}
|
|
7147
7161
|
}
|
|
7148
7162
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: InteractionsPanelComponent, deps: [{ token: OverlayService }, { token: ComponentRegistryService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7149
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: InteractionsPanelComponent, isStandalone: false, selector: "app-interactions-panel", inputs: { node: "node" }, ngImport: i0, template: "<div class=\"interactions-panel\">\n <!-- No element selected -->\n <div *ngIf=\"!node\" class=\"section-empty\">\n Select an element to manage interactions\n </div>\n\n <ng-container *ngIf=\"node\">\n <!-- Interaction cards -->\n <div *ngFor=\"let ix of interactions\" class=\"ix-card\" [class.is-expanded]=\"expandedId === ix.id\">\n <!-- Summary row -->\n <div class=\"ix-card-header\" (click)=\"toggleExpand(ix.id)\">\n <i [class]=\"getTriggerIcon(ix.trigger)\" class=\"ix-trigger-icon\"></i>\n <div class=\"ix-card-summary\">\n <span class=\"ix-trigger-label\">{{ getTriggerLabel(ix.trigger) }}</span>\n <span class=\"ix-arrow\">\u2192</span>\n <span class=\"ix-action-label\">{{ getActionsSummary(ix) }}</span>\n </div>\n <button class=\"ix-remove-btn\" title=\"Remove\" (click)=\"removeInteraction(ix.id); $event.stopPropagation()\">\n <i class=\"ph-thin ph-x\"></i>\n </button>\n </div>\n\n <!-- Expanded detail -->\n <div *ngIf=\"expandedId === ix.id\" class=\"ix-card-body\">\n <div class=\"ix-field\">\n <label>Trigger</label>\n <select [(ngModel)]=\"ix.trigger\">\n <option *ngFor=\"let t of triggerOptions\" [value]=\"t.value\">{{ t.label }}</option>\n </select>\n </div>\n\n <div *ngFor=\"let action of ix.actions; let ai = index\" class=\"ix-action-row\">\n <div class=\"ix-action-header\">\n <span class=\"ix-action-index\">\n Target {{ ai + 1 }}\n <span *ngIf=\"ix.actions.length > 1\" class=\"ix-action-target-badge\">\n \u2192 {{ getTargetLabel(action.target) }}\n </span>\n </span>\n <button *ngIf=\"ix.actions.length > 1\"\n class=\"ix-remove-btn small\"\n title=\"Remove action\"\n (click)=\"removeAction(ix, ai)\">\n <i class=\"ph-thin ph-x\"></i>\n </button>\n </div>\n\n <div class=\"ix-field\">\n <label>Type</label>\n <select [(ngModel)]=\"action.type\">\n <option *ngFor=\"let a of actionTypeOptions\" [value]=\"a.value\">{{ a.label }}</option>\n </select>\n </div>\n\n <div class=\"ix-field\">\n <label>Target</label>\n <p-select\n [(ngModel)]=\"action.target\"\n [options]=\"nodeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [filter]=\"true\"\n filterPlaceholder=\"Search\u2026\"\n styleClass=\"ix-target-select\"\n appendTo=\"body\">\n </p-select>\n <span *ngIf=\"nodeOptions.length === 1\" class=\"ix-target-hint\">\n Name elements in the Layers panel to target them\n </span>\n </div>\n\n <div class=\"ix-field-row\">\n <div class=\"ix-field\">\n <label>Duration (ms)</label>\n <input type=\"number\" [(ngModel)]=\"action.duration\" min=\"0\" step=\"50\">\n </div>\n <div class=\"ix-field\">\n <label>Delay (ms)</label>\n <input type=\"number\" [(ngModel)]=\"action.delay\" min=\"0\" step=\"50\">\n </div>\n </div>\n\n <div class=\"ix-field\">\n <label>Easing</label>\n <select [(ngModel)]=\"action.easing\">\n <option *ngFor=\"let e of easingOptions\" [value]=\"e\">{{ e }}</option>\n </select>\n </div>\n\n <div class=\"ix-field ix-checkbox-field\">\n <label>\n <input type=\"checkbox\" [(ngModel)]=\"action.once\">\n Play once\n </label>\n </div>\n </div>\n\n <button class=\"ix-add-action-btn\" (click)=\"addAction(ix)\">\n <i class=\"ph-thin ph-plus\"></i> Add target\n </button>\n\n <!-- Toggle section (click only) -->\n <ng-container *ngIf=\"ix.trigger === 'click'\">\n <div class=\"ix-toggle-header\">\n <span class=\"ix-toggle-label\">\n <i class=\"ph-thin ph-arrows-clockwise\"></i> 2nd click\n </span>\n <label class=\"ix-toggle-switch\">\n <input type=\"checkbox\"\n [checked]=\"hasToggle(ix)\"\n (change)=\"hasToggle(ix) ? disableToggle(ix) : enableToggle(ix)\">\n <span class=\"ix-toggle-track\"></span>\n </label>\n </div>\n\n <ng-container *ngIf=\"hasToggle(ix)\">\n <div *ngFor=\"let ra of ix.reverseActions; let ri = index\" class=\"ix-action-row ix-action-row--reverse\">\n <div class=\"ix-action-header\">\n <span class=\"ix-action-index\">\n Target {{ ri + 1 }}\n <span *ngIf=\"(ix.reverseActions?.length ?? 0) > 1\" class=\"ix-action-target-badge\">\n \u2192 {{ getTargetLabel(ra.target) }}\n </span>\n </span>\n <button *ngIf=\"(ix.reverseActions?.length ?? 0) > 1\"\n class=\"ix-remove-btn small\"\n title=\"Remove\"\n (click)=\"removeReverseAction(ix, ri)\">\n <i class=\"ph-thin ph-x\"></i>\n </button>\n </div>\n\n <div class=\"ix-field\">\n <label>Type</label>\n <select [(ngModel)]=\"ra.type\">\n <option *ngFor=\"let a of actionTypeOptions\" [value]=\"a.value\">{{ a.label }}</option>\n </select>\n </div>\n\n <div class=\"ix-field\">\n <label>Target</label>\n <p-select\n [(ngModel)]=\"ra.target\"\n [options]=\"nodeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [filter]=\"true\"\n filterPlaceholder=\"Search\u2026\"\n styleClass=\"ix-target-select\"\n appendTo=\"body\">\n </p-select>\n </div>\n\n <div class=\"ix-field-row\">\n <div class=\"ix-field\">\n <label>Duration (ms)</label>\n <input type=\"number\" [(ngModel)]=\"ra.duration\" min=\"0\" step=\"50\">\n </div>\n <div class=\"ix-field\">\n <label>Delay (ms)</label>\n <input type=\"number\" [(ngModel)]=\"ra.delay\" min=\"0\" step=\"50\">\n </div>\n </div>\n\n <div class=\"ix-field\">\n <label>Easing</label>\n <select [(ngModel)]=\"ra.easing\">\n <option *ngFor=\"let e of easingOptions\" [value]=\"e\">{{ e }}</option>\n </select>\n </div>\n </div>\n\n <button class=\"ix-add-action-btn\" (click)=\"addReverseAction(ix)\">\n <i class=\"ph-thin ph-plus\"></i> Add target\n </button>\n </ng-container>\n </ng-container>\n </div>\n </div>\n\n <!-- Add interaction form -->\n <div *ngIf=\"isAdding\" class=\"ix-add-form\">\n <div class=\"ix-field\">\n <label>Trigger</label>\n <select [(ngModel)]=\"newTrigger\">\n <option *ngFor=\"let t of triggerOptions\" [value]=\"t.value\">{{ t.label }}</option>\n </select>\n </div>\n <div class=\"ix-field\">\n <label>Action</label>\n <select [(ngModel)]=\"newActionType\">\n <option *ngFor=\"let a of actionTypeOptions\" [value]=\"a.value\">{{ a.label }}</option>\n </select>\n </div>\n <div class=\"ix-field\">\n <label>Target</label>\n <p-select\n [(ngModel)]=\"newTarget\"\n [options]=\"nodeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [filter]=\"true\"\n filterPlaceholder=\"Search\u2026\"\n styleClass=\"ix-target-select\"\n appendTo=\"body\">\n </p-select>\n <span *ngIf=\"nodeOptions.length === 1\" class=\"ix-target-hint\">\n Name elements in the Layers panel to target them\n </span>\n </div>\n <div *ngIf=\"isSwiperGoToSlide\" class=\"ix-field\">\n <label>Slide index (0-based)</label>\n <input type=\"number\" [(ngModel)]=\"newSlideIndex\" min=\"0\" step=\"1\">\n </div>\n <div *ngIf=\"!isSwiperAction\" class=\"ix-field-row\">\n <div class=\"ix-field\">\n <label>Duration (ms)</label>\n <input type=\"number\" [(ngModel)]=\"newDuration\" min=\"0\" step=\"50\">\n </div>\n <div class=\"ix-field\">\n <label>Delay (ms)</label>\n <input type=\"number\" [(ngModel)]=\"newDelay\" min=\"0\" step=\"50\">\n </div>\n </div>\n <div class=\"ix-field\">\n <label>Easing</label>\n <select [(ngModel)]=\"newEasing\">\n <option *ngFor=\"let e of easingOptions\" [value]=\"e\">{{ e }}</option>\n </select>\n </div>\n <div class=\"ix-field ix-checkbox-field\">\n <label>\n <input type=\"checkbox\" [(ngModel)]=\"newOnce\">\n Play once\n </label>\n </div>\n <div class=\"ix-form-actions\">\n <button class=\"ix-btn ix-btn--secondary\" (click)=\"cancelAdd()\">Cancel</button>\n <button class=\"ix-btn ix-btn--primary\" (click)=\"confirmAdd()\">Add</button>\n </div>\n </div>\n\n <!-- Add button -->\n <button *ngIf=\"!isAdding\" class=\"ix-add-btn\" (click)=\"startAdd()\">\n <i class=\"ph-thin ph-plus\"></i> Add interaction\n </button>\n </ng-container>\n</div>\n", styles: [".interactions-panel{padding:.5rem}.section-empty{color:var(--p-text-muted-color);font-size:12px;text-align:center;padding:1rem}.ix-card{border:1px solid var(--p-surface-200);border-radius:8px;margin-bottom:6px;overflow:hidden;transition:border-color .15s}.ix-card.is-expanded{border-color:#cb9090}.ix-card-header{display:flex;align-items:center;gap:8px;padding:8px 10px;cursor:pointer;font-size:12px;transition:background .12s}.ix-card-header:hover{background:var(--p-surface-50)}.ix-trigger-icon{font-size:14px;color:#cb9090;flex-shrink:0}.ix-card-summary{flex:1;min-width:0;display:flex;align-items:center;gap:4px;overflow:hidden}.ix-trigger-label{font-weight:500;white-space:nowrap}.ix-arrow{color:var(--p-text-muted-color);flex-shrink:0}.ix-action-label{color:var(--p-text-muted-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ix-remove-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;flex-shrink:0;font-size:12px}.ix-remove-btn:hover{background:#dc26261a;color:#dc2626}.ix-remove-btn.small{width:16px;height:16px;font-size:10px}.ix-card-body{padding:0 10px 10px;border-top:1px solid var(--p-surface-100)}.ix-action-row{padding:8px 0;border-bottom:1px dashed var(--p-surface-100)}.ix-action-row:last-of-type{border-bottom:none}.ix-action-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.ix-action-index{display:flex;align-items:center;gap:4px;font-size:11px;font-weight:600;color:var(--p-text-muted-color);text-transform:uppercase;letter-spacing:.03em}.ix-action-target-badge{font-weight:400;text-transform:none;letter-spacing:0;color:#cb9090}.ix-action-row--reverse{background:#638fcb0a;border-radius:6px;padding:6px 8px;border-bottom:none!important;margin-bottom:4px}.ix-toggle-header{display:flex;align-items:center;justify-content:space-between;padding:8px 0 4px;border-top:1px solid var(--p-surface-200);margin-top:4px}.ix-toggle-label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);display:flex;align-items:center;gap:5px}.ix-toggle-label i{font-size:12px}.ix-toggle-switch{position:relative;display:inline-flex;align-items:center;cursor:pointer}.ix-toggle-switch input[type=checkbox]{position:absolute;opacity:0;width:0;height:0}.ix-toggle-track{display:block;width:28px;height:16px;border-radius:8px;background:var(--p-surface-300);transition:background .2s;position:relative}.ix-toggle-track:after{content:\"\";position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;transition:transform .2s}.ix-toggle-switch input:checked~.ix-toggle-track{background:#638fcb}.ix-toggle-switch input:checked~.ix-toggle-track:after{transform:translate(12px)}.ix-add-action-btn{display:flex;align-items:center;gap:4px;margin-top:8px;padding:4px 8px;border:1px dashed var(--p-surface-300);background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:6px;font-size:11px;transition:border-color .15s,color .15s}.ix-add-action-btn:hover{border-color:#cb9090;color:#cb9090}.ix-field{margin-bottom:8px}.ix-field label{display:block;font-size:11px;color:var(--p-text-muted-color);margin-bottom:3px;font-weight:500}.ix-field select,.ix-field input[type=number]{width:100%;padding:5px 8px;border:1px solid var(--p-surface-200);border-radius:6px;font-size:12px;background:var(--p-surface-0);color:var(--p-text-color);outline:none;transition:border-color .15s}.ix-field select:focus,.ix-field input[type=number]:focus{border-color:#cb9090}.ix-field-row{display:flex;gap:8px}.ix-field-row .ix-field{flex:1}.ix-checkbox-field label{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:12px;color:var(--p-text-color)}.ix-checkbox-field input[type=checkbox]{accent-color:#cb9090}.ix-add-form{border:1px solid var(--p-surface-200);border-radius:8px;padding:10px;margin-bottom:6px}.ix-form-actions{display:flex;justify-content:flex-end;gap:6px;margin-top:4px}.ix-btn{padding:5px 12px;border:none;border-radius:6px;font-size:12px;cursor:pointer;transition:background .12s,color .12s}.ix-btn--primary{background:#cb9090;color:#fff}.ix-btn--primary:hover{background:#be7474}.ix-btn--secondary{background:transparent;color:var(--p-text-muted-color)}.ix-btn--secondary:hover{background:var(--p-surface-100);color:var(--p-text-color)}.ix-add-btn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:8px;border:1px dashed var(--p-surface-300);background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:8px;font-size:12px;transition:border-color .15s,color .15s}.ix-add-btn:hover{border-color:#cb9090;color:#cb9090}.ix-target-hint{display:block;font-size:10px;color:var(--p-text-muted-color);margin-top:4px;font-style:italic}::ng-deep .ix-target-select{width:100%}::ng-deep .ix-target-select .p-select-label{font-size:12px;padding:4px 8px}::ng-deep .ix-target-select .p-select{border-radius:6px}\n"], dependencies: [{ 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: i4$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i4$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i4$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }] }); }
|
|
7163
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: InteractionsPanelComponent, isStandalone: false, selector: "app-interactions-panel", inputs: { node: "node" }, ngImport: i0, template: "<div class=\"interactions-panel\">\n <!-- No element selected -->\n <div *ngIf=\"!node\" class=\"section-empty\">\n Select an element to manage interactions\n </div>\n\n <ng-container *ngIf=\"node\">\n <!-- Interaction cards -->\n <div *ngFor=\"let ix of interactions\" class=\"ix-card\" [class.is-expanded]=\"expandedId === ix.id\">\n <!-- Summary row -->\n <div class=\"ix-card-header\" (click)=\"toggleExpand(ix.id)\">\n <i [class]=\"getTriggerIcon(ix.trigger)\" class=\"ix-trigger-icon\"></i>\n <div class=\"ix-card-summary\">\n <span class=\"ix-trigger-label\">{{ getTriggerLabel(ix.trigger) }}</span>\n <span class=\"ix-arrow\">\u2192</span>\n <span class=\"ix-action-label\">{{ getActionsSummary(ix) }}</span>\n </div>\n <button class=\"ix-remove-btn\" title=\"Remove\" (click)=\"removeInteraction(ix.id); $event.stopPropagation()\">\n <i class=\"ph-thin ph-x\"></i>\n </button>\n </div>\n\n <!-- Expanded detail -->\n <div *ngIf=\"expandedId === ix.id\" class=\"ix-card-body\">\n <div class=\"ix-field\">\n <label>Trigger</label>\n <select [(ngModel)]=\"ix.trigger\">\n <option *ngFor=\"let t of triggerOptions\" [value]=\"t.value\">{{ t.label }}</option>\n </select>\n </div>\n\n <div *ngFor=\"let action of ix.actions; let ai = index\" class=\"ix-action-row\">\n <div class=\"ix-action-header\">\n <span class=\"ix-action-index\">\n Target {{ ai + 1 }}\n <span *ngIf=\"ix.actions.length > 1\" class=\"ix-action-target-badge\">\n \u2192 {{ getTargetLabel(action.target) }}\n </span>\n </span>\n <button *ngIf=\"ix.actions.length > 1\"\n class=\"ix-remove-btn small\"\n title=\"Remove action\"\n (click)=\"removeAction(ix, ai)\">\n <i class=\"ph-thin ph-x\"></i>\n </button>\n </div>\n\n <div class=\"ix-field\">\n <label>Type</label>\n <select [(ngModel)]=\"action.type\">\n <option *ngFor=\"let a of actionTypeOptions\" [value]=\"a.value\">{{ a.label }}</option>\n </select>\n </div>\n\n <div class=\"ix-field\">\n <label>Target</label>\n <p-select\n [(ngModel)]=\"action.target\"\n [options]=\"nodeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [filter]=\"true\"\n filterPlaceholder=\"Search\u2026\"\n styleClass=\"ix-target-select\"\n appendTo=\"body\">\n </p-select>\n <span *ngIf=\"nodeOptions.length === 1\" class=\"ix-target-hint\">\n Name elements in the Layers panel to target them\n </span>\n </div>\n\n <div class=\"ix-field-row\">\n <div class=\"ix-field\">\n <label>Duration (ms)</label>\n <input type=\"number\" [(ngModel)]=\"action.duration\" min=\"0\" step=\"50\">\n </div>\n <div class=\"ix-field\">\n <label>Delay (ms)</label>\n <input type=\"number\" [(ngModel)]=\"action.delay\" min=\"0\" step=\"50\">\n </div>\n </div>\n\n <div class=\"ix-field\">\n <label>Easing</label>\n <select [(ngModel)]=\"action.easing\">\n <option *ngFor=\"let e of easingOptions\" [value]=\"e\">{{ e }}</option>\n </select>\n </div>\n\n <div class=\"ix-field ix-checkbox-field\">\n <label>\n <input type=\"checkbox\" [(ngModel)]=\"action.once\">\n Play once\n </label>\n </div>\n </div>\n\n <button class=\"ix-add-action-btn\" (click)=\"addAction(ix)\">\n <i class=\"ph-thin ph-plus\"></i> Add target\n </button>\n\n <!-- Toggle section (click only) -->\n <ng-container *ngIf=\"ix.trigger === 'click'\">\n <div class=\"ix-toggle-header\">\n <span class=\"ix-toggle-label\">\n <i class=\"ph-thin ph-arrows-clockwise\"></i> 2nd click\n </span>\n <label class=\"ix-toggle-switch\">\n <input type=\"checkbox\"\n [checked]=\"hasToggle(ix)\"\n (change)=\"hasToggle(ix) ? disableToggle(ix) : enableToggle(ix)\">\n <span class=\"ix-toggle-track\"></span>\n </label>\n </div>\n\n <ng-container *ngIf=\"hasToggle(ix)\">\n <div *ngFor=\"let ra of ix.reverseActions; let ri = index\" class=\"ix-action-row ix-action-row--reverse\">\n <div class=\"ix-action-header\">\n <span class=\"ix-action-index\">\n Target {{ ri + 1 }}\n <span *ngIf=\"(ix.reverseActions?.length ?? 0) > 1\" class=\"ix-action-target-badge\">\n \u2192 {{ getTargetLabel(ra.target) }}\n </span>\n </span>\n <button *ngIf=\"(ix.reverseActions?.length ?? 0) > 1\"\n class=\"ix-remove-btn small\"\n title=\"Remove\"\n (click)=\"removeReverseAction(ix, ri)\">\n <i class=\"ph-thin ph-x\"></i>\n </button>\n </div>\n\n <div class=\"ix-field\">\n <label>Type</label>\n <select [(ngModel)]=\"ra.type\">\n <option *ngFor=\"let a of actionTypeOptions\" [value]=\"a.value\">{{ a.label }}</option>\n </select>\n </div>\n\n <div class=\"ix-field\">\n <label>Target</label>\n <p-select\n [(ngModel)]=\"ra.target\"\n [options]=\"nodeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [filter]=\"true\"\n filterPlaceholder=\"Search\u2026\"\n styleClass=\"ix-target-select\"\n appendTo=\"body\">\n </p-select>\n </div>\n\n <div class=\"ix-field-row\">\n <div class=\"ix-field\">\n <label>Duration (ms)</label>\n <input type=\"number\" [(ngModel)]=\"ra.duration\" min=\"0\" step=\"50\">\n </div>\n <div class=\"ix-field\">\n <label>Delay (ms)</label>\n <input type=\"number\" [(ngModel)]=\"ra.delay\" min=\"0\" step=\"50\">\n </div>\n </div>\n\n <div class=\"ix-field\">\n <label>Easing</label>\n <select [(ngModel)]=\"ra.easing\">\n <option *ngFor=\"let e of easingOptions\" [value]=\"e\">{{ e }}</option>\n </select>\n </div>\n </div>\n\n <button class=\"ix-add-action-btn\" (click)=\"addReverseAction(ix)\">\n <i class=\"ph-thin ph-plus\"></i> Add target\n </button>\n </ng-container>\n </ng-container>\n </div>\n </div>\n\n <!-- Add interaction form -->\n <div *ngIf=\"isAdding\" class=\"ix-add-form\">\n <div class=\"ix-field\">\n <label>Trigger</label>\n <select [(ngModel)]=\"newTrigger\">\n <option *ngFor=\"let t of triggerOptions\" [value]=\"t.value\">{{ t.label }}</option>\n </select>\n </div>\n <div class=\"ix-field\">\n <label>Action</label>\n <select [(ngModel)]=\"newActionType\">\n <option *ngFor=\"let a of actionTypeOptions\" [value]=\"a.value\">{{ a.label }}</option>\n </select>\n </div>\n <div class=\"ix-field\">\n <label>Target</label>\n <p-select\n [(ngModel)]=\"newTarget\"\n [options]=\"nodeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [filter]=\"true\"\n filterPlaceholder=\"Search\u2026\"\n styleClass=\"ix-target-select\"\n appendTo=\"body\">\n </p-select>\n <span *ngIf=\"nodeOptions.length === 1\" class=\"ix-target-hint\">\n Name elements in the Layers panel to target them\n </span>\n </div>\n <div *ngIf=\"isSwiperGoToSlide\" class=\"ix-field\">\n <label>Slide index (0-based)</label>\n <input type=\"number\" [(ngModel)]=\"newSlideIndex\" min=\"0\" step=\"1\">\n </div>\n <div *ngIf=\"!isSwiperAction\" class=\"ix-field-row\">\n <div class=\"ix-field\">\n <label>Duration (ms)</label>\n <input type=\"number\" [(ngModel)]=\"newDuration\" min=\"0\" step=\"50\">\n </div>\n <div class=\"ix-field\">\n <label>Delay (ms)</label>\n <input type=\"number\" [(ngModel)]=\"newDelay\" min=\"0\" step=\"50\">\n </div>\n </div>\n <div class=\"ix-field\">\n <label>Easing</label>\n <select [(ngModel)]=\"newEasing\">\n <option *ngFor=\"let e of easingOptions\" [value]=\"e\">{{ e }}</option>\n </select>\n </div>\n <div class=\"ix-field ix-checkbox-field\">\n <label>\n <input type=\"checkbox\" [(ngModel)]=\"newOnce\">\n Play once\n </label>\n </div>\n <div class=\"ix-form-actions\">\n <button class=\"ix-btn ix-btn--secondary\" (click)=\"cancelAdd()\">Cancel</button>\n <button class=\"ix-btn ix-btn--primary\" (click)=\"confirmAdd()\">Add</button>\n </div>\n </div>\n\n <!-- Add button -->\n <button *ngIf=\"!isAdding\" class=\"ix-add-btn\" (click)=\"startAdd()\">\n <i class=\"ph-thin ph-plus\"></i> Add interaction\n </button>\n </ng-container>\n</div>\n", styles: [".interactions-panel{padding:.5rem}.section-empty{color:var(--p-text-muted-color);font-size:12px;text-align:center;padding:1rem}.ix-card{border:1px solid var(--p-surface-200);border-radius:8px;margin-bottom:6px;overflow:hidden;transition:border-color .15s}.ix-card.is-expanded{border-color:#cb9090}.ix-card-header{display:flex;align-items:center;gap:8px;padding:8px 10px;cursor:pointer;font-size:12px;transition:background .12s}.ix-card-header:hover{background:var(--p-surface-50)}.ix-trigger-icon{font-size:14px;color:#cb9090;flex-shrink:0}.ix-card-summary{flex:1;min-width:0;display:flex;align-items:center;gap:4px;overflow:hidden}.ix-trigger-label{font-weight:500;white-space:nowrap}.ix-arrow{color:var(--p-text-muted-color);flex-shrink:0}.ix-action-label{color:var(--p-text-muted-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ix-remove-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;flex-shrink:0;font-size:12px}.ix-remove-btn:hover{background:#dc26261a;color:#dc2626}.ix-remove-btn.small{width:16px;height:16px;font-size:10px}.ix-card-body{padding:0 10px 10px;border-top:1px solid var(--p-surface-100)}.ix-action-row{padding:8px 0;border-bottom:1px dashed var(--p-surface-100)}.ix-action-row:last-of-type{border-bottom:none}.ix-action-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.ix-action-index{display:flex;align-items:center;gap:4px;font-size:11px;font-weight:600;color:var(--p-text-muted-color);text-transform:uppercase;letter-spacing:.03em}.ix-action-target-badge{font-weight:400;text-transform:none;letter-spacing:0;color:#cb9090}.ix-action-row--reverse{background:#638fcb0a;border-radius:6px;padding:6px 8px;border-bottom:none!important;margin-bottom:4px}.ix-toggle-header{display:flex;align-items:center;justify-content:space-between;padding:8px 0 4px;border-top:1px solid var(--p-surface-200);margin-top:4px}.ix-toggle-label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);display:flex;align-items:center;gap:5px}.ix-toggle-label i{font-size:12px}.ix-toggle-switch{position:relative;display:inline-flex;align-items:center;cursor:pointer}.ix-toggle-switch input[type=checkbox]{position:absolute;opacity:0;width:0;height:0}.ix-toggle-track{display:block;width:28px;height:16px;border-radius:8px;background:var(--p-surface-300);transition:background .2s;position:relative}.ix-toggle-track:after{content:\"\";position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;transition:transform .2s}.ix-toggle-switch input:checked~.ix-toggle-track{background:#638fcb}.ix-toggle-switch input:checked~.ix-toggle-track:after{transform:translate(12px)}.ix-add-action-btn{display:flex;align-items:center;gap:4px;margin-top:8px;padding:4px 8px;border:1px dashed var(--p-surface-300);background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:6px;font-size:11px;transition:border-color .15s,color .15s}.ix-add-action-btn:hover{border-color:#cb9090;color:#cb9090}.ix-field{margin-bottom:8px}.ix-field label{display:block;font-size:11px;color:var(--p-text-muted-color);margin-bottom:3px;font-weight:500}.ix-field select,.ix-field input[type=number]{width:100%;padding:5px 8px;border:1px solid var(--p-surface-200);border-radius:6px;font-size:12px;background:var(--p-surface-0);color:var(--p-text-color);outline:none;transition:border-color .15s}.ix-field select:focus,.ix-field input[type=number]:focus{border-color:#cb9090}.ix-field-row{display:flex;gap:8px}.ix-field-row .ix-field{flex:1}.ix-checkbox-field label{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:12px;color:var(--p-text-color)}.ix-checkbox-field input[type=checkbox]{accent-color:#cb9090}.ix-add-form{border:1px solid var(--p-surface-200);border-radius:8px;padding:10px;margin-bottom:6px}.ix-form-actions{display:flex;justify-content:flex-end;gap:6px;margin-top:4px}.ix-btn{padding:5px 12px;border:none;border-radius:6px;font-size:12px;cursor:pointer;transition:background .12s,color .12s}.ix-btn--primary{background:#cb9090;color:#fff}.ix-btn--primary:hover{background:#be7474}.ix-btn--secondary{background:transparent;color:var(--p-text-muted-color)}.ix-btn--secondary:hover{background:var(--p-surface-100);color:var(--p-text-color)}.ix-add-btn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:8px;border:1px dashed var(--p-surface-300);background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:8px;font-size:12px;transition:border-color .15s,color .15s}.ix-add-btn:hover{border-color:#cb9090;color:#cb9090}.ix-target-hint{display:block;font-size:10px;color:var(--p-text-muted-color);margin-top:4px;font-style:italic}::ng-deep .ix-target-select{width:100%}::ng-deep .ix-target-select .p-select-label{font-size:12px;padding:4px 8px}::ng-deep .ix-target-select .p-select{border-radius:6px}\n"], dependencies: [{ 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: i4$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i4$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i4$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }] }); }
|
|
7150
7164
|
}
|
|
7151
7165
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: InteractionsPanelComponent, decorators: [{
|
|
7152
7166
|
type: Component,
|
|
@@ -7296,6 +7310,7 @@ class IoxBuilderModule {
|
|
|
7296
7310
|
InteractionPresetRegistryService,
|
|
7297
7311
|
BuilderHistoryService,
|
|
7298
7312
|
BuilderClipboardService,
|
|
7313
|
+
BuilderDataSourceService,
|
|
7299
7314
|
], imports: [CommonModule,
|
|
7300
7315
|
FormsModule,
|
|
7301
7316
|
DragDropModule,
|
|
@@ -7351,6 +7366,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
7351
7366
|
InteractionPresetRegistryService,
|
|
7352
7367
|
BuilderHistoryService,
|
|
7353
7368
|
BuilderClipboardService,
|
|
7369
|
+
BuilderDataSourceService,
|
|
7354
7370
|
],
|
|
7355
7371
|
exports: [
|
|
7356
7372
|
// Angular/PrimeNG modules re-exported so consumers can use them
|
|
@@ -7388,6 +7404,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
7388
7404
|
}]
|
|
7389
7405
|
}] });
|
|
7390
7406
|
|
|
7407
|
+
/**
|
|
7408
|
+
* Canvas data preview used to come from host-provided content services (IOX_CONTENT_SERVICE /
|
|
7409
|
+
* IOX_SHOP_SERVICE), whose `getContent(contentType, orgId)` hit the ADMIN resources endpoint and
|
|
7410
|
+
* accepted no filters — so the Repeater/Slider ignored every data-source filter. Data now flows
|
|
7411
|
+
* through BuilderDataSourceService + the shared planDataSource, configured with
|
|
7412
|
+
* IOX_DATA_SOURCE_ENDPOINTS. Those tokens are gone; do not reintroduce a fetch that bypasses it.
|
|
7413
|
+
*/
|
|
7414
|
+
/** Optional font manager. Provide from the host app to populate the fontFamily dropdown. */
|
|
7415
|
+
const IOX_FONT_MANAGER = new InjectionToken('IOX_FONT_MANAGER');
|
|
7416
|
+
|
|
7391
7417
|
class BuilderButtonComponentConfig extends ComponentConfig {
|
|
7392
7418
|
constructor() {
|
|
7393
7419
|
super('Button', 'app-builder-button', 'ph-thin ph-cursor-click', 'Basic');
|
|
@@ -7894,5 +7920,5 @@ class BuilderSpacerComponentConfig extends ComponentConfig {
|
|
|
7894
7920
|
* Generated bundle index. Do not edit.
|
|
7895
7921
|
*/
|
|
7896
7922
|
|
|
7897
|
-
export { ACTION_TYPE_OPTIONS, BackgroundGroupStyleConfig, BorderGroupStyleConfig, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderClipboardService, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderHistoryService, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ComponentConfig, ComponentRegistryService, DEVICE_OPTIONS, DataSourceRegistryService, DataSourceType, DeviceMode, DimensionsGroupStyleConfig, DragEngineService, EASING_OPTIONS, EffectsGroupStyleConfig, GroupStyleConfig, INTERACTION_STATES, INVERSE_ACTION,
|
|
7923
|
+
export { ACTION_TYPE_OPTIONS, BackgroundGroupStyleConfig, BorderGroupStyleConfig, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderClipboardService, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDataSourceService, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderHistoryService, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ComponentConfig, ComponentRegistryService, DEVICE_OPTIONS, DataSourceRegistryService, DataSourceType, DeviceMode, DimensionsGroupStyleConfig, DragEngineService, EASING_OPTIONS, EffectsGroupStyleConfig, GroupStyleConfig, INTERACTION_STATES, INVERSE_ACTION, IOX_DATA_SOURCE_ENDPOINTS, IOX_FONT_MANAGER, InteractionEngineService, InteractionPresetRegistryService, InteractionsPanelComponent, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LayerTreeComponent, LayoutGroupStyleConfig, ListGroupStyleConfig, NodeAction, OverlayComponent, OverlayService, PanelChildComponent, PanelComponent, PanelEventService, PanelEventTypes, PanelTypes, PositionGroupStyleConfig, PresetRegistryService, RELATIONAL_STATES, RELATIONAL_STATE_BASE, ROUTE_ANIMATION_OPTIONS, RenderDirective, RepeaterComponentConfig, SCREEN_WIDTH_OPTIONS, STRUCTURAL_STATES, SUPPORTED_STATES, SectionComponent, SectionComponentConfig, SizeGroupStyleConfig, SliderContainerComponent, SliderContainerConfig, SliderSlideComponent, SliderSlideConfig, SpacingGroupStyleConfig, StyleCategory, StyleRegistryService, TraitConfig as StyleTraitConfig, SymbolRegistryService, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, TypographyGroupStyleConfig, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, ViewportService, ZOOM_OPTIONS, buildFullStyleTraits, buildPresetStyleTraits, defaultPageSettings, flattenSchemaFields, generateNodeId, resolveTraitControllerType, resolveTraitOptions };
|
|
7898
7924
|
//# sourceMappingURL=vectoriox-iox-builder.mjs.map
|