@vectoriox/iox-builder 1.1.5 → 1.1.8
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.
|
@@ -189,6 +189,11 @@ class OverlayService {
|
|
|
189
189
|
this.scrollContainerElement = null;
|
|
190
190
|
/** Emits the scroll container element whenever it is registered. */
|
|
191
191
|
this.scrollContainer$ = new Subject();
|
|
192
|
+
/** Emits cursor coords when a canvas element is right-clicked. */
|
|
193
|
+
this.contextMenu$ = new Subject();
|
|
194
|
+
}
|
|
195
|
+
triggerContextMenu(x, y) {
|
|
196
|
+
this.contextMenu$.next({ x, y });
|
|
192
197
|
}
|
|
193
198
|
setContainer(container) {
|
|
194
199
|
this.containerElement = container;
|
|
@@ -1526,6 +1531,13 @@ class RenderDirective {
|
|
|
1526
1531
|
event.stopPropagation();
|
|
1527
1532
|
this.onClick.emit({ element: nativeEl, node, componentRef });
|
|
1528
1533
|
});
|
|
1534
|
+
nativeEl.addEventListener('contextmenu', (event) => {
|
|
1535
|
+
event.preventDefault();
|
|
1536
|
+
event.stopPropagation();
|
|
1537
|
+
// Select the element first, then open the more menu at cursor position.
|
|
1538
|
+
this.onClick.emit({ element: nativeEl, node, componentRef });
|
|
1539
|
+
this.overlayService.triggerContextMenu(event.clientX, event.clientY);
|
|
1540
|
+
});
|
|
1529
1541
|
}
|
|
1530
1542
|
// Wire up interactions (animations) after the element is in the DOM.
|
|
1531
1543
|
this.interactionEngine.attach(node);
|
|
@@ -1663,11 +1675,10 @@ class OverlayComponent {
|
|
|
1663
1675
|
this.hiPaddingStyle = {};
|
|
1664
1676
|
// Select: simple IOX pink outline
|
|
1665
1677
|
this.selectOutlineStyle = {};
|
|
1666
|
-
// More dropdown
|
|
1678
|
+
// More dropdown — opened from the ⋯ button or from a right-click.
|
|
1679
|
+
// Position is set to fixed viewport coords so it appears at the cursor.
|
|
1667
1680
|
this.moreMenuVisible = false;
|
|
1668
|
-
|
|
1669
|
-
this.contextMenuVisible = false;
|
|
1670
|
-
this.contextMenuStyle = {};
|
|
1681
|
+
this.moreMenuStyle = {};
|
|
1671
1682
|
this.subs = [];
|
|
1672
1683
|
this.boundUpdate = () => this.updateAll();
|
|
1673
1684
|
this.activeScrollContainer = null;
|
|
@@ -1708,6 +1719,12 @@ class OverlayComponent {
|
|
|
1708
1719
|
this.activeScrollContainer = el;
|
|
1709
1720
|
el.addEventListener('scroll', this.boundUpdate, { passive: true });
|
|
1710
1721
|
}));
|
|
1722
|
+
// Open the more menu when a canvas element is right-clicked.
|
|
1723
|
+
this.subs.push(this.overlayService.contextMenu$.subscribe(({ x, y }) => {
|
|
1724
|
+
this.moreMenuStyle = { top: `${y}px`, left: `${x}px` };
|
|
1725
|
+
this.moreMenuVisible = true;
|
|
1726
|
+
this.cdr.markForCheck();
|
|
1727
|
+
}));
|
|
1711
1728
|
}
|
|
1712
1729
|
ngOnDestroy() {
|
|
1713
1730
|
this.subs.forEach(s => s.unsubscribe());
|
|
@@ -1746,7 +1763,14 @@ class OverlayComponent {
|
|
|
1746
1763
|
}
|
|
1747
1764
|
onToggleMore(event) {
|
|
1748
1765
|
event.stopPropagation();
|
|
1749
|
-
|
|
1766
|
+
event.preventDefault();
|
|
1767
|
+
if (this.moreMenuVisible) {
|
|
1768
|
+
this.moreMenuVisible = false;
|
|
1769
|
+
}
|
|
1770
|
+
else {
|
|
1771
|
+
this.moreMenuStyle = { top: `${event.clientY}px`, left: `${event.clientX}px` };
|
|
1772
|
+
this.moreMenuVisible = true;
|
|
1773
|
+
}
|
|
1750
1774
|
this.cdr.markForCheck();
|
|
1751
1775
|
}
|
|
1752
1776
|
closeMoreMenu() {
|
|
@@ -1756,20 +1780,10 @@ class OverlayComponent {
|
|
|
1756
1780
|
onContextMenu(event) {
|
|
1757
1781
|
event.preventDefault();
|
|
1758
1782
|
event.stopPropagation();
|
|
1759
|
-
this.
|
|
1760
|
-
|
|
1761
|
-
top: `${event.clientY}px`,
|
|
1762
|
-
left: `${event.clientX}px`,
|
|
1763
|
-
};
|
|
1764
|
-
this.contextMenuVisible = true;
|
|
1783
|
+
this.moreMenuStyle = { top: `${event.clientY}px`, left: `${event.clientX}px` };
|
|
1784
|
+
this.moreMenuVisible = true;
|
|
1765
1785
|
this.cdr.markForCheck();
|
|
1766
1786
|
}
|
|
1767
|
-
onContextSaveAsBlock(event) {
|
|
1768
|
-
event.stopPropagation();
|
|
1769
|
-
this.closeContextMenu();
|
|
1770
|
-
if (this.selectEntry)
|
|
1771
|
-
this.toolbarAction.emit({ action: ToolbarAction.SaveAsBlock, entry: this.selectEntry });
|
|
1772
|
-
}
|
|
1773
1787
|
onMakeGlobal(event, position) {
|
|
1774
1788
|
event.stopPropagation();
|
|
1775
1789
|
this.closeMoreMenu();
|
|
@@ -1782,10 +1796,6 @@ class OverlayComponent {
|
|
|
1782
1796
|
if (this.selectEntry)
|
|
1783
1797
|
this.toolbarAction.emit({ action: ToolbarAction.RemoveGlobal, entry: this.selectEntry });
|
|
1784
1798
|
}
|
|
1785
|
-
closeContextMenu() {
|
|
1786
|
-
this.contextMenuVisible = false;
|
|
1787
|
-
this.cdr.markForCheck();
|
|
1788
|
-
}
|
|
1789
1799
|
get hasInteractions() {
|
|
1790
1800
|
return !!this.selectEntry?.node?.interactions?.length;
|
|
1791
1801
|
}
|
|
@@ -1912,11 +1922,11 @@ class OverlayComponent {
|
|
|
1912
1922
|
return `polygon(evenodd, 0px 0px, ${w}px 0px, ${w}px ${h}px, 0px ${h}px, 0px 0px, ${x1}px ${y1}px, ${x2}px ${y1}px, ${x2}px ${y2}px, ${x1}px ${y2}px, ${x1}px ${y1}px)`;
|
|
1913
1923
|
}
|
|
1914
1924
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OverlayComponent, deps: [{ token: OverlayService }, { token: ViewportService }, { token: PresetRegistryService }, { token: StyleRegistryService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1915
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: OverlayComponent, isStandalone: false, selector: "app-overlay", outputs: { toolbarAction: "toolbarAction" }, ngImport: i0, template: "<div class=\"overlay-root\">\n\n <!-- HOVER \u2014 Chrome DevTools-style rings (content area stays transparent) -->\n <ng-container *ngIf=\"hoverEntry\">\n <div class=\"hi-outline\" [ngStyle]=\"hiOutlineStyle\"></div>\n <div class=\"hi-margin\" [ngStyle]=\"hiMarginStyle\"></div>\n <div class=\"hi-padding\" [ngStyle]=\"hiPaddingStyle\"></div>\n </ng-container>\n\n <!-- SELECT \u2014 IOX pink outline + toolbar -->\n <div class=\"select-outline\" *ngIf=\"selectEntry\" [ngStyle]=\"selectOutlineStyle\"
|
|
1925
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: OverlayComponent, isStandalone: false, selector: "app-overlay", outputs: { toolbarAction: "toolbarAction" }, ngImport: i0, template: "<div class=\"overlay-root\">\n\n <!-- HOVER \u2014 Chrome DevTools-style rings (content area stays transparent) -->\n <ng-container *ngIf=\"hoverEntry\">\n <div class=\"hi-outline\" [ngStyle]=\"hiOutlineStyle\"></div>\n <div class=\"hi-margin\" [ngStyle]=\"hiMarginStyle\"></div>\n <div class=\"hi-padding\" [ngStyle]=\"hiPaddingStyle\"></div>\n </ng-container>\n\n <!-- SELECT \u2014 IOX pink outline + toolbar -->\n <div class=\"select-outline\" *ngIf=\"selectEntry\" [ngStyle]=\"selectOutlineStyle\">\n\n <!-- Preset badge \u2014 centered below the outline, shown when a preset is applied -->\n <div *ngIf=\"selectedPresetName\" class=\"preset-badge\" (mousedown)=\"onEditPreset($event)\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n\n <div class=\"select-toolbar\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ selectEntry?.componentName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n <button class=\"toolbar-btn\" title=\"Duplicate\" (mousedown)=\"onDuplicate($event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button *ngIf=\"hasInteractions\" class=\"toolbar-btn toolbar-btn--play\" title=\"Play animations\" (mousedown)=\"onPlay($event)\">\n <i class=\"ph-thin ph-play\"></i>\n </button>\n <button class=\"toolbar-btn toolbar-btn--danger\" title=\"Delete\" (mousedown)=\"onDelete($event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n <button class=\"toolbar-btn\" title=\"Select parent\" (mousedown)=\"onSelectParent($event)\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n </button>\n\n <!-- More menu trigger \u2014 opens a fixed-position dropdown at the cursor -->\n <button class=\"toolbar-btn toolbar-btn--more\" title=\"More actions\" (mousedown)=\"onToggleMore($event)\">\n <i class=\"ph-thin ph-dots-three\"></i>\n </button>\n </div>\n </div>\n\n <!-- Shared more/context menu \u2014 fixed-position, opened by \u22EF button or right-click -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" [ngStyle]=\"moreMenuStyle\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <button class=\"more-item\" (mousedown)=\"onSelectParent($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n Select parent\n </button>\n <button class=\"more-item\" (mousedown)=\"onDuplicate($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-copy\"></i>\n Duplicate\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onDelete($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-trash\"></i>\n Delete\n </button>\n <div class=\"more-divider\"></div>\n <button class=\"more-item\" (mousedown)=\"onSaveAsBlock($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\n <button *ngIf=\"hasInteractions\" class=\"more-item more-item--play\" (mousedown)=\"onPlay($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-play\"></i>\n Play animations\n </button>\n <div class=\"more-divider\"></div>\n <ng-container *ngIf=\"!selectedNodeIsGlobal; else removeGlobalItem\">\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'before')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (Before Content)\n </button>\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'after')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (After Content)\n </button>\n </ng-container>\n <ng-template #removeGlobalItem>\n <button class=\"more-item\" (mousedown)=\"onRemoveGlobal($event)\">\n <i class=\"ph-thin ph-globe\"></i>\n Remove from Global\n </button>\n </ng-template>\n </div>\n\n <!-- Backdrop to close the more menu -->\n <div *ngIf=\"moreMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu()\">\n </div>\n\n</div>\n", styles: [":host{display:block;position:absolute;inset:0;pointer-events:none;z-index:12;overflow:visible}.hi-outline,.hi-margin,.hi-padding{position:fixed;pointer-events:none;transition:none;box-sizing:border-box}.hi-outline{box-shadow:inset 0 0 0 1.5px #cb9090}.hi-margin{background:#f6b23361}.hi-padding{background:#60c38366}.select-outline{position:fixed;z-index:999;box-shadow:inset 0 0 0 1px #cb9090;pointer-events:none;transition:none;overflow:visible;will-change:transform;box-sizing:border-box}.select-toolbar{position:absolute;top:0;left:0;transform:translateY(-100%);display:flex;align-items:center;background:#cb9090;border-radius:3px 3px 0 0;pointer-events:all;white-space:nowrap;overflow:visible}.select-toolbar .toolbar-name{padding:0 8px;font-size:11px;font-weight:500;color:#fff;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:22px}.select-toolbar .toolbar-sep{width:1px;height:14px;background:#ffffff59;margin:0 2px;flex-shrink:0}.select-toolbar .toolbar-btn{display:flex;align-items:center;justify-content:center;width:24px;height:22px;padding:0;border:none;background:transparent;color:#fff;font-size:13px;cursor:pointer;transition:background .15s;flex-shrink:0}.select-toolbar .toolbar-btn:hover{background:#ffffff2e}.select-toolbar .toolbar-btn--danger:hover{background:#c8323259}.select-toolbar .toolbar-btn--more{border-radius:0 3px 0 0}.toolbar-more-dropdown{position:fixed;z-index:1000;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.toolbar-more-dropdown .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 14px;border:none;background:transparent;font-size:13px;color:var(--p-text-color, #333);cursor:pointer;text-align:left;white-space:nowrap}.toolbar-more-dropdown .more-item i{font-size:14px}.toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item--danger{color:#c84040}.toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.preset-badge{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;white-space:nowrap;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s}.preset-badge i{font-size:12px}.preset-badge:hover{background:#be7474}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1916
1926
|
}
|
|
1917
1927
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OverlayComponent, decorators: [{
|
|
1918
1928
|
type: Component,
|
|
1919
|
-
args: [{ selector: 'app-overlay', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"overlay-root\">\n\n <!-- HOVER \u2014 Chrome DevTools-style rings (content area stays transparent) -->\n <ng-container *ngIf=\"hoverEntry\">\n <div class=\"hi-outline\" [ngStyle]=\"hiOutlineStyle\"></div>\n <div class=\"hi-margin\" [ngStyle]=\"hiMarginStyle\"></div>\n <div class=\"hi-padding\" [ngStyle]=\"hiPaddingStyle\"></div>\n </ng-container>\n\n <!-- SELECT \u2014 IOX pink outline + toolbar -->\n <div class=\"select-outline\" *ngIf=\"selectEntry\" [ngStyle]=\"selectOutlineStyle\"
|
|
1929
|
+
args: [{ selector: 'app-overlay', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"overlay-root\">\n\n <!-- HOVER \u2014 Chrome DevTools-style rings (content area stays transparent) -->\n <ng-container *ngIf=\"hoverEntry\">\n <div class=\"hi-outline\" [ngStyle]=\"hiOutlineStyle\"></div>\n <div class=\"hi-margin\" [ngStyle]=\"hiMarginStyle\"></div>\n <div class=\"hi-padding\" [ngStyle]=\"hiPaddingStyle\"></div>\n </ng-container>\n\n <!-- SELECT \u2014 IOX pink outline + toolbar -->\n <div class=\"select-outline\" *ngIf=\"selectEntry\" [ngStyle]=\"selectOutlineStyle\">\n\n <!-- Preset badge \u2014 centered below the outline, shown when a preset is applied -->\n <div *ngIf=\"selectedPresetName\" class=\"preset-badge\" (mousedown)=\"onEditPreset($event)\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n\n <div class=\"select-toolbar\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ selectEntry?.componentName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n <button class=\"toolbar-btn\" title=\"Duplicate\" (mousedown)=\"onDuplicate($event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button *ngIf=\"hasInteractions\" class=\"toolbar-btn toolbar-btn--play\" title=\"Play animations\" (mousedown)=\"onPlay($event)\">\n <i class=\"ph-thin ph-play\"></i>\n </button>\n <button class=\"toolbar-btn toolbar-btn--danger\" title=\"Delete\" (mousedown)=\"onDelete($event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n <button class=\"toolbar-btn\" title=\"Select parent\" (mousedown)=\"onSelectParent($event)\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n </button>\n\n <!-- More menu trigger \u2014 opens a fixed-position dropdown at the cursor -->\n <button class=\"toolbar-btn toolbar-btn--more\" title=\"More actions\" (mousedown)=\"onToggleMore($event)\">\n <i class=\"ph-thin ph-dots-three\"></i>\n </button>\n </div>\n </div>\n\n <!-- Shared more/context menu \u2014 fixed-position, opened by \u22EF button or right-click -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" [ngStyle]=\"moreMenuStyle\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <button class=\"more-item\" (mousedown)=\"onSelectParent($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-arrow-up\"></i>\n Select parent\n </button>\n <button class=\"more-item\" (mousedown)=\"onDuplicate($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-copy\"></i>\n Duplicate\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onDelete($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-trash\"></i>\n Delete\n </button>\n <div class=\"more-divider\"></div>\n <button class=\"more-item\" (mousedown)=\"onSaveAsBlock($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\n <button *ngIf=\"hasInteractions\" class=\"more-item more-item--play\" (mousedown)=\"onPlay($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-play\"></i>\n Play animations\n </button>\n <div class=\"more-divider\"></div>\n <ng-container *ngIf=\"!selectedNodeIsGlobal; else removeGlobalItem\">\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'before')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (Before Content)\n </button>\n <button class=\"more-item\" (mousedown)=\"onMakeGlobal($event, 'after')\">\n <i class=\"ph-thin ph-globe\"></i>\n Make Global (After Content)\n </button>\n </ng-container>\n <ng-template #removeGlobalItem>\n <button class=\"more-item\" (mousedown)=\"onRemoveGlobal($event)\">\n <i class=\"ph-thin ph-globe\"></i>\n Remove from Global\n </button>\n </ng-template>\n </div>\n\n <!-- Backdrop to close the more menu -->\n <div *ngIf=\"moreMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu()\">\n </div>\n\n</div>\n", styles: [":host{display:block;position:absolute;inset:0;pointer-events:none;z-index:12;overflow:visible}.hi-outline,.hi-margin,.hi-padding{position:fixed;pointer-events:none;transition:none;box-sizing:border-box}.hi-outline{box-shadow:inset 0 0 0 1.5px #cb9090}.hi-margin{background:#f6b23361}.hi-padding{background:#60c38366}.select-outline{position:fixed;z-index:999;box-shadow:inset 0 0 0 1px #cb9090;pointer-events:none;transition:none;overflow:visible;will-change:transform;box-sizing:border-box}.select-toolbar{position:absolute;top:0;left:0;transform:translateY(-100%);display:flex;align-items:center;background:#cb9090;border-radius:3px 3px 0 0;pointer-events:all;white-space:nowrap;overflow:visible}.select-toolbar .toolbar-name{padding:0 8px;font-size:11px;font-weight:500;color:#fff;max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:22px}.select-toolbar .toolbar-sep{width:1px;height:14px;background:#ffffff59;margin:0 2px;flex-shrink:0}.select-toolbar .toolbar-btn{display:flex;align-items:center;justify-content:center;width:24px;height:22px;padding:0;border:none;background:transparent;color:#fff;font-size:13px;cursor:pointer;transition:background .15s;flex-shrink:0}.select-toolbar .toolbar-btn:hover{background:#ffffff2e}.select-toolbar .toolbar-btn--danger:hover{background:#c8323259}.select-toolbar .toolbar-btn--more{border-radius:0 3px 0 0}.toolbar-more-dropdown{position:fixed;z-index:1000;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.toolbar-more-dropdown .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 14px;border:none;background:transparent;font-size:13px;color:var(--p-text-color, #333);cursor:pointer;text-align:left;white-space:nowrap}.toolbar-more-dropdown .more-item i{font-size:14px}.toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item--danger{color:#c84040}.toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.preset-badge{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;white-space:nowrap;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s}.preset-badge i{font-size:12px}.preset-badge:hover{background:#be7474}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"] }]
|
|
1920
1930
|
}], ctorParameters: () => [{ type: OverlayService }, { type: ViewportService }, { type: PresetRegistryService }, { type: StyleRegistryService }, { type: i0.ChangeDetectorRef }], propDecorators: { toolbarAction: [{
|
|
1921
1931
|
type: Output
|
|
1922
1932
|
}] } });
|
|
@@ -2649,7 +2659,7 @@ class BuilderComponent {
|
|
|
2649
2659
|
else if (action === NodeAction.Duplicate) {
|
|
2650
2660
|
const clone = this.deepCloneWithNewIds(node);
|
|
2651
2661
|
result.parent.splice(result.index + 1, 0, clone);
|
|
2652
|
-
this.cdr.
|
|
2662
|
+
this.cdr.detectChanges();
|
|
2653
2663
|
}
|
|
2654
2664
|
}
|
|
2655
2665
|
onTreeNodeMove() {
|
|
@@ -2666,20 +2676,21 @@ class BuilderComponent {
|
|
|
2666
2676
|
return;
|
|
2667
2677
|
switch (action) {
|
|
2668
2678
|
case ToolbarAction.Delete: {
|
|
2669
|
-
const result = this.findNodeInTree(node, this.layout);
|
|
2679
|
+
const result = this.findNodeInTree(node, this.layout) ?? this.findNodeInTree(node, this.globalElements);
|
|
2670
2680
|
if (result) {
|
|
2671
2681
|
result.parent.splice(result.index, 1);
|
|
2672
2682
|
this.selectedItem = null;
|
|
2673
2683
|
this.overlayService.clearSelect();
|
|
2684
|
+
this.cdr.detectChanges();
|
|
2674
2685
|
}
|
|
2675
2686
|
break;
|
|
2676
2687
|
}
|
|
2677
2688
|
case ToolbarAction.Duplicate: {
|
|
2678
|
-
const result = this.findNodeInTree(node, this.layout);
|
|
2689
|
+
const result = this.findNodeInTree(node, this.layout) ?? this.findNodeInTree(node, this.globalElements);
|
|
2679
2690
|
if (result) {
|
|
2680
2691
|
const clone = this.deepCloneWithNewIds(node);
|
|
2681
2692
|
result.parent.splice(result.index + 1, 0, clone);
|
|
2682
|
-
this.cdr.
|
|
2693
|
+
this.cdr.detectChanges();
|
|
2683
2694
|
}
|
|
2684
2695
|
break;
|
|
2685
2696
|
}
|
|
@@ -2694,7 +2705,7 @@ class BuilderComponent {
|
|
|
2694
2705
|
break;
|
|
2695
2706
|
}
|
|
2696
2707
|
case ToolbarAction.SelectParent: {
|
|
2697
|
-
const parentNode = this.findParentNode(node, this.layout);
|
|
2708
|
+
const parentNode = this.findParentNode(node, this.layout) ?? this.findParentNode(node, this.globalElements);
|
|
2698
2709
|
if (parentNode) {
|
|
2699
2710
|
const ref = this.overlayService.getNodeRef(parentNode);
|
|
2700
2711
|
if (ref) {
|