@vectoriox/iox-builder 11.4.0 → 11.5.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.
@@ -25,7 +25,7 @@ import { Subject, BehaviorSubject, of, forkJoin } from 'rxjs';
25
25
  import interact from 'interactjs';
26
26
  import { map, catchError } from 'rxjs/operators';
27
27
  import * as i1 from '@angular/common/http';
28
- import { itemActionOf, BEHAVIOUR_ACTION_TYPES, SERVER_ELEMENT_ACTION_TYPES, CONSENT_ACTION_TYPES, opensAtClickedItem } from '@vectoriox/iox-ui/actions-core';
28
+ import { itemActionOf, BEHAVIOUR_ACTION_TYPES, SERVER_ELEMENT_ACTION_TYPES, CONSENT_ACTION_TYPES, opensAtClickedItem, openedDialogId, DIALOG_CLOSING_ATTRIBUTE, cancelExit, runExitMotion } from '@vectoriox/iox-ui/actions-core';
29
29
  import Lenis from 'lenis';
30
30
  import Moveable from 'moveable';
31
31
  import Selecto from 'selecto';
@@ -931,6 +931,9 @@ var PanelEventTypes;
931
931
  * through also runs. This event is that path for code outside `BuilderComponent` itself,
932
932
  * mirroring what `onTreeNodeSelect`/`onCrumbSelect` already do internally. */
933
933
  PanelEventTypes["SELECT_NODE"] = "selectnode";
934
+ /** A canvas Dialog closed while the selection sat in it (data = { dialogId }): the builder moves the selection
935
+ * to the dialog's opener (the menu button), else clears it — never left on an element leaving the DOM. */
936
+ PanelEventTypes["DIALOG_CLOSED_OVER_SELECTION"] = "dialogclosedoverselection";
934
937
  /** A panel rewrote a node's SUBTREE in place — its children (a Card's Parts), its layout styles (Card ▸
935
938
  * Layout), a part's element style or scheme. Carries `{ node }`. The builder re-renders the subtree,
936
939
  * re-registers every node's rules and design classes, refreshes a Repeater holding it, and records ONE
@@ -4891,18 +4894,21 @@ class CanvasDesignStateService {
4891
4894
  return;
4892
4895
  this._state$.next({ ...this._state$.value, revealed, pinned, selectedTriggers, triggeredBySelection });
4893
4896
  }
4894
- /** Closed on the canvas (its X, its backdrop, the eye): no longer pinned or switched open. */
4897
+ /** Closed on the canvas (its X, its backdrop, the eye): no longer pinned, switched open or revealed by the
4898
+ * selection — selecting into it again reveals it again. */
4895
4899
  dismiss(nodeId) {
4896
4900
  if (!nodeId)
4897
4901
  return;
4898
- const { pinned, shown } = this._state$.value;
4899
- if (!pinned.has(nodeId) && !shown.has(nodeId))
4902
+ const { pinned, shown, revealed } = this._state$.value;
4903
+ if (!pinned.has(nodeId) && !shown.has(nodeId) && !revealed.has(nodeId))
4900
4904
  return;
4901
4905
  const nextPinned = new Set(pinned);
4902
4906
  nextPinned.delete(nodeId);
4903
4907
  const nextShown = new Map(shown);
4904
4908
  nextShown.delete(nodeId);
4905
- this._state$.next({ ...this._state$.value, pinned: nextPinned, shown: nextShown });
4909
+ const nextRevealed = new Set(revealed);
4910
+ nextRevealed.delete(nodeId);
4911
+ this._state$.next({ ...this._state$.value, pinned: nextPinned, shown: nextShown, revealed: nextRevealed });
4906
4912
  }
4907
4913
  /** The switcher's choice for one part (null = back to the saved default). */
4908
4914
  setShown(nodeId, state) {
@@ -6649,6 +6655,45 @@ function preventNativeCanvasDrag(event) {
6649
6655
  event.preventDefault();
6650
6656
  }
6651
6657
 
6658
+ /** The panels that describe the SELECTED ELEMENT: selecting another element keeps whichever of these is open. */
6659
+ const ELEMENT_PANELS = new Set([PanelTypes.BINDINGS, PanelTypes.STYLES, PanelTypes.INTERACTIONS]);
6660
+ /**
6661
+ * The panel a selection shows. An element panel that is open stays (the author wiring Interactions across
6662
+ * several elements is not thrown back to Styles on every click); with the Page panel open, or none, the
6663
+ * element's Styles open.
6664
+ */
6665
+ function panelForSelection(activePanel, isPanelOpen) {
6666
+ return isPanelOpen && activePanel && ELEMENT_PANELS.has(activePanel) ? activePanel : PanelTypes.STYLES;
6667
+ }
6668
+
6669
+ /**
6670
+ * The node whose click opens `dialogId` (the menu button for a drawer, More for a bar's drawer) — where the
6671
+ * canvas selection goes when the dialog it sat in closes. The first in tree order across the page and its
6672
+ * globals, or null when nothing opens it.
6673
+ */
6674
+ function findDialogOpener(trees, dialogId) {
6675
+ const visit = (nodes) => {
6676
+ for (const node of nodes ?? []) {
6677
+ if (openedDialogId(node) === dialogId)
6678
+ return node;
6679
+ const hit = visit(node.children);
6680
+ if (hit)
6681
+ return hit;
6682
+ }
6683
+ return null;
6684
+ };
6685
+ for (const tree of trees) {
6686
+ const hit = visit(tree);
6687
+ if (hit)
6688
+ return hit;
6689
+ }
6690
+ return null;
6691
+ }
6692
+ /** True when the element sits in a dialog that is playing its exit (actions-core `runExitMotion` marks it). */
6693
+ function isInsideExit(el) {
6694
+ return !!el?.closest?.(`[${DIALOG_CLOSING_ATTRIBUTE}]`);
6695
+ }
6696
+
6652
6697
  /** States whose rule needs the LIVE DOM to scope (a parent's / a trigger's id) — the RenderDirective owns them. */
6653
6698
  const DOM_SCOPED_STATES = new Set([...RELATIONAL_STATES, ...TARGETED_STATES]);
6654
6699
  /** A node's base style map, from its style traits (the live values the Style panel edits). */
@@ -7485,6 +7530,19 @@ function compositePartSub(node, ancestors = []) {
7485
7530
  return null;
7486
7531
  }
7487
7532
 
7533
+ /** Hides a piece of selection / hover chrome without dropping the entry it describes. */
7534
+ const HIDDEN_CHROME = Object.freeze({ display: 'none' });
7535
+ /**
7536
+ * True when the element is in the document and draws a box the chrome can point at. A node whose element left
7537
+ * the DOM (a part of a canvas dialog that just closed) or draws nothing (`display: contents`, a closed dialog's
7538
+ * host) measures 0×0 at the viewport's corner — chrome drawn from that rect lands at the top-left of the screen.
7539
+ */
7540
+ function hasRenderedBox(el, rect) {
7541
+ if (!el?.isConnected || !rect)
7542
+ return false;
7543
+ return rect.width > 0 || rect.height > 0;
7544
+ }
7545
+
7488
7546
  /**
7489
7547
  * PresetRegistryService — in-memory store for org-level style presets.
7490
7548
  *
@@ -8062,6 +8120,12 @@ class OverlayComponent {
8062
8120
  }
8063
8121
  const styledEl = this.overlayService.getStyledElement(this.hoverEntry.element);
8064
8122
  const rect = styledEl.getBoundingClientRect();
8123
+ if (!hasRenderedBox(styledEl, rect)) {
8124
+ this.hiOutlineStyle = HIDDEN_CHROME;
8125
+ this.hiMarginStyle = HIDDEN_CHROME;
8126
+ this.hiPaddingStyle = HIDDEN_CHROME;
8127
+ return;
8128
+ }
8065
8129
  // Recalculate fresh — stored boxModel can be stale if CSS rules changed.
8066
8130
  const { margin, border, padding } = this.overlayService.buildBoxModel(this.hoverEntry.element);
8067
8131
  // All overlay boxes use position:fixed with raw viewport coords from
@@ -8104,6 +8168,12 @@ class OverlayComponent {
8104
8168
  }
8105
8169
  const styledEl = this.overlayService.getStyledElement(this.selectEntry.element);
8106
8170
  const rect = styledEl.getBoundingClientRect();
8171
+ // An element that left the DOM (a part of a dialog that just closed) or draws no box measures 0,0 — the
8172
+ // outline and its toolbar would sit at the viewport's corner. Nothing to point at: no chrome.
8173
+ if (!hasRenderedBox(styledEl, rect)) {
8174
+ this.selectOutlineStyle = HIDDEN_CHROME;
8175
+ return;
8176
+ }
8107
8177
  // position:fixed with raw viewport coords — same reasoning as updateHover.
8108
8178
  this.selectOutlineStyle = this.createBoxStyle(rect.top, rect.left, rect.width, rect.height);
8109
8179
  // The breadcrumb band begins at the canvas area's top (our own host). A toolbar rendered
@@ -9829,12 +9899,20 @@ class BuilderComponent {
9829
9899
  this.activePanel = panel;
9830
9900
  this.panelEventService.emit(this.isPanelOpen ? PanelEventTypes.PANEL_SELECTED : PanelEventTypes.PANEL_OPEN, panel);
9831
9901
  }
9902
+ /** A new element was selected: keep the element panel that is open, else open Styles (`panelForSelection`). */
9903
+ selectPanelForElement() {
9904
+ this.selectPanel(panelForSelection(this.activePanel, this.isPanelOpen));
9905
+ }
9832
9906
  handleClick(event) {
9833
9907
  if (this.activeMode === BuilderMode.Pan)
9834
9908
  return;
9909
+ // The canvas is live: a click on a dialog's Close ran its closeDialog first (capture). Selecting into the
9910
+ // closing dialog would reveal it again (R2) and leave the selection on an element about to leave the DOM.
9911
+ if (isInsideExit(event.element))
9912
+ return;
9835
9913
  this.selectedItem = event.node;
9836
9914
  this.overlayService.setSelect(event.element, event.node.type, this.activeMode, event.node, event.componentRef, event.fromRow ?? null);
9837
- this.selectPanel(PanelTypes.STYLES);
9915
+ this.selectPanelForElement();
9838
9916
  this._emitElementSelect(event.node, event.componentRef);
9839
9917
  }
9840
9918
  /**
@@ -9861,7 +9939,7 @@ class BuilderComponent {
9861
9939
  return;
9862
9940
  this.selectedItem = node;
9863
9941
  this.overlayService.setSelect(ref.element, node.type, this.activeMode, node, ref.componentRef);
9864
- this.selectPanel(PanelTypes.STYLES);
9942
+ this.selectPanelForElement();
9865
9943
  this._emitElementSelect(node, ref.componentRef);
9866
9944
  });
9867
9945
  }
@@ -9894,6 +9972,26 @@ class BuilderComponent {
9894
9972
  this.overlayService.clearSelect();
9895
9973
  this.refreshBreakpointCounts();
9896
9974
  }
9975
+ /**
9976
+ * The canvas Dialog the selection sat in closed (its Close, the backdrop, the eye): the selection moves to its
9977
+ * opener — the menu button that opened the drawer — or, when nothing opens it, off the canvas. Never left on an
9978
+ * element that is leaving the DOM (its chrome drew at the viewport's corner), and never on the dialog itself,
9979
+ * which selecting would open again.
9980
+ */
9981
+ selectAfterDialogClosed(dialogId) {
9982
+ const opener = dialogId ? findDialogOpener([this.layout, this.globalElements], dialogId) : null;
9983
+ const ref = opener ? this.overlayService.getNodeRef(opener) : null;
9984
+ if (opener && ref?.element?.isConnected) {
9985
+ this.selectedItem = opener;
9986
+ this.overlayService.setSelect(ref.element, opener.type, this.activeMode, opener, ref.componentRef);
9987
+ this._emitElementSelect(opener, ref.componentRef);
9988
+ return;
9989
+ }
9990
+ this.selectedItem = null;
9991
+ this.selectedPath = [];
9992
+ this.overlayService.clearSelect();
9993
+ this.panelEventService.emit(PanelEventTypes.ELEMENT_DESELECT, null);
9994
+ }
9897
9995
  /** Breadcrumb crumb clicked — select that ancestor. Mirrors a layer-tree click. */
9898
9996
  onCrumbSelect(node) {
9899
9997
  this._withNodeRef(node, ref => {
@@ -9932,7 +10030,7 @@ class BuilderComponent {
9932
10030
  this.overlayService.setSelect(ref.element, node.type, this.activeMode, node, ref.componentRef);
9933
10031
  this._emitElementSelect(node, ref.componentRef);
9934
10032
  });
9935
- this.selectPanel(PanelTypes.STYLES);
10033
+ this.selectPanelForElement();
9936
10034
  }
9937
10035
  onTreeNodeAction(event) {
9938
10036
  const { action, node } = event;
@@ -10101,7 +10199,7 @@ class BuilderComponent {
10101
10199
  }
10102
10200
  case ToolbarAction.EditPreset: {
10103
10201
  this.panelEventService.emit(PanelEventTypes.PRESET_EDIT, node.stylePresetId);
10104
- this.panelEventService.emit(this.isPanelOpen ? PanelEventTypes.PANEL_SELECTED : PanelEventTypes.PANEL_OPEN, PanelTypes.STYLES);
10202
+ this.selectPanel(PanelTypes.STYLES);
10105
10203
  break;
10106
10204
  }
10107
10205
  case ToolbarAction.EditInteractionPreset: {
@@ -10109,7 +10207,7 @@ class BuilderComponent {
10109
10207
  if (node.interactionPresetId) {
10110
10208
  this.panelEventService.emit(PanelEventTypes.INTERACTION_PRESET_EDIT, node.interactionPresetId);
10111
10209
  }
10112
- this.panelEventService.emit(this.isPanelOpen ? PanelEventTypes.PANEL_SELECTED : PanelEventTypes.PANEL_OPEN, PanelTypes.INTERACTIONS);
10210
+ this.selectPanel(PanelTypes.INTERACTIONS);
10113
10211
  // Expand the specific interaction the badge represents so the panel opens "on the right
10114
10212
  // interaction active". Emitted AFTER PANEL_OPEN so the panel is showing this node.
10115
10213
  if (event.interaction?.id) {
@@ -10516,6 +10614,10 @@ class BuilderComponent {
10516
10614
  });
10517
10615
  return;
10518
10616
  }
10617
+ if (panelEvent.type === PanelEventTypes.DIALOG_CLOSED_OVER_SELECTION) {
10618
+ this.selectAfterDialogClosed(String(panelEvent.data?.dialogId ?? ''));
10619
+ return;
10620
+ }
10519
10621
  // Every style or structural edit — including a breakpoint override — emits LAYOUT_CHANGED.
10520
10622
  if (panelEvent.type === PanelEventTypes.LAYOUT_CHANGED) {
10521
10623
  this.refreshBreakpointCounts();
@@ -10527,8 +10629,12 @@ class BuilderComponent {
10527
10629
  this.isPanelOpen = false;
10528
10630
  return;
10529
10631
  }
10530
- if (panelEvent.type === PanelEventTypes.PANEL_OPEN) {
10632
+ // Whoever opened a panel (a tab, a deep link, a toolbar badge), the builder knows which one is showing —
10633
+ // the next selection keeps it when it is an element panel.
10634
+ if (panelEvent.type === PanelEventTypes.PANEL_OPEN || panelEvent.type === PanelEventTypes.PANEL_SELECTED) {
10531
10635
  this.isPanelOpen = true;
10636
+ if (typeof panelEvent.data === 'string')
10637
+ this.activePanel = panelEvent.data;
10532
10638
  }
10533
10639
  }
10534
10640
  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: CanvasDesignStateService }, { token: InteractionEngineService }, { token: InteractionPresetRegistryService }, { token: BuilderClipboardService }, { token: SymbolRegistryService }, { token: i0.ChangeDetectorRef }, { token: i0.ApplicationRef }, { token: MoveableCanvasService }, { token: SelectoCanvasService }, { token: StyleRegistryService }], target: i0.ɵɵFactoryTarget.Component }); }
@@ -11183,12 +11289,13 @@ class BuilderDialogComponent {
11183
11289
  const allowed = ['center', 'top', 'bottom', 'start', 'end'];
11184
11290
  return allowed.indexOf(String(this.placement)) >= 0 ? String(this.placement) : 'center';
11185
11291
  }
11186
- constructor(dragEngine, instanceRegistry, overlayService, cdr, designState) {
11292
+ constructor(dragEngine, instanceRegistry, overlayService, cdr, designState, panelEvents) {
11187
11293
  this.dragEngine = dragEngine;
11188
11294
  this.instanceRegistry = instanceRegistry;
11189
11295
  this.overlayService = overlayService;
11190
11296
  this.cdr = cdr;
11191
11297
  this.designState = designState;
11298
+ this.panelEvents = panelEvents;
11192
11299
  this.children = [];
11193
11300
  this.nodeId = '';
11194
11301
  this.dropListId = '';
@@ -11200,27 +11307,74 @@ class BuilderDialogComponent {
11200
11307
  this.childMouseLeave = new EventEmitter();
11201
11308
  /** Canvas-only visibility. Never serialised; the live site always starts closed. */
11202
11309
  this.designOpen = false;
11310
+ /** The exit is playing: still rendered, already closed for every action and the eye. */
11311
+ this.closing = false;
11203
11312
  /** Opened by an action on the canvas (the canvas is a live runtime): stays until something closes it. */
11204
11313
  this.runtimeOpen = false;
11205
11314
  /** Closed by its X / backdrop while the selection or the switcher still shows it: hidden until either changes. */
11206
11315
  this.dismissed = false;
11207
11316
  }
11317
+ /** Open on the canvas right now (an exit that is playing counts as closed). */
11318
+ get isOpen() {
11319
+ return this.designOpen && !this.closing;
11320
+ }
11208
11321
  /** Shown when an action opened it, or the canvas design state shows it (selection inside / switched open). */
11209
11322
  recompute() {
11210
11323
  const shown = !this.dismissed && (this.runtimeOpen || !!this.designState?.isShown(this.nodeId));
11211
- if (shown === this.designOpen)
11324
+ if (shown) {
11325
+ if (this.closing) {
11326
+ this.closing = false;
11327
+ cancelExit(this.stageRef?.nativeElement);
11328
+ }
11329
+ if (this.designOpen)
11330
+ return;
11331
+ this.designOpen = true;
11332
+ this.cdr.markForCheck();
11212
11333
  return;
11213
- this.designOpen = shown;
11334
+ }
11335
+ if (this.designOpen && !this.closing)
11336
+ this.playExit();
11337
+ }
11338
+ /** Close with the look's exit motion; the stage leaves the DOM when it has played (now, under reduced motion). */
11339
+ playExit() {
11340
+ const stage = this.stageRef?.nativeElement;
11341
+ this.closing = true;
11342
+ if (!stage) {
11343
+ this.finishExit();
11344
+ return;
11345
+ }
11346
+ void runExitMotion(stage, { animate: motionAllowed() }).then(done => { if (done && this.closing)
11347
+ this.finishExit(); });
11348
+ }
11349
+ finishExit() {
11350
+ this.closing = false;
11351
+ this.designOpen = false;
11214
11352
  this.cdr.markForCheck();
11215
11353
  }
11216
11354
  openRuntime() { this.runtimeOpen = true; this.dismissed = false; this.recompute(); }
11217
11355
  closeRuntime() {
11356
+ // A selection INSIDE the dialog (its Close, picked to style it) would be left on an element about to leave
11357
+ // the DOM — the selection chrome drawn at the viewport's corner (Doron's live test). It moves to the
11358
+ // dialog's opener (the menu button), else off the canvas; checked BEFORE the reveal is cleared.
11359
+ const handOff = this.selectionInside();
11218
11360
  this.runtimeOpen = false;
11219
- // Unpin it first (a free-standing dialog the selection opened, A4) — that emits and clears
11220
- // `dismissed`; then hide it even while the selection still sits inside a revealed part (R2).
11361
+ // Unpin it and clear its reveal (a free-standing dialog the selection opened, A4; a part the selection sat
11362
+ // in, R2) — that emits and clears `dismissed`; then hide it even while the selection is still inside.
11221
11363
  this.designState?.dismiss(this.nodeId);
11222
11364
  this.dismissed = true;
11223
11365
  this.recompute();
11366
+ if (handOff)
11367
+ this.panelEvents?.emit(PanelEventTypes.DIALOG_CLOSED_OVER_SELECTION, { dialogId: this.nodeId });
11368
+ }
11369
+ /** True when the canvas selection is this dialog or a node inside it. */
11370
+ selectionInside() {
11371
+ const sel = this.overlayService.getCurrentSelection?.();
11372
+ if (!sel)
11373
+ return false;
11374
+ if (sel.node?.id === this.nodeId)
11375
+ return true;
11376
+ const stage = this.stageRef?.nativeElement;
11377
+ return !!stage && !!sel.element && stage.contains(sel.element);
11224
11378
  }
11225
11379
  ngOnInit() {
11226
11380
  // Board A4: "Closed later? Click it [in the tree] and it reopens." Selection IS the
@@ -11258,8 +11412,8 @@ class BuilderDialogComponent {
11258
11412
  this.instanceRegistry.register(this.nodeId, {
11259
11413
  open: () => this.openRuntime(),
11260
11414
  close: () => this.closeRuntime(),
11261
- toggle: () => (this.designOpen ? this.closeRuntime() : this.openRuntime()),
11262
- isOpen: () => this.designOpen,
11415
+ toggle: () => (this.isOpen ? this.closeRuntime() : this.openRuntime()),
11416
+ isOpen: () => this.isOpen,
11263
11417
  });
11264
11418
  }
11265
11419
  ngOnDestroy() {
@@ -11290,9 +11444,9 @@ class BuilderDialogComponent {
11290
11444
  onDrop(event) {
11291
11445
  this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr);
11292
11446
  }
11293
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDialogComponent, deps: [{ token: DragEngineService }, { token: i1$1.ComponentInstanceRegistryService }, { token: OverlayService }, { token: i0.ChangeDetectorRef }, { token: CanvasDesignStateService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
11294
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: BuilderDialogComponent, isStandalone: false, selector: "app-builder-dialog", inputs: { children: "children", nodeId: "nodeId", dropListId: "dropListId", closeOnBackdrop: "closeOnBackdrop", showCloseButton: "showCloseButton", placement: "placement" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
11295
- <div *ngIf="designOpen" class="dialog-stage" [attr.data-placement]="placementValue"
11447
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDialogComponent, deps: [{ token: DragEngineService }, { token: i1$1.ComponentInstanceRegistryService }, { token: OverlayService }, { token: i0.ChangeDetectorRef }, { token: CanvasDesignStateService, optional: true }, { token: PanelEventService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
11448
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: BuilderDialogComponent, isStandalone: false, selector: "app-builder-dialog", inputs: { children: "children", nodeId: "nodeId", dropListId: "dropListId", closeOnBackdrop: "closeOnBackdrop", showCloseButton: "showCloseButton", placement: "placement" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, viewQueries: [{ propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true }], ngImport: i0, template: `
11449
+ <div *ngIf="designOpen" #stage class="dialog-stage" [attr.data-placement]="placementValue"
11296
11450
  (click)="onStageClick($event)">
11297
11451
  <div [ngClass]="['iox-node-' + nodeId, 'iox-outer-' + nodeId]"
11298
11452
  class="dialog-surface"
@@ -11323,12 +11477,12 @@ class BuilderDialogComponent {
11323
11477
  </ng-container>
11324
11478
  </div>
11325
11479
  </div>
11326
- `, isInline: true, styles: [":host{display:contents}.dialog-stage{position:fixed;inset:0;z-index:50;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);place-items:center;padding:24px;box-sizing:border-box;background:#0f172a73}:host(.iox-es) .dialog-stage{background:var(--iox-scrim)}.dialog-stage[data-placement=top]{align-items:start}.dialog-stage[data-placement=bottom]{align-items:end}.dialog-stage[data-placement=start]{justify-items:start}.dialog-stage[data-placement=end]{justify-items:end}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]){padding:0}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]) .dialog-surface{height:100%;max-height:100%}:host(.iox-es) .dialog-stage[data-placement=end] .dialog-surface{border-start-end-radius:0;border-end-end-radius:0}:host(.iox-es) .dialog-stage[data-placement=start] .dialog-surface{border-start-start-radius:0;border-end-start-radius:0}:where(.dialog-surface){box-sizing:border-box;max-width:100%;max-height:100%;overflow:auto;contain:layout}.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}:host(.iox-es) .dialog-close{border-radius:var(--iox-radius-pill);background:var(--iox-surface-2);color:var(--iox-text)}.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: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId", "ioxPhrasing"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
11480
+ `, isInline: true, styles: [":host{display:contents}.dialog-stage{position:fixed;inset:0;z-index:50;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);place-items:center;padding:24px;box-sizing:border-box;background:#0f172a73}:host(.iox-es) .dialog-stage{background:var(--iox-scrim)}.dialog-stage[data-placement=top]{align-items:start}.dialog-stage[data-placement=bottom]{align-items:end}.dialog-stage[data-placement=start]{justify-items:start}.dialog-stage[data-placement=end]{justify-items:end}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]){padding:0}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]) .dialog-surface{height:100%;max-height:100%}:host(.iox-es) .dialog-stage[data-placement=end] .dialog-surface{border-start-end-radius:0;border-end-end-radius:0}:host(.iox-es) .dialog-stage[data-placement=start] .dialog-surface{border-start-start-radius:0;border-end-start-radius:0}:host(.iox-es) .dialog-stage{animation:iox-dialog-scrim-in var(--iox-dur-base) var(--iox-ease-enter) both}:host(.iox-es) .dialog-stage[data-iox-closing]{animation:iox-dialog-scrim-out var(--iox-dur-base) var(--iox-ease-exit) both}:host(.iox-es) .dialog-surface{--dialog-exit-x: 0px;--dialog-exit-y: 12px;--dialog-exit-opacity: 0;animation:iox-dialog-in var(--iox-dur-base) var(--iox-ease-enter) both}:host(.iox-es) .dialog-stage[data-iox-closing] .dialog-surface{animation:iox-dialog-out var(--iox-dur-base) var(--iox-ease-exit) both}:host(.iox-es) .dialog-stage[data-placement=top] .dialog-surface{--dialog-exit-y: -12px}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]) .dialog-surface{--dialog-exit-y: 0px;--dialog-exit-opacity: 1}:host(.iox-es) .dialog-stage[data-placement=end] .dialog-surface{--dialog-exit-x: calc(100% * var(--dialog-dir, 1))}:host(.iox-es) .dialog-stage[data-placement=start] .dialog-surface{--dialog-exit-x: calc(-100% * var(--dialog-dir, 1))}:host-context([dir=\"rtl\"]){--dialog-dir: -1}@keyframes iox-dialog-scrim-in{0%{background-color:transparent}}@keyframes iox-dialog-scrim-out{to{background-color:transparent}}@keyframes iox-dialog-in{0%{translate:var(--dialog-exit-x) var(--dialog-exit-y);opacity:var(--dialog-exit-opacity)}}@keyframes iox-dialog-out{to{translate:var(--dialog-exit-x) var(--dialog-exit-y);opacity:var(--dialog-exit-opacity)}}:where(.dialog-surface){box-sizing:border-box;max-width:100%;max-height:100%;overflow:auto;contain:layout}.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}:host(.iox-es) .dialog-close{border-radius:var(--iox-radius-pill);background:var(--iox-surface-2);color:var(--iox-text)}.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: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId", "ioxPhrasing"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
11327
11481
  }
11328
11482
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDialogComponent, decorators: [{
11329
11483
  type: Component,
11330
11484
  args: [{ selector: 'app-builder-dialog', template: `
11331
- <div *ngIf="designOpen" class="dialog-stage" [attr.data-placement]="placementValue"
11485
+ <div *ngIf="designOpen" #stage class="dialog-stage" [attr.data-placement]="placementValue"
11332
11486
  (click)="onStageClick($event)">
11333
11487
  <div [ngClass]="['iox-node-' + nodeId, 'iox-outer-' + nodeId]"
11334
11488
  class="dialog-surface"
@@ -11359,9 +11513,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
11359
11513
  </ng-container>
11360
11514
  </div>
11361
11515
  </div>
11362
- `, standalone: false, styles: [":host{display:contents}.dialog-stage{position:fixed;inset:0;z-index:50;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);place-items:center;padding:24px;box-sizing:border-box;background:#0f172a73}:host(.iox-es) .dialog-stage{background:var(--iox-scrim)}.dialog-stage[data-placement=top]{align-items:start}.dialog-stage[data-placement=bottom]{align-items:end}.dialog-stage[data-placement=start]{justify-items:start}.dialog-stage[data-placement=end]{justify-items:end}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]){padding:0}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]) .dialog-surface{height:100%;max-height:100%}:host(.iox-es) .dialog-stage[data-placement=end] .dialog-surface{border-start-end-radius:0;border-end-end-radius:0}:host(.iox-es) .dialog-stage[data-placement=start] .dialog-surface{border-start-start-radius:0;border-end-start-radius:0}:where(.dialog-surface){box-sizing:border-box;max-width:100%;max-height:100%;overflow:auto;contain:layout}.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}:host(.iox-es) .dialog-close{border-radius:var(--iox-radius-pill);background:var(--iox-surface-2);color:var(--iox-text)}.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"] }]
11516
+ `, standalone: false, styles: [":host{display:contents}.dialog-stage{position:fixed;inset:0;z-index:50;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);place-items:center;padding:24px;box-sizing:border-box;background:#0f172a73}:host(.iox-es) .dialog-stage{background:var(--iox-scrim)}.dialog-stage[data-placement=top]{align-items:start}.dialog-stage[data-placement=bottom]{align-items:end}.dialog-stage[data-placement=start]{justify-items:start}.dialog-stage[data-placement=end]{justify-items:end}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]){padding:0}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]) .dialog-surface{height:100%;max-height:100%}:host(.iox-es) .dialog-stage[data-placement=end] .dialog-surface{border-start-end-radius:0;border-end-end-radius:0}:host(.iox-es) .dialog-stage[data-placement=start] .dialog-surface{border-start-start-radius:0;border-end-start-radius:0}:host(.iox-es) .dialog-stage{animation:iox-dialog-scrim-in var(--iox-dur-base) var(--iox-ease-enter) both}:host(.iox-es) .dialog-stage[data-iox-closing]{animation:iox-dialog-scrim-out var(--iox-dur-base) var(--iox-ease-exit) both}:host(.iox-es) .dialog-surface{--dialog-exit-x: 0px;--dialog-exit-y: 12px;--dialog-exit-opacity: 0;animation:iox-dialog-in var(--iox-dur-base) var(--iox-ease-enter) both}:host(.iox-es) .dialog-stage[data-iox-closing] .dialog-surface{animation:iox-dialog-out var(--iox-dur-base) var(--iox-ease-exit) both}:host(.iox-es) .dialog-stage[data-placement=top] .dialog-surface{--dialog-exit-y: -12px}:host(.iox-es) .dialog-stage:is([data-placement=end],[data-placement=start]) .dialog-surface{--dialog-exit-y: 0px;--dialog-exit-opacity: 1}:host(.iox-es) .dialog-stage[data-placement=end] .dialog-surface{--dialog-exit-x: calc(100% * var(--dialog-dir, 1))}:host(.iox-es) .dialog-stage[data-placement=start] .dialog-surface{--dialog-exit-x: calc(-100% * var(--dialog-dir, 1))}:host-context([dir=\"rtl\"]){--dialog-dir: -1}@keyframes iox-dialog-scrim-in{0%{background-color:transparent}}@keyframes iox-dialog-scrim-out{to{background-color:transparent}}@keyframes iox-dialog-in{0%{translate:var(--dialog-exit-x) var(--dialog-exit-y);opacity:var(--dialog-exit-opacity)}}@keyframes iox-dialog-out{to{translate:var(--dialog-exit-x) var(--dialog-exit-y);opacity:var(--dialog-exit-opacity)}}:where(.dialog-surface){box-sizing:border-box;max-width:100%;max-height:100%;overflow:auto;contain:layout}.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}:host(.iox-es) .dialog-close{border-radius:var(--iox-radius-pill);background:var(--iox-surface-2);color:var(--iox-text)}.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"] }]
11363
11517
  }], ctorParameters: () => [{ type: DragEngineService }, { type: i1$1.ComponentInstanceRegistryService }, { type: OverlayService }, { type: i0.ChangeDetectorRef }, { type: CanvasDesignStateService, decorators: [{
11364
11518
  type: Optional
11519
+ }] }, { type: PanelEventService, decorators: [{
11520
+ type: Optional
11365
11521
  }] }], propDecorators: { children: [{
11366
11522
  type: Input
11367
11523
  }], nodeId: [{
@@ -11380,6 +11536,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
11380
11536
  type: Output
11381
11537
  }], childMouseLeave: [{
11382
11538
  type: Output
11539
+ }], stageRef: [{
11540
+ type: ViewChild,
11541
+ args: ['stage']
11383
11542
  }] } });
11384
11543
 
11385
11544
  /** Swiper's event → the interaction trigger it replays (componentEvents). */