@vectoriox/iox-builder 4.25.0 → 4.27.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.
|
@@ -15,12 +15,13 @@ import { InputTextModule } from 'primeng/inputtext';
|
|
|
15
15
|
import { SelectModule } from 'primeng/select';
|
|
16
16
|
import { TooltipModule } from 'primeng/tooltip';
|
|
17
17
|
import { DialogModule } from 'primeng/dialog';
|
|
18
|
-
import * as
|
|
18
|
+
import * as i2$2 from '@vectoriox/iox-ui';
|
|
19
19
|
import { VALIDATION_STATES as VALIDATION_STATES$1, VALIDATION_STATE_CLASS as VALIDATION_STATE_CLASS$1, DEFAULT_WIDTH_BY_TYPE, resolveFlavorDefaults, Breakpoint, BREAKPOINTS, countOverrides, setOverride, DEFAULT_FLAVOR, breakpointDef, breakpointForWidth, FormRenderState, safeSetInput, ContextStore, ComponentInstanceRegistryService, isActionEnabled, isContextAction, contextActionEffect, resolveContextValue, DeclarationContext, buildPartSelector, planResponsiveRules, resolveStyleProps, buildTargetedStateSelector, compileDeclarations, wrapInBreakpointQuery, BreakpointQueryKind, composeVirtualTraits, stateNamesIn, partClassName, resolveInputs, setInputOverride, collectContextSlotKeys, withContextSlots, compilePageStyle, nodeUsesContext, resolveBoundValue, IS_PREVIEW, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, IoxPageModule, PART_CLASS_NAMES } from '@vectoriox/iox-ui';
|
|
20
20
|
export { ComponentInstanceRegistryService, VIRTUAL_TRAIT_KEYS, composeVirtualTraits } from '@vectoriox/iox-ui';
|
|
21
21
|
import Lenis from 'lenis';
|
|
22
22
|
import { Subject, BehaviorSubject, of, forkJoin } from 'rxjs';
|
|
23
23
|
import interact from 'interactjs';
|
|
24
|
+
import { BEHAVIOUR_ACTION_TYPES } from '@vectoriox/iox-ui/actions-core';
|
|
24
25
|
import Moveable from 'moveable';
|
|
25
26
|
import Selecto from 'selecto';
|
|
26
27
|
import { map, catchError } from 'rxjs/operators';
|
|
@@ -83,6 +84,8 @@ const INVERSE_ACTION = {
|
|
|
83
84
|
// `contextActionEffect` (@vectoriox/iox-ui).
|
|
84
85
|
setContext: 'clearContext',
|
|
85
86
|
clearContext: 'setContext',
|
|
87
|
+
openDialog: 'closeDialog',
|
|
88
|
+
closeDialog: 'openDialog',
|
|
86
89
|
};
|
|
87
90
|
const TRIGGER_OPTIONS = [
|
|
88
91
|
{ value: 'pageLoad', label: 'Page load', icon: 'ph-thin ph-play' },
|
|
@@ -106,9 +109,14 @@ const ACTION_TYPE_OPTIONS = [
|
|
|
106
109
|
{ value: 'show', label: 'Show' },
|
|
107
110
|
{ value: 'hide', label: 'Hide' },
|
|
108
111
|
{ value: 'toggleVisibility', label: 'Toggle visibility' },
|
|
112
|
+
{ value: 'openDialog', label: 'Open dialog' },
|
|
113
|
+
{ value: 'closeDialog', label: 'Close dialog' },
|
|
114
|
+
{ value: 'toggleDialog', label: 'Toggle dialog' },
|
|
109
115
|
{ value: 'setContext', label: 'Set context' },
|
|
110
116
|
{ value: 'clearContext', label: 'Clear context' },
|
|
111
117
|
];
|
|
118
|
+
/** Dialog actions, for the engines' dispatch branch (mirror of SWIPER's set). */
|
|
119
|
+
const DIALOG_ACTION_TYPES = new Set(['openDialog', 'closeDialog', 'toggleDialog']);
|
|
112
120
|
const EASING_OPTIONS$1 = ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'];
|
|
113
121
|
/** Interaction pseudo-classes — compiled to .iox-node-{id}:state */
|
|
114
122
|
const INTERACTION_STATES = ['hover', 'active', 'focus'];
|
|
@@ -3254,6 +3262,22 @@ class InteractionEngineService {
|
|
|
3254
3262
|
this.executeSwiperAction(action);
|
|
3255
3263
|
continue;
|
|
3256
3264
|
}
|
|
3265
|
+
// Dialog actions (A1b): the canvas RUNS them — styling a dialog you cannot open is
|
|
3266
|
+
// impossible. The canvas twin registered open/close/toggle under its nodeId, exactly
|
|
3267
|
+
// the Swiper-method pattern; a missing/mistargeted id is a silent no-op, never a throw.
|
|
3268
|
+
if (DIALOG_ACTION_TYPES.has(action.type)) {
|
|
3269
|
+
this.executeDialogAction(action);
|
|
3270
|
+
continue;
|
|
3271
|
+
}
|
|
3272
|
+
// Tier-A behaviour (A1c). The canvas-is-live rules are catalog DATA
|
|
3273
|
+
// (ELEMENT_ACTION_DESCRIPTORS): copy runs, scrollTo runs (scrollIntoView — the frame
|
|
3274
|
+
// scrolls natively here; the Lenis rule is the LIVE side's), navigate and submitForm
|
|
3275
|
+
// SIMULATE — a dispatched event the host surfaces as a toast, never a route change
|
|
3276
|
+
// or a fake submit under the author's feet.
|
|
3277
|
+
if (BEHAVIOUR_ACTION_TYPES.has(action.type)) {
|
|
3278
|
+
this.executeBehaviourAction(node, action, selfEl);
|
|
3279
|
+
continue;
|
|
3280
|
+
}
|
|
3257
3281
|
// Context actions write STATE, not animation. `selfEl` is deliberate: $item is read by
|
|
3258
3282
|
// walking up from the element actually hovered/clicked, which for a repeater PREVIEW ROW
|
|
3259
3283
|
// is the clone — so each row publishes its own item, exactly as on the live site.
|
|
@@ -3303,6 +3327,44 @@ class InteractionEngineService {
|
|
|
3303
3327
|
// MERGE, not replace — a page can hold several repeaters, each publishing its own source.
|
|
3304
3328
|
this.contextData = { ...this.contextData, ...(data ?? {}) };
|
|
3305
3329
|
}
|
|
3330
|
+
executeBehaviourAction(node, action, selfEl) {
|
|
3331
|
+
switch (action.type) {
|
|
3332
|
+
case 'copyToClipboard': {
|
|
3333
|
+
const text = String(action.params?.['text'] ?? '');
|
|
3334
|
+
if (text)
|
|
3335
|
+
navigator.clipboard?.writeText(text).catch(() => { });
|
|
3336
|
+
return;
|
|
3337
|
+
}
|
|
3338
|
+
case 'scrollTo': {
|
|
3339
|
+
const target = this.resolveTarget(node, action, selfEl);
|
|
3340
|
+
target?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3343
|
+
case 'navigate':
|
|
3344
|
+
case 'submitForm': {
|
|
3345
|
+
// Simulated: the host (the admin app) listens and shows "would …" as a toast.
|
|
3346
|
+
const detail = { type: action.type, params: action.params ?? {}, target: action.target };
|
|
3347
|
+
window.dispatchEvent(new CustomEvent('iox-action-simulated', { detail }));
|
|
3348
|
+
return;
|
|
3349
|
+
}
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
executeDialogAction(action) {
|
|
3353
|
+
const dialog = action.target && action.target !== 'self' ? this.instanceRegistry.get(action.target) : null;
|
|
3354
|
+
if (!dialog)
|
|
3355
|
+
return;
|
|
3356
|
+
switch (action.type) {
|
|
3357
|
+
case 'openDialog':
|
|
3358
|
+
dialog.open?.();
|
|
3359
|
+
break;
|
|
3360
|
+
case 'closeDialog':
|
|
3361
|
+
dialog.close?.();
|
|
3362
|
+
break;
|
|
3363
|
+
case 'toggleDialog':
|
|
3364
|
+
dialog.toggle?.();
|
|
3365
|
+
break;
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3306
3368
|
executeSwiperAction(action) {
|
|
3307
3369
|
// Target is the nodeId of the SliderContainer to control.
|
|
3308
3370
|
const swiper = this.instanceRegistry.get(action.target);
|
|
@@ -6535,11 +6597,32 @@ class BuilderComponent {
|
|
|
6535
6597
|
this.lenis = undefined;
|
|
6536
6598
|
this.lenisRafId = undefined;
|
|
6537
6599
|
}
|
|
6600
|
+
/**
|
|
6601
|
+
* K5 (actions plan): actions need NAMED targets — the panel lists only labeled nodes, so an
|
|
6602
|
+
* unlabeled Dialog is unpickable. Every insert path labels the node "<Type>" or "<Type> N",
|
|
6603
|
+
* counting existing labels of that family across the whole tree.
|
|
6604
|
+
*/
|
|
6605
|
+
autoLabel(config) {
|
|
6606
|
+
if (!config?.type || config.label)
|
|
6607
|
+
return;
|
|
6608
|
+
const base = String(config.type).replace(/([a-z])([A-Z])/g, '$1 $2');
|
|
6609
|
+
let count = 0;
|
|
6610
|
+
const walk = (nodes) => {
|
|
6611
|
+
for (const n of nodes ?? []) {
|
|
6612
|
+
if (typeof n?.label === 'string' && (n.label === base || n.label.startsWith(base + ' ')))
|
|
6613
|
+
count++;
|
|
6614
|
+
walk(n?.children);
|
|
6615
|
+
}
|
|
6616
|
+
};
|
|
6617
|
+
walk(this.layout);
|
|
6618
|
+
config.label = count === 0 ? base : `${base} ${count + 1}`;
|
|
6619
|
+
}
|
|
6538
6620
|
addComponent(name) {
|
|
6539
6621
|
const config = this.registry.createConfig(name);
|
|
6540
6622
|
if (!config) {
|
|
6541
6623
|
return;
|
|
6542
6624
|
}
|
|
6625
|
+
this.autoLabel(config);
|
|
6543
6626
|
this.layout.push(config);
|
|
6544
6627
|
}
|
|
6545
6628
|
onDrop(event) {
|
|
@@ -6549,6 +6632,7 @@ class BuilderComponent {
|
|
|
6549
6632
|
const config = this.registry.createConfig(payload.data);
|
|
6550
6633
|
if (!config)
|
|
6551
6634
|
return;
|
|
6635
|
+
this.autoLabel(config);
|
|
6552
6636
|
this.layout.splice(insertIndex, 0, config);
|
|
6553
6637
|
this.cdr.markForCheck();
|
|
6554
6638
|
this._selectAfterDrop(config);
|
|
@@ -7210,7 +7294,7 @@ class BuilderComponent {
|
|
|
7210
7294
|
}
|
|
7211
7295
|
}
|
|
7212
7296
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderComponent, deps: [{ token: ComponentRegistryService }, { token: OverlayService }, { token: PanelEventService }, { token: DragEngineService }, { token: DataSourceRegistryService }, { token: ViewportService }, { token: FormStateService }, { token: InteractionEngineService }, { token: InteractionPresetRegistryService }, { token: BuilderClipboardService }, { token: SymbolRegistryService }, { token: i0.ChangeDetectorRef }, { token: i0.ApplicationRef }, { token: MoveableCanvasService }, { token: SelectoCanvasService }, { token: StyleRegistryService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7213
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: BuilderComponent, isStandalone: false, selector: "app-builder", inputs: { layout: "layout", dataSources: "dataSources", orgId: "orgId", routeParams: "routeParams", pageName: "pageName", isSaving: "isSaving", pageStatus: "pageStatus", pageSettings: "pageSettings", globalElements: "globalElements", canUndo: "canUndo", canRedo: "canRedo", moveableMode: "moveableMode" }, outputs: { save: "save", undo: "undo", redo: "redo", back: "back", preview: "preview", publishToggle: "publishToggle", pageSettingsChange: "pageSettingsChange", applyAnimationToAll: "applyAnimationToAll", saveBlock: "saveBlock", globalElementsChange: "globalElementsChange" }, viewQueries: [{ propertyName: "previewCanvas", first: true, predicate: ["previewCanvas"], descendants: true }, { propertyName: "previewScrollRef", first: true, predicate: ["previewScroll"], descendants: true }, { propertyName: "lenisContentRef", first: true, predicate: ["lenisContent"], descendants: true }, { propertyName: "globalOverlayRef", first: true, predicate: ["globalOverlay"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"builder\">\n <header class=\"builder-header\">\n <div class=\"sidebar-switcher\">\n <button (click)=\"activeSidebar = 'pages'\" [class.active]=\"activeSidebar === 'pages'\" title=\"Pages\" aria-label=\"Pages\">\n <i class=\"ph-thin ph-browsers\"></i>\n </button>\n <button (click)=\"activeSidebar = 'components'\" [class.active]=\"activeSidebar === 'components'\" title=\"Components\" aria-label=\"Components\">\n <i class=\"ph-thin ph-cube\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tree'\" [class.active]=\"activeSidebar === 'tree'\" title=\"Layers\" aria-label=\"Layers\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tokens'\" [class.active]=\"activeSidebar === 'tokens'\" title=\"Design Tokens\" aria-label=\"Design Tokens\">\n <i class=\"ph-thin ph-circles-three\"></i>\n </button>\n </div>\n\n <app-toolbar\n [activeMode]=\"activeMode\"\n [activeBreakpoint]=\"activeBreakpoint\"\n [breakpointCounts]=\"breakpointCounts\"\n [auditCount]=\"auditFindings.length\"\n [auditOpen]=\"auditOpen\"\n [activeZoom]=\"activeZoom\"\n [activeScreenWidth]=\"activeScreenWidth\"\n [isSaving]=\"isSaving\"\n [pageStatus]=\"pageStatus\"\n [canUndo]=\"canUndo\"\n [canRedo]=\"canRedo\"\n (modeChange)=\"handleToolbarModeChange($event)\"\n (breakpointChange)=\"handleToolbarBreakpointChange($event)\"\n (auditToggle)=\"toggleAudit()\"\n (zoomChange)=\"handleToolbarZoomChange($event)\"\n (screenWidthChange)=\"handleToolbarScreenWidthChange($event)\"\n (save)=\"save.emit()\"\n (preview)=\"preview.emit()\"\n (publishToggle)=\"publishToggle.emit()\"\n (undo)=\"undo.emit()\"\n (redo)=\"redo.emit()\">\n </app-toolbar>\n\n <div class=\"panel-switcher\">\n <button (click)=\"selectPanel(panelTypes.BINDINGS)\" [class.active]=\"activePanel === panelTypes.BINDINGS\" title=\"Bindings\">\n <i class=\"ph-thin ph-plugs-connected\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.STYLES)\" [class.active]=\"activePanel === panelTypes.STYLES\" title=\"Styles\">\n <i class=\"ph-thin ph-paint-brush\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.PAGE)\" [class.active]=\"activePanel === panelTypes.PAGE\" title=\"Page settings\" aria-label=\"Page settings\">\n <i class=\"ph-thin ph-gear-six\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.INTERACTIONS)\" [class.active]=\"activePanel === panelTypes.INTERACTIONS\" title=\"Interactions\">\n <i class=\"ph-thin ph-lightning\"></i>\n </button>\n </div> \n </header>\n\n <div class=\"builder-main\" [class.panel-open]=\"isPanelOpen\">\n <aside class=\"sidebar\">\n <div *ngIf=\"activeSidebar === 'pages'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderPages]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'components'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderComponents]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'tokens'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderTokens]\"></ng-content>\n </div>\n <app-layer-tree *ngIf=\"activeSidebar === 'tree'\"\n [layout]=\"layout\"\n [globalElements]=\"globalElements\"\n (nodeSelect)=\"onTreeNodeSelect($event)\"\n (nodeAction)=\"onTreeNodeAction($event)\"\n (nodeMove)=\"onTreeNodeMove()\"></app-layer-tree>\n </aside>\n\n <main #previewCanvas class=\"preview\"\n [class.grab-mode]=\"activeMode === builderModes.Pan\"\n [class.grabbing]=\"isPanning\"\n (click)=\"handleCanvasClick()\"\n (mousedown)=\"onBoardMouseDown($event)\"\n (mousemove)=\"onBoardMouseMove($event)\"\n (mouseup)=\"onBoardMouseUp()\"\n (mouseleave)=\"onBoardMouseUp()\">\n <app-overlay (toolbarAction)=\"onToolbarAction($event)\"></app-overlay>\n\n <!-- Element path \u2014 pinned to the PREVIEW VIEWPORT, not to the canvas frame. The frame\n pans and scales; a breadcrumb that tracked its edge would drift off-screen and\n shrink with zoom. Sits in the gutter above the frame (see $canvas-inset-block-start).\n\n \u26A0\uFE0F stopPropagation is REQUIRED, not defensive. This element lives inside .preview,\n whose (click) is handleCanvasClick() \u2014 \"you clicked empty canvas, drop the\n selection\". Without it, picking an ancestor crumb selects that node and then\n immediately bubbles into the canvas handler, which clears it: the selection and the\n layer-tree highlight both fall back to Body. Same reason .audit-dock stops its own. -->\n <app-breadcrumb-bar\n (click)=\"$event.stopPropagation()\"\n [path]=\"selectedPath\"\n (nodeSelect)=\"onCrumbSelect($event)\"\n (rootSelect)=\"onCrumbRootSelect()\"\n (nodePeek)=\"onCrumbPeek($event)\">\n </app-breadcrumb-bar>\n\n <!-- Responsive audit (A5) \u2014 floats over the canvas, right gutter. -->\n @if (auditOpen) {\n <div class=\"audit-dock\" (click)=\"$event.stopPropagation()\">\n <app-audit-panel\n [findings]=\"auditFindings\"\n [breakpointLabel]=\"auditBreakpointLabel\"\n [running]=\"auditRunning\"\n (select)=\"selectAuditNode($event)\"\n (fix)=\"applyAuditFix($event)\"\n (fixAll)=\"applyAllAuditFixes()\"\n (rerun)=\"runAudit()\"\n (closePanel)=\"toggleAudit()\"></app-audit-panel>\n </div>\n }\n\n <!-- Custom Lenis scrollbar \u2014 lives in .preview (not .preview-scroll) so it\n stays in the right gutter and never overlaps the canvas at large widths.\n No translateY counteract needed since it isn't inside the Lenis wrapper. -->\n <div class=\"canvas-scrollbar\"\n [class.visible]=\"isScrollbarVisible\">\n <div class=\"canvas-scrollbar-thumb\"\n [style.height.px]=\"scrollThumbHeight\"\n [style.top.px]=\"scrollThumbTop\">\n </div>\n </div>\n\n <!-- Global elements overlay \u2014 outside Lenis so position:fixed children\n stay pinned to the canvas viewport rather than scrolling with content.\n Shares viewportTransform so elements scale correctly at any zoom level.\n Height matches viewportHeight so position:fixed + inset:0 fills the\n simulated viewport correctly (CSS calc(100%) would give the wrong\n containing-block height and break full-screen fixed overlays). -->\n <div *ngIf=\"globalElements.length\"\n #globalOverlay\n class=\"global-elements-overlay\"\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n <ng-container *ngFor=\"let item of globalElementsBefore\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n <ng-container *ngFor=\"let item of globalElementsAfter\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n </div>\n\n <div class=\"preview-scroll\"\n #previewScroll\n [style.width.px]=\"viewportScaledWidth\"\n [class.pan-mode]=\"activeMode === builderModes.Pan\">\n\n <!-- Lenis content proxy: height = realContentHeight \u00D7 scale.\n Lenis scrolls against this value so scroll range is always in\n visual px \u2014 correct at any zoom level. -->\n <div class=\"preview-lenis-content\" #lenisContent\n [style.height.px]=\"scaledContentHeight\">\n\n <iox-page-component\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n\n <!-- ngStyle carries the page's own background/typography (pageSettings.style),\n compiled by the SAME function the engine applies to <body>. Inline wins over\n the #canvas-preview white default, which stays as the unset fallback. -->\n <div class=\"canvas-viewport\"\n id=\"canvas-preview\"\n [ngStyle]=\"pageStyleCss\"\n [style.min-height.px]=\"canvasMinHeight\">\n\n <!-- Empty page (B4): a starting point beats a blank canvas. Each starter is\n a responsive layout preset \u2014 ordinary nodes, editable afterwards. -->\n @if (isPageEmpty) {\n <div class=\"empty-canvas\" (click)=\"$event.stopPropagation()\">\n <h2 class=\"empty-title\">Start with a layout</h2>\n <p class=\"empty-sub\">Each one already adapts to tablet and phone. You can edit or take it apart afterwards.</p>\n <div class=\"empty-grid\">\n @for (starter of starterLayouts; track starter.id) {\n <button type=\"button\" class=\"empty-card\" (click)=\"startWithLayout(starter)\">\n <i [class]=\"starter.icon\" aria-hidden=\"true\"></i>\n <span class=\"empty-card-name\">{{ starter.name }}</span>\n <span class=\"empty-card-desc\">{{ starter.description }}</span>\n </button>\n }\n </div>\n <button type=\"button\" class=\"empty-link\" (click)=\"browseComponents()\">Or start from a single element</button>\n </div>\n }\n\n <!-- WRAPPER COLLAPSE (task 9c): top-level nodes render DIRECTLY into the\n canvas viewport \u2014 no .preview-node wrapper; iox-outer + drag move to the\n host (RenderDirective, via ioxDragSourceId). -->\n <ng-container *ngFor=\"let item of layout\"\n [ioxRender]=\"item\"\n [ioxDragSourceId]=\"'canvas-preview'\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </div>\n </iox-page-component>\n </div>\n </div>\n </main>\n\n <ng-content select=\"[builderPanel]\"></ng-content>\n </div>\n\n <!-- Save as Reusable Block dialog -->\n @if (showSaveBlockDialog) {\n <div class=\"save-block-backdrop\" (click)=\"cancelSaveBlock()\"></div>\n <div class=\"save-block-dialog\" (click)=\"$event.stopPropagation()\">\n <h4 class=\"save-block-title\">Save as Reusable Block</h4>\n <input class=\"save-block-input\"\n type=\"text\"\n placeholder=\"Block name...\"\n [(ngModel)]=\"saveBlockName\"\n (keydown.enter)=\"confirmSaveBlock()\"\n (keydown.escape)=\"cancelSaveBlock()\"\n autofocus>\n <div class=\"save-block-actions\">\n <p-button size=\"small\" severity=\"secondary\" label=\"Cancel\" (click)=\"cancelSaveBlock()\"></p-button>\n <p-button size=\"small\" label=\"Save\" [disabled]=\"!saveBlockName.trim()\" (click)=\"confirmSaveBlock()\"></p-button>\n </div>\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex:1;min-height:0;overflow:hidden}.builder{display:flex;flex-direction:column;direction:ltr;width:100%;height:100%;min-height:0;border-radius:0;overflow:hidden;position:relative}.builder .builder-header{background:var(--p-surface-0);padding:.375rem .75rem;border-bottom:1px solid var(--p-surface-200);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:.5rem;flex-shrink:0}.builder .builder-header .header-back{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;cursor:pointer;color:var(--p-text-muted-color);font-size:16px;transition:background .15s ease-out;margin-inline-end:.25rem}.builder .builder-header .header-back:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .builder-header .header-page-name{flex:1;text-align:center;font-size:.8rem;font-weight:500;color:var(--p-text-muted-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-inline:1rem}.builder .sidebar-switcher,.builder .panel-switcher{display:flex;gap:.25rem}.builder .sidebar-switcher button,.builder .panel-switcher button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.builder .sidebar-switcher button i,.builder .panel-switcher button i{pointer-events:none}.builder .sidebar-switcher button:hover,.builder .panel-switcher button:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .sidebar-switcher button.active,.builder .panel-switcher button.active{background:#cb9090;color:#fff}.builder .panel-switcher{justify-self:end}.builder .builder-main{display:flex;flex:1 1 0;min-height:0;position:relative;overflow:hidden}.builder .sidebar{width:260px;min-width:260px;background:var(--p-surface-0);border-inline-end:1px solid var(--p-surface-200);overflow-y:auto;overflow-x:hidden;flex-shrink:0}.builder .preview{flex:1 1 0;min-width:0;min-height:0;position:relative;overflow:hidden}.builder .preview.grab-mode{cursor:grab}.builder .preview.grab-mode iox-page-component{pointer-events:none}.builder .preview.grabbing{cursor:grabbing}.builder .canvas-scrollbar{position:absolute;right:4px;top:46px;bottom:20px;width:6px;z-index:20;opacity:0;transition:opacity .2s ease;pointer-events:none}.builder .canvas-scrollbar.visible{opacity:1}.builder .canvas-scrollbar-thumb{position:absolute;left:0;width:100%;background:#00000059;border-radius:3px;transition:top .05s linear}.builder .preview-scroll{position:absolute;inset:46px auto 20px;inset-inline-start:50%;transform:translate(-50%);max-width:calc(100% - 40px);height:calc(100% - 66px);overflow:hidden}.builder .preview-lenis-content{position:relative;width:100%;overflow:hidden;contain:paint}.builder iox-page-component{position:absolute!important;top:0;bottom:auto!important;right:auto!important;left:50%;transform-origin:top center;overflow:visible!important;container:iox-canvas/inline-size;box-shadow:0 1px 4px #00000014,0 4px 16px #0000000a;transition:width .25s ease,transform .25s ease}.builder iox-page-component ::ng-deep .iox-page-wrapper{height:auto!important;overflow:visible!important}.builder #canvas-preview{background:#fff}.builder .empty-canvas{max-inline-size:560px;margin:0 auto;padding:48px 24px;text-align:center;color:#4b5563}.builder .empty-title{margin:0;font-size:18px;font-weight:600;color:#111827}.builder .empty-sub{margin:6px 0 20px;font-size:12px;line-height:1.5;color:#6b7280}.builder .empty-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.builder .empty-card{display:flex;flex-direction:column;align-items:center;gap:4px;padding:14px 10px;border:1px solid #e5e7eb;border-radius:10px;background:#fff;cursor:pointer;transition:border-color .15s ease,box-shadow .15s ease}.builder .empty-card:hover{border-color:#cb9090;box-shadow:0 2px 10px #0000000f}.builder .empty-card:focus-visible{outline:2px solid #cb9090;outline-offset:2px}.builder .empty-card i{font-size:20px;color:#a05c5c}.builder .empty-card-name{font-size:11.5px;font-weight:600;color:#111827}.builder .empty-card-desc{font-size:9.5px;line-height:1.35;color:#6b7280}.builder .empty-link{margin-block-start:16px;padding:0;border:none;background:none;font-size:11px;color:#a05c5c;cursor:pointer}.builder .empty-link:hover{text-decoration:underline}.builder .empty-link:focus-visible{outline:2px solid #cb9090;outline-offset:2px}.builder app-breadcrumb-bar{position:absolute;inset-block-start:12px;inset-inline-start:20px;inset-inline-end:56px;z-index:20;pointer-events:none}.builder .audit-dock{position:absolute;inset-block-start:46px;inset-inline-end:16px;z-index:20}.builder .global-elements-overlay{position:absolute;top:46px;left:50%;transform-origin:top center;pointer-events:none;z-index:9;overflow:hidden;container:iox-canvas/inline-size}.builder .global-elements-overlay ::ng-deep>*{pointer-events:auto}.builder .preview-node.is-selected{cursor:grab}.builder .empty-state{min-height:240px;border:1px dashed var(--p-surface-200);border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--p-text-muted-color);text-align:center;padding:1rem}.save-block-backdrop{position:fixed;inset:0;z-index:1000;background:#00000040}.save-block-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#fff;border-radius:8px;box-shadow:0 8px 32px #0000002e;padding:24px;width:320px}.save-block-dialog .save-block-title{margin:0 0 16px;font-size:14px;font-weight:600;color:var(--p-text-color, #333)}.save-block-dialog .save-block-input{width:100%;padding:8px 10px;border:1px solid var(--p-surface-300, #d1d5db);border-radius:6px;font-size:13px;outline:none;box-sizing:border-box;margin-bottom:16px}.save-block-dialog .save-block-input:focus{border-color:#cb9090;box-shadow:0 0 0 2px #cb909033}.save-block-dialog .save-block-actions{display:flex;justify-content:flex-end;gap:8px}::ng-deep .moveable-control-box.iox-moveable-silent{z-index:1000!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-line,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation-line{display:none!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-control{display:block!important;width:10px!important;height:10px!important;margin-top:-5px!important;margin-left:-5px!important;background:#fff!important;border:1.5px solid #cb9090!important;border-radius:2px!important;box-shadow:0 1px 3px #0003!important}\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: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i16.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: i16.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i16.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i17.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i18.IoxPageComponent, selector: "iox-page-component", inputs: ["class"], outputs: ["scrollEvent"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "component", type: OverlayComponent, selector: "app-overlay", outputs: ["toolbarAction"] }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["activeMode", "activeBreakpoint", "breakpointCounts", "auditCount", "auditOpen", "activeZoom", "activeScreenWidth", "canUndo", "canRedo", "isSaving", "pageStatus"], outputs: ["modeChange", "breakpointChange", "auditToggle", "zoomChange", "screenWidthChange", "undo", "redo", "save", "preview", "publishToggle"] }, { kind: "component", type: LayerTreeComponent, selector: "app-layer-tree", inputs: ["layout", "globalElements"], outputs: ["nodeSelect", "nodeAction", "nodeMove"] }, { kind: "component", type: BreadcrumbBarComponent, selector: "app-breadcrumb-bar", inputs: ["path"], outputs: ["nodeSelect", "rootSelect", "nodePeek"] }, { kind: "component", type: AuditPanelComponent, selector: "app-audit-panel", inputs: ["findings", "breakpointLabel", "running"], outputs: ["select", "fix", "fixAll", "rerun", "closePanel"] }] }); }
|
|
7297
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: BuilderComponent, isStandalone: false, selector: "app-builder", inputs: { layout: "layout", dataSources: "dataSources", orgId: "orgId", routeParams: "routeParams", pageName: "pageName", isSaving: "isSaving", pageStatus: "pageStatus", pageSettings: "pageSettings", globalElements: "globalElements", canUndo: "canUndo", canRedo: "canRedo", moveableMode: "moveableMode" }, outputs: { save: "save", undo: "undo", redo: "redo", back: "back", preview: "preview", publishToggle: "publishToggle", pageSettingsChange: "pageSettingsChange", applyAnimationToAll: "applyAnimationToAll", saveBlock: "saveBlock", globalElementsChange: "globalElementsChange" }, viewQueries: [{ propertyName: "previewCanvas", first: true, predicate: ["previewCanvas"], descendants: true }, { propertyName: "previewScrollRef", first: true, predicate: ["previewScroll"], descendants: true }, { propertyName: "lenisContentRef", first: true, predicate: ["lenisContent"], descendants: true }, { propertyName: "globalOverlayRef", first: true, predicate: ["globalOverlay"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"builder\">\n <header class=\"builder-header\">\n <div class=\"sidebar-switcher\">\n <button (click)=\"activeSidebar = 'pages'\" [class.active]=\"activeSidebar === 'pages'\" title=\"Pages\" aria-label=\"Pages\">\n <i class=\"ph-thin ph-browsers\"></i>\n </button>\n <button (click)=\"activeSidebar = 'components'\" [class.active]=\"activeSidebar === 'components'\" title=\"Components\" aria-label=\"Components\">\n <i class=\"ph-thin ph-cube\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tree'\" [class.active]=\"activeSidebar === 'tree'\" title=\"Layers\" aria-label=\"Layers\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tokens'\" [class.active]=\"activeSidebar === 'tokens'\" title=\"Design Tokens\" aria-label=\"Design Tokens\">\n <i class=\"ph-thin ph-circles-three\"></i>\n </button>\n </div>\n\n <app-toolbar\n [activeMode]=\"activeMode\"\n [activeBreakpoint]=\"activeBreakpoint\"\n [breakpointCounts]=\"breakpointCounts\"\n [auditCount]=\"auditFindings.length\"\n [auditOpen]=\"auditOpen\"\n [activeZoom]=\"activeZoom\"\n [activeScreenWidth]=\"activeScreenWidth\"\n [isSaving]=\"isSaving\"\n [pageStatus]=\"pageStatus\"\n [canUndo]=\"canUndo\"\n [canRedo]=\"canRedo\"\n (modeChange)=\"handleToolbarModeChange($event)\"\n (breakpointChange)=\"handleToolbarBreakpointChange($event)\"\n (auditToggle)=\"toggleAudit()\"\n (zoomChange)=\"handleToolbarZoomChange($event)\"\n (screenWidthChange)=\"handleToolbarScreenWidthChange($event)\"\n (save)=\"save.emit()\"\n (preview)=\"preview.emit()\"\n (publishToggle)=\"publishToggle.emit()\"\n (undo)=\"undo.emit()\"\n (redo)=\"redo.emit()\">\n </app-toolbar>\n\n <div class=\"panel-switcher\">\n <button (click)=\"selectPanel(panelTypes.BINDINGS)\" [class.active]=\"activePanel === panelTypes.BINDINGS\" title=\"Bindings\">\n <i class=\"ph-thin ph-plugs-connected\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.STYLES)\" [class.active]=\"activePanel === panelTypes.STYLES\" title=\"Styles\">\n <i class=\"ph-thin ph-paint-brush\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.PAGE)\" [class.active]=\"activePanel === panelTypes.PAGE\" title=\"Page settings\" aria-label=\"Page settings\">\n <i class=\"ph-thin ph-gear-six\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.INTERACTIONS)\" [class.active]=\"activePanel === panelTypes.INTERACTIONS\" title=\"Interactions\">\n <i class=\"ph-thin ph-lightning\"></i>\n </button>\n </div> \n </header>\n\n <div class=\"builder-main\" [class.panel-open]=\"isPanelOpen\">\n <aside class=\"sidebar\">\n <div *ngIf=\"activeSidebar === 'pages'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderPages]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'components'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderComponents]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'tokens'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderTokens]\"></ng-content>\n </div>\n <app-layer-tree *ngIf=\"activeSidebar === 'tree'\"\n [layout]=\"layout\"\n [globalElements]=\"globalElements\"\n (nodeSelect)=\"onTreeNodeSelect($event)\"\n (nodeAction)=\"onTreeNodeAction($event)\"\n (nodeMove)=\"onTreeNodeMove()\"></app-layer-tree>\n </aside>\n\n <main #previewCanvas class=\"preview\"\n [class.grab-mode]=\"activeMode === builderModes.Pan\"\n [class.grabbing]=\"isPanning\"\n (click)=\"handleCanvasClick()\"\n (mousedown)=\"onBoardMouseDown($event)\"\n (mousemove)=\"onBoardMouseMove($event)\"\n (mouseup)=\"onBoardMouseUp()\"\n (mouseleave)=\"onBoardMouseUp()\">\n <app-overlay (toolbarAction)=\"onToolbarAction($event)\"></app-overlay>\n\n <!-- Element path \u2014 pinned to the PREVIEW VIEWPORT, not to the canvas frame. The frame\n pans and scales; a breadcrumb that tracked its edge would drift off-screen and\n shrink with zoom. Sits in the gutter above the frame (see $canvas-inset-block-start).\n\n \u26A0\uFE0F stopPropagation is REQUIRED, not defensive. This element lives inside .preview,\n whose (click) is handleCanvasClick() \u2014 \"you clicked empty canvas, drop the\n selection\". Without it, picking an ancestor crumb selects that node and then\n immediately bubbles into the canvas handler, which clears it: the selection and the\n layer-tree highlight both fall back to Body. Same reason .audit-dock stops its own. -->\n <app-breadcrumb-bar\n (click)=\"$event.stopPropagation()\"\n [path]=\"selectedPath\"\n (nodeSelect)=\"onCrumbSelect($event)\"\n (rootSelect)=\"onCrumbRootSelect()\"\n (nodePeek)=\"onCrumbPeek($event)\">\n </app-breadcrumb-bar>\n\n <!-- Responsive audit (A5) \u2014 floats over the canvas, right gutter. -->\n @if (auditOpen) {\n <div class=\"audit-dock\" (click)=\"$event.stopPropagation()\">\n <app-audit-panel\n [findings]=\"auditFindings\"\n [breakpointLabel]=\"auditBreakpointLabel\"\n [running]=\"auditRunning\"\n (select)=\"selectAuditNode($event)\"\n (fix)=\"applyAuditFix($event)\"\n (fixAll)=\"applyAllAuditFixes()\"\n (rerun)=\"runAudit()\"\n (closePanel)=\"toggleAudit()\"></app-audit-panel>\n </div>\n }\n\n <!-- Custom Lenis scrollbar \u2014 lives in .preview (not .preview-scroll) so it\n stays in the right gutter and never overlaps the canvas at large widths.\n No translateY counteract needed since it isn't inside the Lenis wrapper. -->\n <div class=\"canvas-scrollbar\"\n [class.visible]=\"isScrollbarVisible\">\n <div class=\"canvas-scrollbar-thumb\"\n [style.height.px]=\"scrollThumbHeight\"\n [style.top.px]=\"scrollThumbTop\">\n </div>\n </div>\n\n <!-- Global elements overlay \u2014 outside Lenis so position:fixed children\n stay pinned to the canvas viewport rather than scrolling with content.\n Shares viewportTransform so elements scale correctly at any zoom level.\n Height matches viewportHeight so position:fixed + inset:0 fills the\n simulated viewport correctly (CSS calc(100%) would give the wrong\n containing-block height and break full-screen fixed overlays). -->\n <div *ngIf=\"globalElements.length\"\n #globalOverlay\n class=\"global-elements-overlay\"\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n <ng-container *ngFor=\"let item of globalElementsBefore\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n <ng-container *ngFor=\"let item of globalElementsAfter\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n </div>\n\n <div class=\"preview-scroll\"\n #previewScroll\n [style.width.px]=\"viewportScaledWidth\"\n [class.pan-mode]=\"activeMode === builderModes.Pan\">\n\n <!-- Lenis content proxy: height = realContentHeight \u00D7 scale.\n Lenis scrolls against this value so scroll range is always in\n visual px \u2014 correct at any zoom level. -->\n <div class=\"preview-lenis-content\" #lenisContent\n [style.height.px]=\"scaledContentHeight\">\n\n <iox-page-component\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n\n <!-- ngStyle carries the page's own background/typography (pageSettings.style),\n compiled by the SAME function the engine applies to <body>. Inline wins over\n the #canvas-preview white default, which stays as the unset fallback. -->\n <div class=\"canvas-viewport\"\n id=\"canvas-preview\"\n [ngStyle]=\"pageStyleCss\"\n [style.min-height.px]=\"canvasMinHeight\">\n\n <!-- Empty page (B4): a starting point beats a blank canvas. Each starter is\n a responsive layout preset \u2014 ordinary nodes, editable afterwards. -->\n @if (isPageEmpty) {\n <div class=\"empty-canvas\" (click)=\"$event.stopPropagation()\">\n <h2 class=\"empty-title\">Start with a layout</h2>\n <p class=\"empty-sub\">Each one already adapts to tablet and phone. You can edit or take it apart afterwards.</p>\n <div class=\"empty-grid\">\n @for (starter of starterLayouts; track starter.id) {\n <button type=\"button\" class=\"empty-card\" (click)=\"startWithLayout(starter)\">\n <i [class]=\"starter.icon\" aria-hidden=\"true\"></i>\n <span class=\"empty-card-name\">{{ starter.name }}</span>\n <span class=\"empty-card-desc\">{{ starter.description }}</span>\n </button>\n }\n </div>\n <button type=\"button\" class=\"empty-link\" (click)=\"browseComponents()\">Or start from a single element</button>\n </div>\n }\n\n <!-- WRAPPER COLLAPSE (task 9c): top-level nodes render DIRECTLY into the\n canvas viewport \u2014 no .preview-node wrapper; iox-outer + drag move to the\n host (RenderDirective, via ioxDragSourceId). -->\n <ng-container *ngFor=\"let item of layout\"\n [ioxRender]=\"item\"\n [ioxDragSourceId]=\"'canvas-preview'\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </div>\n </iox-page-component>\n </div>\n </div>\n </main>\n\n <ng-content select=\"[builderPanel]\"></ng-content>\n </div>\n\n <!-- Save as Reusable Block dialog -->\n @if (showSaveBlockDialog) {\n <div class=\"save-block-backdrop\" (click)=\"cancelSaveBlock()\"></div>\n <div class=\"save-block-dialog\" (click)=\"$event.stopPropagation()\">\n <h4 class=\"save-block-title\">Save as Reusable Block</h4>\n <input class=\"save-block-input\"\n type=\"text\"\n placeholder=\"Block name...\"\n [(ngModel)]=\"saveBlockName\"\n (keydown.enter)=\"confirmSaveBlock()\"\n (keydown.escape)=\"cancelSaveBlock()\"\n autofocus>\n <div class=\"save-block-actions\">\n <p-button size=\"small\" severity=\"secondary\" label=\"Cancel\" (click)=\"cancelSaveBlock()\"></p-button>\n <p-button size=\"small\" label=\"Save\" [disabled]=\"!saveBlockName.trim()\" (click)=\"confirmSaveBlock()\"></p-button>\n </div>\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex:1;min-height:0;overflow:hidden}.builder{display:flex;flex-direction:column;direction:ltr;width:100%;height:100%;min-height:0;border-radius:0;overflow:hidden;position:relative}.builder .builder-header{background:var(--p-surface-0);padding:.375rem .75rem;border-bottom:1px solid var(--p-surface-200);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:.5rem;flex-shrink:0}.builder .builder-header .header-back{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;cursor:pointer;color:var(--p-text-muted-color);font-size:16px;transition:background .15s ease-out;margin-inline-end:.25rem}.builder .builder-header .header-back:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .builder-header .header-page-name{flex:1;text-align:center;font-size:.8rem;font-weight:500;color:var(--p-text-muted-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-inline:1rem}.builder .sidebar-switcher,.builder .panel-switcher{display:flex;gap:.25rem}.builder .sidebar-switcher button,.builder .panel-switcher button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.builder .sidebar-switcher button i,.builder .panel-switcher button i{pointer-events:none}.builder .sidebar-switcher button:hover,.builder .panel-switcher button:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .sidebar-switcher button.active,.builder .panel-switcher button.active{background:#cb9090;color:#fff}.builder .panel-switcher{justify-self:end}.builder .builder-main{display:flex;flex:1 1 0;min-height:0;position:relative;overflow:hidden}.builder .sidebar{width:260px;min-width:260px;background:var(--p-surface-0);border-inline-end:1px solid var(--p-surface-200);overflow-y:auto;overflow-x:hidden;flex-shrink:0}.builder .preview{flex:1 1 0;min-width:0;min-height:0;position:relative;overflow:hidden}.builder .preview.grab-mode{cursor:grab}.builder .preview.grab-mode iox-page-component{pointer-events:none}.builder .preview.grabbing{cursor:grabbing}.builder .canvas-scrollbar{position:absolute;right:4px;top:46px;bottom:20px;width:6px;z-index:20;opacity:0;transition:opacity .2s ease;pointer-events:none}.builder .canvas-scrollbar.visible{opacity:1}.builder .canvas-scrollbar-thumb{position:absolute;left:0;width:100%;background:#00000059;border-radius:3px;transition:top .05s linear}.builder .preview-scroll{position:absolute;inset:46px auto 20px;inset-inline-start:50%;transform:translate(-50%);max-width:calc(100% - 40px);height:calc(100% - 66px);overflow:hidden}.builder .preview-lenis-content{position:relative;width:100%;overflow:hidden;contain:paint}.builder iox-page-component{position:absolute!important;top:0;bottom:auto!important;right:auto!important;left:50%;transform-origin:top center;overflow:visible!important;container:iox-canvas/inline-size;box-shadow:0 1px 4px #00000014,0 4px 16px #0000000a;transition:width .25s ease,transform .25s ease}.builder iox-page-component ::ng-deep .iox-page-wrapper{height:auto!important;overflow:visible!important}.builder #canvas-preview{background:#fff}.builder .empty-canvas{max-inline-size:560px;margin:0 auto;padding:48px 24px;text-align:center;color:#4b5563}.builder .empty-title{margin:0;font-size:18px;font-weight:600;color:#111827}.builder .empty-sub{margin:6px 0 20px;font-size:12px;line-height:1.5;color:#6b7280}.builder .empty-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.builder .empty-card{display:flex;flex-direction:column;align-items:center;gap:4px;padding:14px 10px;border:1px solid #e5e7eb;border-radius:10px;background:#fff;cursor:pointer;transition:border-color .15s ease,box-shadow .15s ease}.builder .empty-card:hover{border-color:#cb9090;box-shadow:0 2px 10px #0000000f}.builder .empty-card:focus-visible{outline:2px solid #cb9090;outline-offset:2px}.builder .empty-card i{font-size:20px;color:#a05c5c}.builder .empty-card-name{font-size:11.5px;font-weight:600;color:#111827}.builder .empty-card-desc{font-size:9.5px;line-height:1.35;color:#6b7280}.builder .empty-link{margin-block-start:16px;padding:0;border:none;background:none;font-size:11px;color:#a05c5c;cursor:pointer}.builder .empty-link:hover{text-decoration:underline}.builder .empty-link:focus-visible{outline:2px solid #cb9090;outline-offset:2px}.builder app-breadcrumb-bar{position:absolute;inset-block-start:12px;inset-inline-start:20px;inset-inline-end:56px;z-index:20;pointer-events:none}.builder .audit-dock{position:absolute;inset-block-start:46px;inset-inline-end:16px;z-index:20}.builder .global-elements-overlay{position:absolute;top:46px;left:50%;transform-origin:top center;pointer-events:none;z-index:9;overflow:hidden;container:iox-canvas/inline-size}.builder .global-elements-overlay ::ng-deep>*{pointer-events:auto}.builder .preview-node.is-selected{cursor:grab}.builder .empty-state{min-height:240px;border:1px dashed var(--p-surface-200);border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--p-text-muted-color);text-align:center;padding:1rem}.save-block-backdrop{position:fixed;inset:0;z-index:1000;background:#00000040}.save-block-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#fff;border-radius:8px;box-shadow:0 8px 32px #0000002e;padding:24px;width:320px}.save-block-dialog .save-block-title{margin:0 0 16px;font-size:14px;font-weight:600;color:var(--p-text-color, #333)}.save-block-dialog .save-block-input{width:100%;padding:8px 10px;border:1px solid var(--p-surface-300, #d1d5db);border-radius:6px;font-size:13px;outline:none;box-sizing:border-box;margin-bottom:16px}.save-block-dialog .save-block-input:focus{border-color:#cb9090;box-shadow:0 0 0 2px #cb909033}.save-block-dialog .save-block-actions{display:flex;justify-content:flex-end;gap:8px}::ng-deep .moveable-control-box.iox-moveable-silent{z-index:1000!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-line,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation-line{display:none!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-control{display:block!important;width:10px!important;height:10px!important;margin-top:-5px!important;margin-left:-5px!important;background:#fff!important;border:1.5px solid #cb9090!important;border-radius:2px!important;box-shadow:0 1px 3px #0003!important}\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: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i16.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: i16.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i16.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i17.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2$2.IoxPageComponent, selector: "iox-page-component", inputs: ["class"], outputs: ["scrollEvent"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "component", type: OverlayComponent, selector: "app-overlay", outputs: ["toolbarAction"] }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["activeMode", "activeBreakpoint", "breakpointCounts", "auditCount", "auditOpen", "activeZoom", "activeScreenWidth", "canUndo", "canRedo", "isSaving", "pageStatus"], outputs: ["modeChange", "breakpointChange", "auditToggle", "zoomChange", "screenWidthChange", "undo", "redo", "save", "preview", "publishToggle"] }, { kind: "component", type: LayerTreeComponent, selector: "app-layer-tree", inputs: ["layout", "globalElements"], outputs: ["nodeSelect", "nodeAction", "nodeMove"] }, { kind: "component", type: BreadcrumbBarComponent, selector: "app-breadcrumb-bar", inputs: ["path"], outputs: ["nodeSelect", "rootSelect", "nodePeek"] }, { kind: "component", type: AuditPanelComponent, selector: "app-audit-panel", inputs: ["findings", "breakpointLabel", "running"], outputs: ["select", "fix", "fixAll", "rerun", "closePanel"] }] }); }
|
|
7214
7298
|
}
|
|
7215
7299
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderComponent, decorators: [{
|
|
7216
7300
|
type: Component,
|
|
@@ -8277,6 +8361,166 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
|
|
|
8277
8361
|
type: Output
|
|
8278
8362
|
}] } });
|
|
8279
8363
|
|
|
8364
|
+
/**
|
|
8365
|
+
* The Dialog's CANVAS twin (actions plan A1b / boards A4–A5). Two render strategies, one model:
|
|
8366
|
+
* the live site uses a real `<dialog>` (top layer); here the overlay is `position: fixed`, which
|
|
8367
|
+
* a transformed ancestor CONTAINS — so it fills the page frame, not the admin viewport, at every
|
|
8368
|
+
* zoom. Closed it renders as a compact chip in flow (A4's "closed later? reopen from the chip"),
|
|
8369
|
+
* and a freshly dropped EMPTY dialog opens itself — you land designing it, not hunting it.
|
|
8370
|
+
* Open/close/toggle actions reach it through the instance registry, same as Swiper's methods.
|
|
8371
|
+
*/
|
|
8372
|
+
class BuilderDialogComponent {
|
|
8373
|
+
constructor(dragEngine, instanceRegistry, cdr) {
|
|
8374
|
+
this.dragEngine = dragEngine;
|
|
8375
|
+
this.instanceRegistry = instanceRegistry;
|
|
8376
|
+
this.cdr = cdr;
|
|
8377
|
+
this.children = [];
|
|
8378
|
+
this.style = {};
|
|
8379
|
+
this.nodeId = '';
|
|
8380
|
+
this.dropListId = '';
|
|
8381
|
+
this.closeOnBackdrop = true;
|
|
8382
|
+
this.showCloseButton = true;
|
|
8383
|
+
this.childClick = new EventEmitter();
|
|
8384
|
+
this.childMouseEnter = new EventEmitter();
|
|
8385
|
+
this.childMouseLeave = new EventEmitter();
|
|
8386
|
+
/** Canvas-only visibility. Never serialised; the live site always starts closed. */
|
|
8387
|
+
this.designOpen = false;
|
|
8388
|
+
}
|
|
8389
|
+
ngOnInit() {
|
|
8390
|
+
// A freshly dropped EMPTY dialog opens itself — "lands open" (board A4).
|
|
8391
|
+
this.designOpen = this.children.length === 0;
|
|
8392
|
+
// Open/close/toggle actions (and A1c's panel) reach the canvas twin through here.
|
|
8393
|
+
this.instanceRegistry.register(this.nodeId, {
|
|
8394
|
+
open: () => { this.designOpen = true; this.cdr.markForCheck(); },
|
|
8395
|
+
close: () => { this.designOpen = false; this.cdr.markForCheck(); },
|
|
8396
|
+
toggle: () => { this.designOpen = !this.designOpen; this.cdr.markForCheck(); },
|
|
8397
|
+
isOpen: () => this.designOpen,
|
|
8398
|
+
});
|
|
8399
|
+
}
|
|
8400
|
+
ngOnDestroy() {
|
|
8401
|
+
this.instanceRegistry.unregister(this.nodeId);
|
|
8402
|
+
}
|
|
8403
|
+
onBackdrop() {
|
|
8404
|
+
if (this.closeOnBackdrop !== false && this.closeOnBackdrop !== 'false')
|
|
8405
|
+
this.designOpen = false;
|
|
8406
|
+
}
|
|
8407
|
+
onDrop(event) {
|
|
8408
|
+
this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr);
|
|
8409
|
+
}
|
|
8410
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDialogComponent, deps: [{ token: DragEngineService }, { token: i2$2.ComponentInstanceRegistryService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8411
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: BuilderDialogComponent, isStandalone: false, selector: "app-builder-dialog", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", closeOnBackdrop: "closeOnBackdrop", showCloseButton: "showCloseButton" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
|
|
8412
|
+
<div *ngIf="!designOpen"
|
|
8413
|
+
class="dialog-chip"
|
|
8414
|
+
role="button"
|
|
8415
|
+
tabindex="0"
|
|
8416
|
+
[attr.aria-label]="'Open dialog for editing'"
|
|
8417
|
+
(click)="designOpen = true"
|
|
8418
|
+
(keydown.enter)="designOpen = true">
|
|
8419
|
+
<i class="ph-thin ph-browser"></i>
|
|
8420
|
+
<span class="dialog-chip-label">Dialog</span>
|
|
8421
|
+
<i class="ph-thin ph-eye dialog-chip-eye"></i>
|
|
8422
|
+
</div>
|
|
8423
|
+
|
|
8424
|
+
<div *ngIf="designOpen" class="dialog-stage">
|
|
8425
|
+
<div class="dialog-backdrop" (click)="onBackdrop()"></div>
|
|
8426
|
+
<div [ngStyle]="style"
|
|
8427
|
+
[ngClass]="'iox-node-' + nodeId"
|
|
8428
|
+
class="dialog-surface"
|
|
8429
|
+
ioxDropzone
|
|
8430
|
+
[ioxDropzoneId]="dropListId"
|
|
8431
|
+
[ioxDropzoneData]="children"
|
|
8432
|
+
(ioxDrop)="onDrop($event)">
|
|
8433
|
+
<button *ngIf="showCloseButton"
|
|
8434
|
+
type="button"
|
|
8435
|
+
class="dialog-close"
|
|
8436
|
+
aria-label="Close dialog"
|
|
8437
|
+
(click)="designOpen = false">
|
|
8438
|
+
<i class="ph-thin ph-x"></i>
|
|
8439
|
+
</button>
|
|
8440
|
+
|
|
8441
|
+
<div *ngIf="!children.length" class="dialog-placeholder">
|
|
8442
|
+
<i class="ph-thin ph-browser"></i>
|
|
8443
|
+
<span>Drop components here</span>
|
|
8444
|
+
</div>
|
|
8445
|
+
|
|
8446
|
+
<ng-container *ngFor="let child of children"
|
|
8447
|
+
[ioxRender]="child"
|
|
8448
|
+
[ioxDragSourceId]="dropListId"
|
|
8449
|
+
(onClick)="childClick.emit($event)"
|
|
8450
|
+
(onMouseEnter)="childMouseEnter.emit($event)"
|
|
8451
|
+
(onMouseLeave)="childMouseLeave.emit()">
|
|
8452
|
+
</ng-container>
|
|
8453
|
+
</div>
|
|
8454
|
+
</div>
|
|
8455
|
+
`, isInline: true, styles: [".dialog-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border:1.5px dashed rgba(203,144,144,.6);border-radius:999px;color:#a05c5c;font-size:12px;cursor:pointer;-webkit-user-select:none;user-select:none;background:#cb90900f}.dialog-chip i{font-size:14px}.dialog-chip-eye{opacity:.7}.dialog-stage{position:fixed;inset:0;z-index:50}.dialog-backdrop{position:absolute;inset:0;background:#0f172a73}.dialog-surface{position:absolute;inset-inline-start:50%;top:50%;transform:translate(-50%,-50%);box-sizing:border-box;max-width:calc(100% - 48px);max-height:calc(100% - 48px);overflow:auto}:host-context([dir=\"rtl\"]) .dialog-surface{transform:translate(50%,-50%)}.dialog-close{position:absolute;inset-inline-end:10px;top:10px;width:26px;height:26px;border:none;border-radius:999px;background:#0f172a0f;color:inherit;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.dialog-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:90px;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px}.dialog-placeholder i{font-size:18px}\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"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
|
|
8456
|
+
}
|
|
8457
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDialogComponent, decorators: [{
|
|
8458
|
+
type: Component,
|
|
8459
|
+
args: [{ selector: 'app-builder-dialog', template: `
|
|
8460
|
+
<div *ngIf="!designOpen"
|
|
8461
|
+
class="dialog-chip"
|
|
8462
|
+
role="button"
|
|
8463
|
+
tabindex="0"
|
|
8464
|
+
[attr.aria-label]="'Open dialog for editing'"
|
|
8465
|
+
(click)="designOpen = true"
|
|
8466
|
+
(keydown.enter)="designOpen = true">
|
|
8467
|
+
<i class="ph-thin ph-browser"></i>
|
|
8468
|
+
<span class="dialog-chip-label">Dialog</span>
|
|
8469
|
+
<i class="ph-thin ph-eye dialog-chip-eye"></i>
|
|
8470
|
+
</div>
|
|
8471
|
+
|
|
8472
|
+
<div *ngIf="designOpen" class="dialog-stage">
|
|
8473
|
+
<div class="dialog-backdrop" (click)="onBackdrop()"></div>
|
|
8474
|
+
<div [ngStyle]="style"
|
|
8475
|
+
[ngClass]="'iox-node-' + nodeId"
|
|
8476
|
+
class="dialog-surface"
|
|
8477
|
+
ioxDropzone
|
|
8478
|
+
[ioxDropzoneId]="dropListId"
|
|
8479
|
+
[ioxDropzoneData]="children"
|
|
8480
|
+
(ioxDrop)="onDrop($event)">
|
|
8481
|
+
<button *ngIf="showCloseButton"
|
|
8482
|
+
type="button"
|
|
8483
|
+
class="dialog-close"
|
|
8484
|
+
aria-label="Close dialog"
|
|
8485
|
+
(click)="designOpen = false">
|
|
8486
|
+
<i class="ph-thin ph-x"></i>
|
|
8487
|
+
</button>
|
|
8488
|
+
|
|
8489
|
+
<div *ngIf="!children.length" class="dialog-placeholder">
|
|
8490
|
+
<i class="ph-thin ph-browser"></i>
|
|
8491
|
+
<span>Drop components here</span>
|
|
8492
|
+
</div>
|
|
8493
|
+
|
|
8494
|
+
<ng-container *ngFor="let child of children"
|
|
8495
|
+
[ioxRender]="child"
|
|
8496
|
+
[ioxDragSourceId]="dropListId"
|
|
8497
|
+
(onClick)="childClick.emit($event)"
|
|
8498
|
+
(onMouseEnter)="childMouseEnter.emit($event)"
|
|
8499
|
+
(onMouseLeave)="childMouseLeave.emit()">
|
|
8500
|
+
</ng-container>
|
|
8501
|
+
</div>
|
|
8502
|
+
</div>
|
|
8503
|
+
`, standalone: false, styles: [".dialog-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border:1.5px dashed rgba(203,144,144,.6);border-radius:999px;color:#a05c5c;font-size:12px;cursor:pointer;-webkit-user-select:none;user-select:none;background:#cb90900f}.dialog-chip i{font-size:14px}.dialog-chip-eye{opacity:.7}.dialog-stage{position:fixed;inset:0;z-index:50}.dialog-backdrop{position:absolute;inset:0;background:#0f172a73}.dialog-surface{position:absolute;inset-inline-start:50%;top:50%;transform:translate(-50%,-50%);box-sizing:border-box;max-width:calc(100% - 48px);max-height:calc(100% - 48px);overflow:auto}:host-context([dir=\"rtl\"]) .dialog-surface{transform:translate(50%,-50%)}.dialog-close{position:absolute;inset-inline-end:10px;top:10px;width:26px;height:26px;border:none;border-radius:999px;background:#0f172a0f;color:inherit;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.dialog-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:90px;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px}.dialog-placeholder i{font-size:18px}\n"] }]
|
|
8504
|
+
}], ctorParameters: () => [{ type: DragEngineService }, { type: i2$2.ComponentInstanceRegistryService }, { type: i0.ChangeDetectorRef }], propDecorators: { children: [{
|
|
8505
|
+
type: Input
|
|
8506
|
+
}], style: [{
|
|
8507
|
+
type: Input
|
|
8508
|
+
}], nodeId: [{
|
|
8509
|
+
type: Input
|
|
8510
|
+
}], dropListId: [{
|
|
8511
|
+
type: Input
|
|
8512
|
+
}], closeOnBackdrop: [{
|
|
8513
|
+
type: Input
|
|
8514
|
+
}], showCloseButton: [{
|
|
8515
|
+
type: Input
|
|
8516
|
+
}], childClick: [{
|
|
8517
|
+
type: Output
|
|
8518
|
+
}], childMouseEnter: [{
|
|
8519
|
+
type: Output
|
|
8520
|
+
}], childMouseLeave: [{
|
|
8521
|
+
type: Output
|
|
8522
|
+
}] } });
|
|
8523
|
+
|
|
8280
8524
|
class SliderContainerComponent {
|
|
8281
8525
|
set style(v) {
|
|
8282
8526
|
if (v === this._style)
|
|
@@ -9318,6 +9562,7 @@ const DECLARATIONS = [
|
|
|
9318
9562
|
BuilderLinkedContainerComponent,
|
|
9319
9563
|
BuilderRepeaterComponent,
|
|
9320
9564
|
BuilderButtonBlockComponent,
|
|
9565
|
+
BuilderDialogComponent,
|
|
9321
9566
|
SliderContainerComponent,
|
|
9322
9567
|
SliderSlideComponent,
|
|
9323
9568
|
PanelComponent,
|
|
@@ -9339,6 +9584,7 @@ class IoxBuilderModule {
|
|
|
9339
9584
|
BuilderLinkedContainerComponent,
|
|
9340
9585
|
BuilderRepeaterComponent,
|
|
9341
9586
|
BuilderButtonBlockComponent,
|
|
9587
|
+
BuilderDialogComponent,
|
|
9342
9588
|
SliderContainerComponent,
|
|
9343
9589
|
SliderSlideComponent,
|
|
9344
9590
|
PanelComponent,
|
|
@@ -9380,6 +9626,7 @@ class IoxBuilderModule {
|
|
|
9380
9626
|
BuilderLinkedContainerComponent,
|
|
9381
9627
|
BuilderRepeaterComponent,
|
|
9382
9628
|
BuilderButtonBlockComponent,
|
|
9629
|
+
BuilderDialogComponent,
|
|
9383
9630
|
SliderContainerComponent,
|
|
9384
9631
|
SliderSlideComponent,
|
|
9385
9632
|
PanelComponent,
|
|
@@ -9486,6 +9733,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
|
|
|
9486
9733
|
BuilderLinkedContainerComponent,
|
|
9487
9734
|
BuilderRepeaterComponent,
|
|
9488
9735
|
BuilderButtonBlockComponent,
|
|
9736
|
+
BuilderDialogComponent,
|
|
9489
9737
|
SliderContainerComponent,
|
|
9490
9738
|
SliderSlideComponent,
|
|
9491
9739
|
PanelComponent,
|
|
@@ -9672,6 +9920,36 @@ function setTrait(node, name, value) {
|
|
|
9672
9920
|
trait.default = value;
|
|
9673
9921
|
}
|
|
9674
9922
|
|
|
9923
|
+
/**
|
|
9924
|
+
* Dialog (actions plan A1b) — an ordinary container whose children are normal nodes, rendered
|
|
9925
|
+
* on the live site as a real `<dialog>` (top layer, free focus trap/Esc) and in the CANVAS as a
|
|
9926
|
+
* fixed-position overlay contained by the transformed frame (a transform is a containing block
|
|
9927
|
+
* for fixed descendants — the deliberate two-strategy split, see actions plan §6a).
|
|
9928
|
+
* Ships CLOSED on the live site always; opened only by the dialog actions.
|
|
9929
|
+
*/
|
|
9930
|
+
class DialogComponentConfig extends ComponentConfig {
|
|
9931
|
+
constructor() {
|
|
9932
|
+
super('Dialog', 'app-builder-dialog', 'ph-thin ph-browser', 'Overlay');
|
|
9933
|
+
this.children = [];
|
|
9934
|
+
this.inputs = {
|
|
9935
|
+
closeOnBackdrop: 'checkbox',
|
|
9936
|
+
showCloseButton: 'checkbox',
|
|
9937
|
+
};
|
|
9938
|
+
this.traits = [
|
|
9939
|
+
new TraitConfig('closeOnBackdrop', 'Close on backdrop', TraitInputType.Checkbox, undefined, true),
|
|
9940
|
+
new TraitConfig('showCloseButton', 'Close button', TraitInputType.Checkbox, undefined, true),
|
|
9941
|
+
];
|
|
9942
|
+
this.styleTraits = buildFullStyleTraits();
|
|
9943
|
+
this.applyStyleDefaults({
|
|
9944
|
+
width: '480px',
|
|
9945
|
+
backgroundColor: '#ffffff',
|
|
9946
|
+
borderRadius: '12px',
|
|
9947
|
+
padding: '24px',
|
|
9948
|
+
boxShadow: '0 18px 40px rgba(0, 0, 0, 0.22)',
|
|
9949
|
+
});
|
|
9950
|
+
}
|
|
9951
|
+
}
|
|
9952
|
+
|
|
9675
9953
|
class BuilderButtonComponentConfig extends ComponentConfig {
|
|
9676
9954
|
constructor() {
|
|
9677
9955
|
super('Button', 'app-builder-button', 'ph-thin ph-cursor-click', 'Basic');
|
|
@@ -10488,5 +10766,5 @@ class BuilderSpacerComponentConfig extends ComponentConfig {
|
|
|
10488
10766
|
* Generated bundle index. Do not edit.
|
|
10489
10767
|
*/
|
|
10490
10768
|
|
|
10491
|
-
export { ACTION_TYPE_OPTIONS, AuditCode, AuditPanelComponent, AuditSeverity, BODY_CRUMB_LABEL, BREAKPOINT_PRESENTATION, BUILDER_CANVAS_CONTAINER, BUILDER_CHROME_EN, BackgroundGroupStyleConfig, BorderGroupStyleConfig, BreadcrumbBarComponent, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderClipboardService, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDataSourceService, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderHistoryService, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ChildLayoutGroupStyleConfig, ComponentConfig, ComponentRegistryService, DEFAULT_ESSENTIAL_TRAITS, DRAG_HANDLE_ATTR, DataSourceRegistryService, DataSourceType, DimensionsGroupStyleConfig, DragEngineService, EASING_OPTIONS$1 as EASING_OPTIONS, ESSENTIAL_TRAITS_BY_TYPE, EffectsGroupStyleConfig, FIELD_PARTS, FORM_PRESETS, FORM_TYPE, FieldComponentConfig, FieldGroupComponentConfig, FormComponentConfig, FormErrorComponentConfig, FormStateService, FormSuccessComponentConfig, GalleryConfig, GroupStyleConfig, INTERACTION_STATES, INVERSE_ACTION, IOX_BUILDER_LABELS, IOX_DATA_SOURCE_ENDPOINTS, IOX_FONT_MANAGER, InteractionEngineService, InteractionPresetRegistryService, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LAYOUT_PRESETS, 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, SubmitButtonComponentConfig, SymbolRegistryService, TARGETED_STATES, TARGETED_STATE_BASE, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, TypographyGroupStyleConfig, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, VALIDATION_STATES, VALIDATION_STATE_CLASS, ViewportService, ZOOM_OPTIONS, arrayItemSchemaFields, arraySchemaFields, auditNodes, buildFormPreset, buildFullStyleTraits, buildLayoutPreset, buildPresetStyleTraits, canFluidise, collapseColumnsProps, columnCountOf, defaultBuilderLabels, defaultPageSettings, dropTargetLabel, essentialTraitsFor, findNodeLocation, findParentOf, flattenSchemaFields, fluidiseProps, generateNodeId, isHiddenAt, matchesControlSearch, nearestFormNode, nodeAncestorPath, nodeAncestorPathInEither, reorderProps, resolveInsertTarget, resolveTraitControllerType, resolveTraitOptions, setStyleTrait, stackChildrenProps, summarise, visibilityProps, wrapNode };
|
|
10769
|
+
export { ACTION_TYPE_OPTIONS, AuditCode, AuditPanelComponent, AuditSeverity, BODY_CRUMB_LABEL, BREAKPOINT_PRESENTATION, BUILDER_CANVAS_CONTAINER, BUILDER_CHROME_EN, BackgroundGroupStyleConfig, BorderGroupStyleConfig, BreadcrumbBarComponent, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderClipboardService, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDataSourceService, BuilderDialogComponent, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderHistoryService, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ChildLayoutGroupStyleConfig, ComponentConfig, ComponentRegistryService, DEFAULT_ESSENTIAL_TRAITS, DRAG_HANDLE_ATTR, DataSourceRegistryService, DataSourceType, DialogComponentConfig, DimensionsGroupStyleConfig, DragEngineService, EASING_OPTIONS$1 as EASING_OPTIONS, ESSENTIAL_TRAITS_BY_TYPE, EffectsGroupStyleConfig, FIELD_PARTS, FORM_PRESETS, FORM_TYPE, FieldComponentConfig, FieldGroupComponentConfig, FormComponentConfig, FormErrorComponentConfig, FormStateService, FormSuccessComponentConfig, GalleryConfig, GroupStyleConfig, INTERACTION_STATES, INVERSE_ACTION, IOX_BUILDER_LABELS, IOX_DATA_SOURCE_ENDPOINTS, IOX_FONT_MANAGER, InteractionEngineService, InteractionPresetRegistryService, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LAYOUT_PRESETS, 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, SubmitButtonComponentConfig, SymbolRegistryService, TARGETED_STATES, TARGETED_STATE_BASE, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, TypographyGroupStyleConfig, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, VALIDATION_STATES, VALIDATION_STATE_CLASS, ViewportService, ZOOM_OPTIONS, arrayItemSchemaFields, arraySchemaFields, auditNodes, buildFormPreset, buildFullStyleTraits, buildLayoutPreset, buildPresetStyleTraits, canFluidise, collapseColumnsProps, columnCountOf, defaultBuilderLabels, defaultPageSettings, dropTargetLabel, essentialTraitsFor, findNodeLocation, findParentOf, flattenSchemaFields, fluidiseProps, generateNodeId, isHiddenAt, matchesControlSearch, nearestFormNode, nodeAncestorPath, nodeAncestorPathInEither, reorderProps, resolveInsertTarget, resolveTraitControllerType, resolveTraitOptions, setStyleTrait, stackChildrenProps, summarise, visibilityProps, wrapNode };
|
|
10492
10770
|
//# sourceMappingURL=vectoriox-iox-builder.mjs.map
|