@vectoriox/iox-builder 1.0.8 → 1.1.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.
|
@@ -31,6 +31,10 @@ var PanelEventTypes;
|
|
|
31
31
|
PanelEventTypes["PANEL_CLOSE"] = "panelclose";
|
|
32
32
|
PanelEventTypes["BINDING_CHANGED"] = "bindingchanged";
|
|
33
33
|
PanelEventTypes["NODE_RENDERED"] = "noderendered";
|
|
34
|
+
/** Open the Style panel in preset-edit mode for the given preset ID. */
|
|
35
|
+
PanelEventTypes["PRESET_EDIT"] = "presetedit";
|
|
36
|
+
/** Fired after a preset is created, updated, or deleted so panels refresh their list. */
|
|
37
|
+
PanelEventTypes["PRESETS_CHANGED"] = "presetschanged";
|
|
34
38
|
})(PanelEventTypes || (PanelEventTypes = {}));
|
|
35
39
|
class PanelEventService {
|
|
36
40
|
constructor() {
|
|
@@ -109,6 +113,7 @@ var ToolbarAction;
|
|
|
109
113
|
ToolbarAction["SaveAsBlock"] = "save-as-block";
|
|
110
114
|
ToolbarAction["MakeGlobal"] = "make-global";
|
|
111
115
|
ToolbarAction["RemoveGlobal"] = "remove-global";
|
|
116
|
+
ToolbarAction["EditPreset"] = "edit-preset";
|
|
112
117
|
})(ToolbarAction || (ToolbarAction = {}));
|
|
113
118
|
var NodeAction;
|
|
114
119
|
(function (NodeAction) {
|
|
@@ -929,13 +934,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
929
934
|
type: Injectable
|
|
930
935
|
}] });
|
|
931
936
|
|
|
937
|
+
const STORAGE_KEY = 'iox_builder_viewport';
|
|
932
938
|
class ViewportService {
|
|
933
939
|
constructor() {
|
|
934
|
-
this.state =
|
|
935
|
-
device: DeviceMode.Desktop,
|
|
936
|
-
width: DEVICE_OPTIONS[0].width,
|
|
937
|
-
scale: 0.75,
|
|
938
|
-
};
|
|
940
|
+
this.state = this.loadFromStorage();
|
|
939
941
|
this.stateSubject = new BehaviorSubject(this.state);
|
|
940
942
|
this.state$ = this.stateSubject.asObservable();
|
|
941
943
|
}
|
|
@@ -949,16 +951,13 @@ class ViewportService {
|
|
|
949
951
|
const option = DEVICE_OPTIONS.find(d => d.mode === device);
|
|
950
952
|
if (!option)
|
|
951
953
|
return;
|
|
952
|
-
this.
|
|
953
|
-
this.stateSubject.next(this.state);
|
|
954
|
+
this.update({ device, width: option.width });
|
|
954
955
|
}
|
|
955
956
|
setScale(scale) {
|
|
956
|
-
this.
|
|
957
|
-
this.stateSubject.next(this.state);
|
|
957
|
+
this.update({ scale: Math.max(0.1, Math.min(2, scale)) });
|
|
958
958
|
}
|
|
959
959
|
setWidth(width) {
|
|
960
|
-
this.
|
|
961
|
-
this.stateSubject.next(this.state);
|
|
960
|
+
this.update({ width });
|
|
962
961
|
}
|
|
963
962
|
/**
|
|
964
963
|
* Calculate the scale that makes the canvas fit inside the available editor width.
|
|
@@ -982,6 +981,42 @@ class ViewportService {
|
|
|
982
981
|
y: (screenY - canvasRect.top) / this.state.scale,
|
|
983
982
|
};
|
|
984
983
|
}
|
|
984
|
+
update(partial) {
|
|
985
|
+
this.state = { ...this.state, ...partial };
|
|
986
|
+
this.stateSubject.next(this.state);
|
|
987
|
+
this.saveToStorage();
|
|
988
|
+
}
|
|
989
|
+
saveToStorage() {
|
|
990
|
+
try {
|
|
991
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.state));
|
|
992
|
+
}
|
|
993
|
+
catch { }
|
|
994
|
+
}
|
|
995
|
+
loadFromStorage() {
|
|
996
|
+
const defaults = {
|
|
997
|
+
device: DeviceMode.Desktop,
|
|
998
|
+
width: DEVICE_OPTIONS[0].width,
|
|
999
|
+
scale: 0.75,
|
|
1000
|
+
};
|
|
1001
|
+
try {
|
|
1002
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
1003
|
+
if (!raw)
|
|
1004
|
+
return defaults;
|
|
1005
|
+
const saved = JSON.parse(raw);
|
|
1006
|
+
const device = Object.values(DeviceMode).includes(saved.device)
|
|
1007
|
+
? saved.device
|
|
1008
|
+
: defaults.device;
|
|
1009
|
+
const option = DEVICE_OPTIONS.find(d => d.mode === device) ?? DEVICE_OPTIONS[0];
|
|
1010
|
+
return {
|
|
1011
|
+
device,
|
|
1012
|
+
width: typeof saved.width === 'number' && saved.width > 0 ? saved.width : option.width,
|
|
1013
|
+
scale: typeof saved.scale === 'number' ? Math.max(0.1, Math.min(2, saved.scale)) : defaults.scale,
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
catch {
|
|
1017
|
+
return defaults;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
985
1020
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ViewportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
986
1021
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ViewportService }); }
|
|
987
1022
|
}
|
|
@@ -1531,10 +1566,63 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
1531
1566
|
type: Input
|
|
1532
1567
|
}] } });
|
|
1533
1568
|
|
|
1569
|
+
/**
|
|
1570
|
+
* PresetRegistryService — in-memory store for org-level style presets.
|
|
1571
|
+
*
|
|
1572
|
+
* Loaded once per page by PageUiComponent (alongside the page layout) and
|
|
1573
|
+
* injected into the overlay (for badge labels) and style panel (for apply /
|
|
1574
|
+
* create / edit / detach flows).
|
|
1575
|
+
*
|
|
1576
|
+
* Scoped to PageUiComponent.providers[] — one registry per builder instance.
|
|
1577
|
+
*/
|
|
1578
|
+
class PresetRegistryService {
|
|
1579
|
+
constructor() {
|
|
1580
|
+
this.presets = new Map();
|
|
1581
|
+
}
|
|
1582
|
+
setPresets(presets) {
|
|
1583
|
+
this.presets.clear();
|
|
1584
|
+
for (const p of presets) {
|
|
1585
|
+
this.presets.set(p.id, p);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
getPreset(id) {
|
|
1589
|
+
return this.presets.get(id);
|
|
1590
|
+
}
|
|
1591
|
+
getAll() {
|
|
1592
|
+
return Array.from(this.presets.values());
|
|
1593
|
+
}
|
|
1594
|
+
upsert(preset) {
|
|
1595
|
+
this.presets.set(preset.id, preset);
|
|
1596
|
+
}
|
|
1597
|
+
remove(id) {
|
|
1598
|
+
this.presets.delete(id);
|
|
1599
|
+
}
|
|
1600
|
+
/**
|
|
1601
|
+
* Resolve the effective style map for a node that references a preset.
|
|
1602
|
+
* Merges preset base styles with the node's local overrides so that
|
|
1603
|
+
* element-level values always win.
|
|
1604
|
+
*
|
|
1605
|
+
* @param presetId ID of the applied preset.
|
|
1606
|
+
* @param overrides The node's `styleOverrides` record (may be empty).
|
|
1607
|
+
*/
|
|
1608
|
+
resolveStyles(presetId, overrides) {
|
|
1609
|
+
const preset = this.presets.get(presetId);
|
|
1610
|
+
if (!preset)
|
|
1611
|
+
return { ...overrides };
|
|
1612
|
+
return { ...preset.styleProps, ...overrides };
|
|
1613
|
+
}
|
|
1614
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: PresetRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1615
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: PresetRegistryService }); }
|
|
1616
|
+
}
|
|
1617
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: PresetRegistryService, decorators: [{
|
|
1618
|
+
type: Injectable
|
|
1619
|
+
}] });
|
|
1620
|
+
|
|
1534
1621
|
class OverlayComponent {
|
|
1535
|
-
constructor(overlayService, viewportService, cdr) {
|
|
1622
|
+
constructor(overlayService, viewportService, presetRegistry, cdr) {
|
|
1536
1623
|
this.overlayService = overlayService;
|
|
1537
1624
|
this.viewportService = viewportService;
|
|
1625
|
+
this.presetRegistry = presetRegistry;
|
|
1538
1626
|
this.cdr = cdr;
|
|
1539
1627
|
this.toolbarAction = new EventEmitter();
|
|
1540
1628
|
this.hoverEntry = null;
|
|
@@ -1672,6 +1760,17 @@ class OverlayComponent {
|
|
|
1672
1760
|
get selectedNodeIsGlobal() {
|
|
1673
1761
|
return !!this.selectEntry?.node?.isGlobal;
|
|
1674
1762
|
}
|
|
1763
|
+
get selectedPresetName() {
|
|
1764
|
+
const id = this.selectEntry?.node?.stylePresetId;
|
|
1765
|
+
if (!id)
|
|
1766
|
+
return null;
|
|
1767
|
+
return this.presetRegistry.getPreset(id)?.name ?? null;
|
|
1768
|
+
}
|
|
1769
|
+
onEditPreset(event) {
|
|
1770
|
+
event.stopPropagation();
|
|
1771
|
+
if (this.selectEntry)
|
|
1772
|
+
this.toolbarAction.emit({ action: ToolbarAction.EditPreset, entry: this.selectEntry });
|
|
1773
|
+
}
|
|
1675
1774
|
observeSelectElement() {
|
|
1676
1775
|
this.resizeObserver?.disconnect();
|
|
1677
1776
|
this.mutationObserver?.disconnect();
|
|
@@ -1779,13 +1878,13 @@ class OverlayComponent {
|
|
|
1779
1878
|
// is a zero-area line — prevents diagonal edge triangle artifacts.
|
|
1780
1879
|
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)`;
|
|
1781
1880
|
}
|
|
1782
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OverlayComponent, deps: [{ token: OverlayService }, { token: ViewportService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1783
|
-
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 (contextmenu)=\"onContextMenu($event)\">\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 last -->\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\n <!-- More dropdown (inline, positioned from toolbar) -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" (click)=\"$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)=\"onContextSaveAsBlock($event)\">\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 </div>\n </div>\n\n <!-- Backdrop to close more menu or context menu -->\n <div *ngIf=\"moreMenuVisible || contextMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu(); closeContextMenu()\">\n </div>\n\n <!-- Right-click context menu -->\n <div *ngIf=\"contextMenuVisible\" class=\"overlay-context-menu\"\n [ngStyle]=\"contextMenuStyle\"\n (click)=\"$event.stopPropagation()\">\n <button class=\"context-menu-item\" (mousedown)=\"onContextSaveAsBlock($event)\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\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}.select-toolbar .toolbar-more-dropdown{position:absolute;top:100%;right:0;left:auto;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;margin-top:2px}.select-toolbar .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}.select-toolbar .toolbar-more-dropdown .more-item i{font-size:14px}.select-toolbar .toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.select-toolbar .toolbar-more-dropdown .more-item--danger{color:#c84040}.select-toolbar .toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.select-toolbar .toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.select-toolbar .toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}.overlay-context-menu{position:fixed;z-index:999;background:#fff;border:1px solid var(--p-surface-200);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.overlay-context-menu .context-menu-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}.overlay-context-menu .context-menu-item i{font-size:14px}.overlay-context-menu .context-menu-item:hover{background:var(--p-surface-100, #f5f5f5)}\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 }); }
|
|
1881
|
+
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: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1882
|
+
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 (contextmenu)=\"onContextMenu($event)\">\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 last -->\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\n <!-- More dropdown (inline, positioned from toolbar) -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" (click)=\"$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)=\"onContextSaveAsBlock($event)\">\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 </div>\n </div>\n\n <!-- Backdrop to close more menu or context menu -->\n <div *ngIf=\"moreMenuVisible || contextMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu(); closeContextMenu()\">\n </div>\n\n <!-- Right-click context menu -->\n <div *ngIf=\"contextMenuVisible\" class=\"overlay-context-menu\"\n [ngStyle]=\"contextMenuStyle\"\n (click)=\"$event.stopPropagation()\">\n <button class=\"context-menu-item\" (mousedown)=\"onContextSaveAsBlock($event)\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\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}.select-toolbar .toolbar-more-dropdown{position:absolute;top:100%;right:0;left:auto;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;margin-top:2px}.select-toolbar .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}.select-toolbar .toolbar-more-dropdown .more-item i{font-size:14px}.select-toolbar .toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.select-toolbar .toolbar-more-dropdown .more-item--danger{color:#c84040}.select-toolbar .toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.select-toolbar .toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.select-toolbar .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}.overlay-context-menu{position:fixed;z-index:999;background:#fff;border:1px solid var(--p-surface-200);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.overlay-context-menu .context-menu-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}.overlay-context-menu .context-menu-item i{font-size:14px}.overlay-context-menu .context-menu-item:hover{background:var(--p-surface-100, #f5f5f5)}\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 }); }
|
|
1784
1883
|
}
|
|
1785
1884
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OverlayComponent, decorators: [{
|
|
1786
1885
|
type: Component,
|
|
1787
|
-
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 (contextmenu)=\"onContextMenu($event)\">\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 last -->\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\n <!-- More dropdown (inline, positioned from toolbar) -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" (click)=\"$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)=\"onContextSaveAsBlock($event)\">\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 </div>\n </div>\n\n <!-- Backdrop to close more menu or context menu -->\n <div *ngIf=\"moreMenuVisible || contextMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu(); closeContextMenu()\">\n </div>\n\n <!-- Right-click context menu -->\n <div *ngIf=\"contextMenuVisible\" class=\"overlay-context-menu\"\n [ngStyle]=\"contextMenuStyle\"\n (click)=\"$event.stopPropagation()\">\n <button class=\"context-menu-item\" (mousedown)=\"onContextSaveAsBlock($event)\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\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}.select-toolbar .toolbar-more-dropdown{position:absolute;top:100%;right:0;left:auto;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;margin-top:2px}.select-toolbar .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}.select-toolbar .toolbar-more-dropdown .more-item i{font-size:14px}.select-toolbar .toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.select-toolbar .toolbar-more-dropdown .more-item--danger{color:#c84040}.select-toolbar .toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.select-toolbar .toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.select-toolbar .toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}.overlay-context-menu{position:fixed;z-index:999;background:#fff;border:1px solid var(--p-surface-200);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.overlay-context-menu .context-menu-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}.overlay-context-menu .context-menu-item i{font-size:14px}.overlay-context-menu .context-menu-item:hover{background:var(--p-surface-100, #f5f5f5)}\n"] }]
|
|
1788
|
-
}], ctorParameters: () => [{ type: OverlayService }, { type: ViewportService }, { type: i0.ChangeDetectorRef }], propDecorators: { toolbarAction: [{
|
|
1886
|
+
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 (contextmenu)=\"onContextMenu($event)\">\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 last -->\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\n <!-- More dropdown (inline, positioned from toolbar) -->\n <div *ngIf=\"moreMenuVisible\" class=\"toolbar-more-dropdown\" (click)=\"$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)=\"onContextSaveAsBlock($event)\">\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 </div>\n </div>\n\n <!-- Backdrop to close more menu or context menu -->\n <div *ngIf=\"moreMenuVisible || contextMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeMoreMenu(); closeContextMenu()\">\n </div>\n\n <!-- Right-click context menu -->\n <div *ngIf=\"contextMenuVisible\" class=\"overlay-context-menu\"\n [ngStyle]=\"contextMenuStyle\"\n (click)=\"$event.stopPropagation()\">\n <button class=\"context-menu-item\" (mousedown)=\"onContextSaveAsBlock($event)\">\n <i class=\"ph-thin ph-bookmark\"></i>\n Save as reusable block\n </button>\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}.select-toolbar .toolbar-more-dropdown{position:absolute;top:100%;right:0;left:auto;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;margin-top:2px}.select-toolbar .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}.select-toolbar .toolbar-more-dropdown .more-item i{font-size:14px}.select-toolbar .toolbar-more-dropdown .more-item:hover{background:var(--p-surface-100, #f5f5f5)}.select-toolbar .toolbar-more-dropdown .more-item--danger{color:#c84040}.select-toolbar .toolbar-more-dropdown .more-item--danger:hover{background:#c8404014}.select-toolbar .toolbar-more-dropdown .more-item--play{color:var(--p-text-color, #333)}.select-toolbar .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}.overlay-context-menu{position:fixed;z-index:999;background:#fff;border:1px solid var(--p-surface-200);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:200px;pointer-events:all}.overlay-context-menu .context-menu-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}.overlay-context-menu .context-menu-item i{font-size:14px}.overlay-context-menu .context-menu-item:hover{background:var(--p-surface-100, #f5f5f5)}\n"] }]
|
|
1887
|
+
}], ctorParameters: () => [{ type: OverlayService }, { type: ViewportService }, { type: PresetRegistryService }, { type: i0.ChangeDetectorRef }], propDecorators: { toolbarAction: [{
|
|
1789
1888
|
type: Output
|
|
1790
1889
|
}] } });
|
|
1791
1890
|
|
|
@@ -2617,6 +2716,11 @@ class BuilderComponent {
|
|
|
2617
2716
|
}
|
|
2618
2717
|
break;
|
|
2619
2718
|
}
|
|
2719
|
+
case ToolbarAction.EditPreset: {
|
|
2720
|
+
this.panelEventService.emit(PanelEventTypes.PRESET_EDIT, node.stylePresetId);
|
|
2721
|
+
this.panelEventService.emit(this.isPanelOpen ? PanelEventTypes.PANEL_SELECTED : PanelEventTypes.PANEL_OPEN, PanelTypes.STYLES);
|
|
2722
|
+
break;
|
|
2723
|
+
}
|
|
2620
2724
|
}
|
|
2621
2725
|
}
|
|
2622
2726
|
confirmSaveBlock() {
|
|
@@ -3560,6 +3664,30 @@ const ACTION_TYPE_OPTIONS = [
|
|
|
3560
3664
|
{ value: 'toggleVisibility', label: 'Toggle visibility' },
|
|
3561
3665
|
];
|
|
3562
3666
|
const EASING_OPTIONS = ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'];
|
|
3667
|
+
/**
|
|
3668
|
+
* Build a full StyleTraitGroup[] schema populated with values from a flat
|
|
3669
|
+
* styleProps map. Used when editing a preset in the Style panel — the panel
|
|
3670
|
+
* receives the same `StyleTraitGroup[]` shape regardless of context.
|
|
3671
|
+
*/
|
|
3672
|
+
function buildPresetStyleTraits(styleProps) {
|
|
3673
|
+
const allGroups = [
|
|
3674
|
+
new LayoutGroupStyleConfig(),
|
|
3675
|
+
new SizeGroupStyleConfig(),
|
|
3676
|
+
new BackgroundGroupStyleConfig(),
|
|
3677
|
+
new SpacingGroupStyleConfig(),
|
|
3678
|
+
new BorderGroupStyleConfig(),
|
|
3679
|
+
new TypographyGroupStyleConfig(),
|
|
3680
|
+
new EffectsGroupStyleConfig(),
|
|
3681
|
+
new PositionGroupStyleConfig(),
|
|
3682
|
+
];
|
|
3683
|
+
return allGroups.map(group => ({
|
|
3684
|
+
...group,
|
|
3685
|
+
traits: group.traits.map(trait => ({
|
|
3686
|
+
...trait,
|
|
3687
|
+
default: styleProps[trait.name] !== undefined ? styleProps[trait.name] : trait.default,
|
|
3688
|
+
})),
|
|
3689
|
+
}));
|
|
3690
|
+
}
|
|
3563
3691
|
var TraitInputType;
|
|
3564
3692
|
(function (TraitInputType) {
|
|
3565
3693
|
TraitInputType["Text"] = "text";
|
|
@@ -4034,6 +4162,7 @@ class IoxBuilderModule {
|
|
|
4034
4162
|
ViewportService,
|
|
4035
4163
|
StyleRegistryService,
|
|
4036
4164
|
PanelEventService,
|
|
4165
|
+
PresetRegistryService,
|
|
4037
4166
|
], imports: [CommonModule,
|
|
4038
4167
|
FormsModule,
|
|
4039
4168
|
DragDropModule,
|
|
@@ -4084,6 +4213,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
4084
4213
|
ViewportService,
|
|
4085
4214
|
StyleRegistryService,
|
|
4086
4215
|
PanelEventService,
|
|
4216
|
+
PresetRegistryService,
|
|
4087
4217
|
],
|
|
4088
4218
|
exports: [
|
|
4089
4219
|
// Angular/PrimeNG modules re-exported so consumers can use them
|
|
@@ -4477,5 +4607,5 @@ class TextBlockComponentConfig extends ComponentConfig {
|
|
|
4477
4607
|
* Generated bundle index. Do not edit.
|
|
4478
4608
|
*/
|
|
4479
4609
|
|
|
4480
|
-
export { ACTION_TYPE_OPTIONS, BuilderButtonComponentConfig, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, CardComponentConfig, ComponentConfig, ComponentRegistryService, DEVICE_OPTIONS, DataSourceRegistryService, DeviceMode, DragEngineService, EASING_OPTIONS$1 as EASING_OPTIONS, GroupStyleConfig, IOX_CONTENT_SERVICE, IOX_FONT_MANAGER, InteractionEngineService, InteractionsPanelComponent, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LayerTreeComponent, NodeAction, OverlayComponent, OverlayService, PanelChildComponent, PanelComponent, PanelEventService, PanelEventTypes, PanelTypes, ROUTE_ANIMATION_OPTIONS, RenderDirective, RepeaterComponentConfig, SCREEN_WIDTH_OPTIONS, SectionComponent, SectionComponentConfig, StyleCategory, StyleRegistryService, TraitConfig as StyleTraitConfig, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, ViewportService, ZOOM_OPTIONS, defaultPageSettings, generateNodeId, resolveTraitControllerType, resolveTraitOptions };
|
|
4610
|
+
export { ACTION_TYPE_OPTIONS, BuilderButtonComponentConfig, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, CardComponentConfig, ComponentConfig, ComponentRegistryService, DEVICE_OPTIONS, DataSourceRegistryService, DeviceMode, DragEngineService, EASING_OPTIONS$1 as EASING_OPTIONS, GroupStyleConfig, IOX_CONTENT_SERVICE, IOX_FONT_MANAGER, InteractionEngineService, InteractionsPanelComponent, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LayerTreeComponent, NodeAction, OverlayComponent, OverlayService, PanelChildComponent, PanelComponent, PanelEventService, PanelEventTypes, PanelTypes, PresetRegistryService, ROUTE_ANIMATION_OPTIONS, RenderDirective, RepeaterComponentConfig, SCREEN_WIDTH_OPTIONS, SectionComponent, SectionComponentConfig, StyleCategory, StyleRegistryService, TraitConfig as StyleTraitConfig, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, ViewportService, ZOOM_OPTIONS, buildPresetStyleTraits, defaultPageSettings, generateNodeId, resolveTraitControllerType, resolveTraitOptions };
|
|
4481
4611
|
//# sourceMappingURL=vectoriox-iox-builder.mjs.map
|