@vectoriox/iox-builder 3.5.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -16,7 +16,7 @@ import { SelectModule } from 'primeng/select';
|
|
|
16
16
|
import { TooltipModule } from 'primeng/tooltip';
|
|
17
17
|
import { DialogModule } from 'primeng/dialog';
|
|
18
18
|
import * as i16 from '@vectoriox/iox-ui';
|
|
19
|
-
import { DEFAULT_WIDTH_BY_TYPE, ContextStore, ComponentInstanceRegistryService, isActionEnabled, isContextAction, contextActionEffect, resolveContextValue, buildTargetedStateSelector, compileDeclarations, safeSetInput, composeVirtualTraits, collectContextSlotKeys, withContextSlots, nodeUsesContext, resolvePath, applyBindingPipes, IS_PREVIEW, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, IoxPageModule } from '@vectoriox/iox-ui';
|
|
19
|
+
import { DEFAULT_WIDTH_BY_TYPE, Breakpoint, BREAKPOINTS, countOverrides, breakpointDef, breakpointForWidth, ContextStore, ComponentInstanceRegistryService, isActionEnabled, isContextAction, contextActionEffect, resolveContextValue, DeclarationContext, planResponsiveRules, resolveStyleProps, buildTargetedStateSelector, compileDeclarations, wrapInBreakpointQuery, BreakpointQueryKind, safeSetInput, composeVirtualTraits, stateNamesIn, collectContextSlotKeys, withContextSlots, nodeUsesContext, resolvePath, applyBindingPipes, IS_PREVIEW, planDataSource, dataSourcePlanToRequest, normalizeCollectionResult, resolveRepeaterItems, getByPath, computeRelative, IoxPageModule } from '@vectoriox/iox-ui';
|
|
20
20
|
export { ComponentInstanceRegistryService, VIRTUAL_TRAIT_KEYS, composeVirtualTraits } from '@vectoriox/iox-ui';
|
|
21
21
|
import Lenis from 'lenis';
|
|
22
22
|
import { Subject, BehaviorSubject, of, forkJoin } from 'rxjs';
|
|
@@ -843,10 +843,10 @@ class PanelEventService {
|
|
|
843
843
|
emit(type, data) {
|
|
844
844
|
this.panelEventSubject.next({ type, data });
|
|
845
845
|
}
|
|
846
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
847
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
846
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PanelEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
847
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PanelEventService }); }
|
|
848
848
|
}
|
|
849
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
849
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PanelEventService, decorators: [{
|
|
850
850
|
type: Injectable
|
|
851
851
|
}] });
|
|
852
852
|
|
|
@@ -943,17 +943,13 @@ var BuilderMode;
|
|
|
943
943
|
BuilderMode["Style"] = "style";
|
|
944
944
|
BuilderMode["Pan"] = "pan";
|
|
945
945
|
})(BuilderMode || (BuilderMode = {}));
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
{ mode: DeviceMode.Desktop, label: 'Desktop', icon: 'ph-thin ph-desktop', width: 1440, height: 900 },
|
|
954
|
-
{ mode: DeviceMode.Tablet, label: 'Tablet', icon: 'ph-thin ph-device-tablet', width: 768, height: 1024 },
|
|
955
|
-
{ mode: DeviceMode.Mobile, label: 'Mobile', icon: 'ph-thin ph-device-mobile', width: 375, height: 812 },
|
|
956
|
-
];
|
|
946
|
+
const BREAKPOINT_PRESENTATION = Object.freeze({
|
|
947
|
+
[Breakpoint.Base]: { icon: 'ph-thin ph-desktop', previewHeight: 900 },
|
|
948
|
+
[Breakpoint.Laptop]: { icon: 'ph-thin ph-laptop', previewHeight: 800 },
|
|
949
|
+
[Breakpoint.Tablet]: { icon: 'ph-thin ph-device-tablet', previewHeight: 1024 },
|
|
950
|
+
[Breakpoint.Mobile]: { icon: 'ph-thin ph-device-mobile', previewHeight: 320, landscape: true },
|
|
951
|
+
[Breakpoint.Small]: { icon: 'ph-thin ph-device-mobile', previewHeight: 844 },
|
|
952
|
+
});
|
|
957
953
|
const ZOOM_OPTIONS = [
|
|
958
954
|
{ label: '25%', value: 25 },
|
|
959
955
|
{ label: '50%', value: 50 },
|
|
@@ -1019,6 +1015,35 @@ function nodeAncestorPathInEither(layout, globalElements, target) {
|
|
|
1019
1015
|
return nodeAncestorPath(layout, target) ?? nodeAncestorPath(globalElements, target);
|
|
1020
1016
|
}
|
|
1021
1017
|
|
|
1018
|
+
/** Counts for ONE node (the selection). Breakpoints with nothing overridden are omitted. */
|
|
1019
|
+
function nodeBreakpointCounts(node) {
|
|
1020
|
+
const counts = {};
|
|
1021
|
+
if (!node?.responsive)
|
|
1022
|
+
return counts;
|
|
1023
|
+
for (const { id } of BREAKPOINTS) {
|
|
1024
|
+
if (id === Breakpoint.Base)
|
|
1025
|
+
continue;
|
|
1026
|
+
const n = countOverrides(node.responsive, id);
|
|
1027
|
+
if (n)
|
|
1028
|
+
counts[id] = n;
|
|
1029
|
+
}
|
|
1030
|
+
return counts;
|
|
1031
|
+
}
|
|
1032
|
+
/** Counts summed over whole trees (the page, when nothing is selected). */
|
|
1033
|
+
function treeBreakpointCounts(...roots) {
|
|
1034
|
+
const counts = {};
|
|
1035
|
+
const visit = (nodes) => {
|
|
1036
|
+
for (const node of nodes ?? []) {
|
|
1037
|
+
for (const [bp, n] of Object.entries(nodeBreakpointCounts(node))) {
|
|
1038
|
+
counts[bp] = (counts[bp] ?? 0) + n;
|
|
1039
|
+
}
|
|
1040
|
+
visit(node.children);
|
|
1041
|
+
}
|
|
1042
|
+
};
|
|
1043
|
+
roots.forEach(visit);
|
|
1044
|
+
return counts;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1022
1047
|
class ComponentRegistryService {
|
|
1023
1048
|
constructor() {
|
|
1024
1049
|
this.components = {};
|
|
@@ -1039,10 +1064,10 @@ class ComponentRegistryService {
|
|
|
1039
1064
|
getAll() {
|
|
1040
1065
|
return Object.values(this.components);
|
|
1041
1066
|
}
|
|
1042
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1043
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1067
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: ComponentRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1068
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: ComponentRegistryService }); }
|
|
1044
1069
|
}
|
|
1045
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1070
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: ComponentRegistryService, decorators: [{
|
|
1046
1071
|
type: Injectable
|
|
1047
1072
|
}] });
|
|
1048
1073
|
|
|
@@ -1188,10 +1213,10 @@ class OverlayService {
|
|
|
1188
1213
|
border: { top: px(si.borderTopWidth), right: px(si.borderRightWidth), bottom: px(si.borderBottomWidth), left: px(si.borderLeftWidth) },
|
|
1189
1214
|
};
|
|
1190
1215
|
}
|
|
1191
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1192
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1216
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: OverlayService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1217
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: OverlayService }); }
|
|
1193
1218
|
}
|
|
1194
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1219
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: OverlayService, decorators: [{
|
|
1195
1220
|
type: Injectable
|
|
1196
1221
|
}] });
|
|
1197
1222
|
|
|
@@ -1262,10 +1287,10 @@ class SymbolRegistryService {
|
|
|
1262
1287
|
removeBlockSymbolId(id) {
|
|
1263
1288
|
this.blockSymbolIds.delete(id);
|
|
1264
1289
|
}
|
|
1265
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1266
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1290
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SymbolRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1291
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SymbolRegistryService }); }
|
|
1267
1292
|
}
|
|
1268
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1293
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SymbolRegistryService, decorators: [{
|
|
1269
1294
|
type: Injectable
|
|
1270
1295
|
}] });
|
|
1271
1296
|
|
|
@@ -2046,10 +2071,10 @@ class DragEngineService {
|
|
|
2046
2071
|
}
|
|
2047
2072
|
return children.length;
|
|
2048
2073
|
}
|
|
2049
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2050
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2074
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DragEngineService, deps: [{ token: ComponentRegistryService }, { token: SymbolRegistryService }, { token: OverlayService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2075
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DragEngineService }); }
|
|
2051
2076
|
}
|
|
2052
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2077
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DragEngineService, decorators: [{
|
|
2053
2078
|
type: Injectable
|
|
2054
2079
|
}], ctorParameters: () => [{ type: ComponentRegistryService }, { type: SymbolRegistryService }, { type: OverlayService }] });
|
|
2055
2080
|
|
|
@@ -2078,14 +2103,15 @@ class DataSourceRegistryService {
|
|
|
2078
2103
|
getAliasOptions() {
|
|
2079
2104
|
return this._ds$.value.map(ds => ({ label: ds.alias, value: ds.alias }));
|
|
2080
2105
|
}
|
|
2081
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2082
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2106
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DataSourceRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2107
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DataSourceRegistryService }); }
|
|
2083
2108
|
}
|
|
2084
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2109
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: DataSourceRegistryService, decorators: [{
|
|
2085
2110
|
type: Injectable
|
|
2086
2111
|
}] });
|
|
2087
2112
|
|
|
2088
2113
|
const STORAGE_KEY = 'iox_builder_viewport';
|
|
2114
|
+
const DEFAULT_WIDTH = breakpointDef(Breakpoint.Base).previewWidth;
|
|
2089
2115
|
class ViewportService {
|
|
2090
2116
|
constructor() {
|
|
2091
2117
|
this.state = this.loadFromStorage();
|
|
@@ -2098,15 +2124,17 @@ class ViewportService {
|
|
|
2098
2124
|
getScale() {
|
|
2099
2125
|
return this.state.scale;
|
|
2100
2126
|
}
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2127
|
+
/** Show (and edit) `bp`: the canvas takes that breakpoint's preview width and height. */
|
|
2128
|
+
setBreakpoint(bp) {
|
|
2129
|
+
const def = breakpointDef(bp);
|
|
2130
|
+
if (!def)
|
|
2104
2131
|
return;
|
|
2105
|
-
this.update({
|
|
2132
|
+
this.update({ width: def.previewWidth, height: BREAKPOINT_PRESENTATION[bp].previewHeight });
|
|
2106
2133
|
}
|
|
2107
2134
|
setScale(scale) {
|
|
2108
2135
|
this.update({ scale: Math.max(0.1, Math.min(2, scale)) });
|
|
2109
2136
|
}
|
|
2137
|
+
/** Any canvas width — the breakpoint follows from it. */
|
|
2110
2138
|
setWidth(width) {
|
|
2111
2139
|
this.update({ width });
|
|
2112
2140
|
}
|
|
@@ -2149,21 +2177,28 @@ class ViewportService {
|
|
|
2149
2177
|
};
|
|
2150
2178
|
}
|
|
2151
2179
|
update(partial) {
|
|
2152
|
-
|
|
2180
|
+
const next = { ...this.state, ...partial };
|
|
2181
|
+
this.state = { ...next, breakpoint: breakpointForWidth(next.width) };
|
|
2153
2182
|
this.stateSubject.next(this.state);
|
|
2154
2183
|
this.saveToStorage();
|
|
2155
2184
|
}
|
|
2156
2185
|
saveToStorage() {
|
|
2157
2186
|
try {
|
|
2158
|
-
|
|
2187
|
+
const { width, height, scale } = this.state;
|
|
2188
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify({ width, height, scale }));
|
|
2159
2189
|
}
|
|
2160
2190
|
catch { }
|
|
2161
2191
|
}
|
|
2192
|
+
/**
|
|
2193
|
+
* Restores width / height / scale. Older builds also saved a `device` ('desktop' | 'tablet' |
|
|
2194
|
+
* 'mobile'); it is ignored — the saved width (1440 / 768 / 375) already resolves to the
|
|
2195
|
+
* matching breakpoint (Base / Tablet / Small), so old preferences carry over unchanged.
|
|
2196
|
+
*/
|
|
2162
2197
|
loadFromStorage() {
|
|
2163
2198
|
const defaults = {
|
|
2164
|
-
|
|
2165
|
-
width:
|
|
2166
|
-
height:
|
|
2199
|
+
breakpoint: breakpointForWidth(DEFAULT_WIDTH),
|
|
2200
|
+
width: DEFAULT_WIDTH,
|
|
2201
|
+
height: BREAKPOINT_PRESENTATION[Breakpoint.Base].previewHeight,
|
|
2167
2202
|
scale: 0.75,
|
|
2168
2203
|
};
|
|
2169
2204
|
try {
|
|
@@ -2171,14 +2206,13 @@ class ViewportService {
|
|
|
2171
2206
|
if (!raw)
|
|
2172
2207
|
return defaults;
|
|
2173
2208
|
const saved = JSON.parse(raw);
|
|
2174
|
-
const
|
|
2175
|
-
|
|
2176
|
-
: defaults.device;
|
|
2177
|
-
const option = DEVICE_OPTIONS.find(d => d.mode === device) ?? DEVICE_OPTIONS[0];
|
|
2209
|
+
const width = typeof saved.width === 'number' && saved.width > 0 ? saved.width : defaults.width;
|
|
2210
|
+
const breakpoint = breakpointForWidth(width);
|
|
2178
2211
|
return {
|
|
2179
|
-
|
|
2180
|
-
width
|
|
2181
|
-
height: typeof saved.height === 'number' && saved.height > 0
|
|
2212
|
+
breakpoint,
|
|
2213
|
+
width,
|
|
2214
|
+
height: typeof saved.height === 'number' && saved.height > 0
|
|
2215
|
+
? saved.height : BREAKPOINT_PRESENTATION[breakpoint].previewHeight,
|
|
2182
2216
|
scale: typeof saved.scale === 'number' ? Math.max(0.1, Math.min(2, saved.scale)) : defaults.scale,
|
|
2183
2217
|
};
|
|
2184
2218
|
}
|
|
@@ -2186,10 +2220,10 @@ class ViewportService {
|
|
|
2186
2220
|
return defaults;
|
|
2187
2221
|
}
|
|
2188
2222
|
}
|
|
2189
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2190
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2223
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: ViewportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2224
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: ViewportService }); }
|
|
2191
2225
|
}
|
|
2192
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2226
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: ViewportService, decorators: [{
|
|
2193
2227
|
type: Injectable
|
|
2194
2228
|
}] });
|
|
2195
2229
|
|
|
@@ -2808,10 +2842,10 @@ class InteractionEngineService {
|
|
|
2808
2842
|
},
|
|
2809
2843
|
};
|
|
2810
2844
|
}
|
|
2811
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2812
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2845
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: InteractionEngineService, deps: [{ token: OverlayService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2846
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: InteractionEngineService }); }
|
|
2813
2847
|
}
|
|
2814
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2848
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: InteractionEngineService, decorators: [{
|
|
2815
2849
|
type: Injectable
|
|
2816
2850
|
}], ctorParameters: () => [{ type: OverlayService }] });
|
|
2817
2851
|
|
|
@@ -2843,10 +2877,10 @@ class InteractionPresetRegistryService {
|
|
|
2843
2877
|
remove(id) {
|
|
2844
2878
|
this.presets.delete(id);
|
|
2845
2879
|
}
|
|
2846
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2847
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2880
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: InteractionPresetRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2881
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: InteractionPresetRegistryService }); }
|
|
2848
2882
|
}
|
|
2849
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2883
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: InteractionPresetRegistryService, decorators: [{
|
|
2850
2884
|
type: Injectable
|
|
2851
2885
|
}] });
|
|
2852
2886
|
|
|
@@ -2874,13 +2908,20 @@ class BuilderClipboardService {
|
|
|
2874
2908
|
getPresetId() { return this._clip.presetId; }
|
|
2875
2909
|
getInteractionPresetId() { return this._clip.interactionPresetId; }
|
|
2876
2910
|
clear() { this._clip = {}; }
|
|
2877
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2878
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2911
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2912
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderClipboardService }); }
|
|
2879
2913
|
}
|
|
2880
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2914
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderClipboardService, decorators: [{
|
|
2881
2915
|
type: Injectable
|
|
2882
2916
|
}] });
|
|
2883
2917
|
|
|
2918
|
+
/**
|
|
2919
|
+
* CSS container name of the builder canvas frame (and of the global-elements overlay). Breakpoint
|
|
2920
|
+
* rules are emitted as `@container iox-canvas (max-width: …)`: the frame's layout width IS the
|
|
2921
|
+
* simulated viewport and is unaffected by the zoom `transform: scale`, whereas a `@media` query
|
|
2922
|
+
* would read the editor window. Set on the frame in builder.component.scss.
|
|
2923
|
+
*/
|
|
2924
|
+
const BUILDER_CANVAS_CONTAINER = 'iox-canvas';
|
|
2884
2925
|
/**
|
|
2885
2926
|
* StyleRegistryService — manages a single <style> tag for the builder canvas.
|
|
2886
2927
|
*
|
|
@@ -2907,6 +2948,14 @@ class StyleRegistryService {
|
|
|
2907
2948
|
constructor() {
|
|
2908
2949
|
this.changes$ = new Subject();
|
|
2909
2950
|
this.rules = new Map();
|
|
2951
|
+
/** Breakpoint rules, kept apart so they flush AFTER every base rule — equal specificity, so
|
|
2952
|
+
* source order decides (plan trap 1). Keyed per breakpoint like `rules` (`id`, `id:state`). */
|
|
2953
|
+
this.responsiveRules = new Map();
|
|
2954
|
+
this.responsiveInputs = new Map();
|
|
2955
|
+
/** Which breakpoint rule keys each node owns — so re-emitting one node's rules is O(its rules),
|
|
2956
|
+
* not a scan of every breakpoint rule on the page (this runs on every node render). */
|
|
2957
|
+
this.responsiveKeys = new Map();
|
|
2958
|
+
this.stateScopes = new Map();
|
|
2910
2959
|
this.styleEl = null;
|
|
2911
2960
|
this._flushPending = false;
|
|
2912
2961
|
}
|
|
@@ -2957,66 +3006,132 @@ class StyleRegistryService {
|
|
|
2957
3006
|
return;
|
|
2958
3007
|
if (state) {
|
|
2959
3008
|
const key = `${nodeId}:${state}`;
|
|
2960
|
-
//
|
|
2961
|
-
//
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
: '';
|
|
2968
|
-
if (css) {
|
|
2969
|
-
this.rules.set(key, css);
|
|
2970
|
-
}
|
|
2971
|
-
else {
|
|
2972
|
-
this.rules.delete(key);
|
|
2973
|
-
}
|
|
2974
|
-
this.flush();
|
|
2975
|
-
return;
|
|
2976
|
-
}
|
|
2977
|
-
// Relational states (parent-hover): the pseudo-class lives on an ANCESTOR
|
|
2978
|
-
// and cascades to this element. Requires the ancestor's css id.
|
|
2979
|
-
if (RELATIONAL_STATES.includes(state)) {
|
|
2980
|
-
const base = RELATIONAL_STATE_BASE[state];
|
|
2981
|
-
const css = (relativeToId && base)
|
|
2982
|
-
? this.compile(`iox-node-${relativeToId}:${base} .iox-node-${nodeId}`, styles)
|
|
2983
|
-
: '';
|
|
2984
|
-
if (css) {
|
|
2985
|
-
this.rules.set(key, css);
|
|
2986
|
-
}
|
|
2987
|
-
else {
|
|
2988
|
-
this.rules.delete(key);
|
|
2989
|
-
}
|
|
2990
|
-
this.flush();
|
|
2991
|
-
return;
|
|
2992
|
-
}
|
|
2993
|
-
// Structural pseudo-classes (first-child, last-child, nth-child) target the
|
|
2994
|
-
// outer wrapper element so they participate correctly in grid/flex layout.
|
|
2995
|
-
const prefix = STRUCTURAL_STATES.includes(state) ? 'iox-outer' : 'iox-node';
|
|
2996
|
-
const css = this.compile(`${prefix}-${nodeId}:${state}`, styles);
|
|
2997
|
-
if (css) {
|
|
3009
|
+
// Remember the scope a relational / targeted rule was given, so the same state at a
|
|
3010
|
+
// breakpoint is scoped identically without re-resolving it (see upsertResponsive).
|
|
3011
|
+
if (relativeToId || triggerId)
|
|
3012
|
+
this.stateScopes.set(key, { relativeToId, triggerId });
|
|
3013
|
+
const selector = this.stateSelector(nodeId, state, relativeToId, triggerId);
|
|
3014
|
+
const css = selector ? this.compile(selector, styles) : '';
|
|
3015
|
+
if (css)
|
|
2998
3016
|
this.rules.set(key, css);
|
|
2999
|
-
|
|
3000
|
-
else {
|
|
3017
|
+
else
|
|
3001
3018
|
this.rules.delete(key);
|
|
3002
|
-
|
|
3019
|
+
if (this.responsiveInputs.has(nodeId))
|
|
3020
|
+
this.emitResponsive(nodeId);
|
|
3003
3021
|
this.flush();
|
|
3004
3022
|
return;
|
|
3005
3023
|
}
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
if (markerCss)
|
|
3011
|
-
this.rules.set(`${nodeId}::marker`, markerCss);
|
|
3012
|
-
else
|
|
3013
|
-
this.rules.delete(`${nodeId}::marker`);
|
|
3014
|
-
}
|
|
3015
|
-
else {
|
|
3024
|
+
const { main, marker } = this.nodeRuleCss(nodeId, styles, this.isOutOfFlow(styles), DeclarationContext.Base);
|
|
3025
|
+
if (marker)
|
|
3026
|
+
this.rules.set(`${nodeId}::marker`, marker);
|
|
3027
|
+
else
|
|
3016
3028
|
this.rules.delete(`${nodeId}::marker`);
|
|
3029
|
+
if (main)
|
|
3030
|
+
this.rules.set(nodeId, main);
|
|
3031
|
+
else
|
|
3032
|
+
this.rules.delete(nodeId);
|
|
3033
|
+
this.flush();
|
|
3034
|
+
}
|
|
3035
|
+
/**
|
|
3036
|
+
* Emit (or clear) a node's breakpoint rules. `planResponsiveRules` — shared with the SSR engine —
|
|
3037
|
+
* decides what each breakpoint emits; this only turns it into selectors, through the SAME
|
|
3038
|
+
* inner/outer split and state selectors as the base rules, compiled in the Override context
|
|
3039
|
+
* (a CSS initial value undoes the wider rule there, so it must not be dropped).
|
|
3040
|
+
*
|
|
3041
|
+
* @param styleProps The node's full BASE style map (raw — virtual traits not yet composed).
|
|
3042
|
+
*/
|
|
3043
|
+
upsertResponsive(nodeId, styleProps, stateStyles, responsive) {
|
|
3044
|
+
if (!nodeId)
|
|
3045
|
+
return;
|
|
3046
|
+
const hasOverrides = !!responsive && Object.keys(responsive).length > 0;
|
|
3047
|
+
// The common case — a node with no overrides that never had any — costs nothing.
|
|
3048
|
+
if (!hasOverrides && !this.responsiveInputs.has(nodeId))
|
|
3049
|
+
return;
|
|
3050
|
+
if (hasOverrides)
|
|
3051
|
+
this.responsiveInputs.set(nodeId, { styleProps, stateStyles, responsive: responsive });
|
|
3052
|
+
else
|
|
3053
|
+
this.responsiveInputs.delete(nodeId);
|
|
3054
|
+
this.emitResponsive(nodeId);
|
|
3055
|
+
this.flush();
|
|
3056
|
+
}
|
|
3057
|
+
emitResponsive(nodeId) {
|
|
3058
|
+
this.clearResponsive(nodeId);
|
|
3059
|
+
const input = this.responsiveInputs.get(nodeId);
|
|
3060
|
+
if (!input)
|
|
3061
|
+
return;
|
|
3062
|
+
for (const layer of planResponsiveRules(input.styleProps, input.stateStyles, input.responsive)) {
|
|
3063
|
+
const bp = layer.breakpoint;
|
|
3064
|
+
// Where `width` lands depends on the position in force AT this breakpoint.
|
|
3065
|
+
const outOfFlow = this.isOutOfFlow(resolveStyleProps(input.styleProps, input.responsive, bp));
|
|
3066
|
+
const { main, marker } = this.nodeRuleCss(nodeId, layer.styleProps, outOfFlow, DeclarationContext.Override);
|
|
3067
|
+
if (main)
|
|
3068
|
+
this.setResponsiveRule(nodeId, bp, nodeId, main);
|
|
3069
|
+
if (marker)
|
|
3070
|
+
this.setResponsiveRule(nodeId, bp, `${nodeId}::marker`, marker);
|
|
3071
|
+
for (const [state, map] of Object.entries(layer.stateStyles)) {
|
|
3072
|
+
const scope = this.stateScopes.get(`${nodeId}:${state}`);
|
|
3073
|
+
const selector = this.stateSelector(nodeId, state, scope?.relativeToId, scope?.triggerId);
|
|
3074
|
+
// A relational/targeted state whose scope isn't known yet is skipped; it is re-emitted
|
|
3075
|
+
// when the base state rule arrives with its scope (see upsert).
|
|
3076
|
+
const css = selector ? this.compile(selector, map, DeclarationContext.Override) : '';
|
|
3077
|
+
if (css)
|
|
3078
|
+
this.setResponsiveRule(nodeId, bp, `${nodeId}:${state}`, css);
|
|
3079
|
+
}
|
|
3017
3080
|
}
|
|
3081
|
+
}
|
|
3082
|
+
setResponsiveRule(nodeId, bp, key, css) {
|
|
3083
|
+
let bucket = this.responsiveRules.get(bp);
|
|
3084
|
+
if (!bucket)
|
|
3085
|
+
this.responsiveRules.set(bp, (bucket = new Map()));
|
|
3086
|
+
bucket.set(key, css);
|
|
3087
|
+
let owned = this.responsiveKeys.get(nodeId);
|
|
3088
|
+
if (!owned)
|
|
3089
|
+
this.responsiveKeys.set(nodeId, (owned = []));
|
|
3090
|
+
owned.push([bp, key]);
|
|
3091
|
+
}
|
|
3092
|
+
clearResponsive(nodeId) {
|
|
3093
|
+
for (const [bp, key] of this.responsiveKeys.get(nodeId) ?? [])
|
|
3094
|
+
this.responsiveRules.get(bp)?.delete(key);
|
|
3095
|
+
this.responsiveKeys.delete(nodeId);
|
|
3096
|
+
}
|
|
3097
|
+
isOutOfFlow(styles) {
|
|
3018
3098
|
const pos = String(styles['position'] ?? '');
|
|
3019
|
-
|
|
3099
|
+
return pos === 'fixed' || pos === 'absolute';
|
|
3100
|
+
}
|
|
3101
|
+
/**
|
|
3102
|
+
* The selector BODY (no leading dot) for a state rule, or null when a relational / targeted
|
|
3103
|
+
* state has no scope yet (emitting it unscoped would be wrong — a page-global `:has()`).
|
|
3104
|
+
*/
|
|
3105
|
+
stateSelector(nodeId, state, relativeToId, triggerId) {
|
|
3106
|
+
// Targeted states (trigger-hover): the styled node restyles when an ARBITRARY chosen
|
|
3107
|
+
// element is hovered. The selector is `:has()`-scoped to `relativeToId` (the nearest
|
|
3108
|
+
// common ancestor of styled + trigger) so it stays repetition-safe with one shared rule.
|
|
3109
|
+
if (TARGETED_STATES.includes(state)) {
|
|
3110
|
+
const base = TARGETED_STATE_BASE[state];
|
|
3111
|
+
return relativeToId && triggerId && base
|
|
3112
|
+
? buildTargetedStateSelector(relativeToId, triggerId, nodeId, base) : null;
|
|
3113
|
+
}
|
|
3114
|
+
// Relational states (parent-hover): the pseudo-class lives on an ANCESTOR
|
|
3115
|
+
// and cascades to this element. Requires the ancestor's css id.
|
|
3116
|
+
if (RELATIONAL_STATES.includes(state)) {
|
|
3117
|
+
const base = RELATIONAL_STATE_BASE[state];
|
|
3118
|
+
return relativeToId && base ? `iox-node-${relativeToId}:${base} .iox-node-${nodeId}` : null;
|
|
3119
|
+
}
|
|
3120
|
+
// Structural pseudo-classes (first-child, last-child, nth-child) target the
|
|
3121
|
+
// outer wrapper element so they participate correctly in grid/flex layout.
|
|
3122
|
+
const prefix = STRUCTURAL_STATES.includes(state) ? 'iox-outer' : 'iox-node';
|
|
3123
|
+
return `${prefix}-${nodeId}:${state}`;
|
|
3124
|
+
}
|
|
3125
|
+
/**
|
|
3126
|
+
* The inner + outer rule (joined) and the `::marker` rule for one composed style map.
|
|
3127
|
+
* `isOutOfFlow` is passed in rather than read from `styles` because a breakpoint layer is
|
|
3128
|
+
* sparse — the position in force may come from a wider layer.
|
|
3129
|
+
*/
|
|
3130
|
+
nodeRuleCss(nodeId, styles, isOutOfFlow, context) {
|
|
3131
|
+
// ::marker pseudo-element — emitted as a separate rule, not part of inner/outer split.
|
|
3132
|
+
const markerStyles = styles['__markerStyles'];
|
|
3133
|
+
const marker = markerStyles && Object.keys(markerStyles).length
|
|
3134
|
+
? this.compile(`iox-node-${nodeId}::marker`, markerStyles, context) : '';
|
|
3020
3135
|
const inner = {};
|
|
3021
3136
|
const outer = {};
|
|
3022
3137
|
for (const [k, v] of Object.entries(styles)) {
|
|
@@ -3031,20 +3146,14 @@ class StyleRegistryService {
|
|
|
3031
3146
|
inner[k] = v;
|
|
3032
3147
|
}
|
|
3033
3148
|
}
|
|
3034
|
-
// Ensure fixed/absolute elements stay visible when no explicit width is set
|
|
3035
|
-
|
|
3149
|
+
// Ensure fixed/absolute elements stay visible when no explicit width is set. A base-rule
|
|
3150
|
+
// render default only — a sparse breakpoint layer must not invent a width.
|
|
3151
|
+
if (context === DeclarationContext.Base && isOutOfFlow && inner['width'] === undefined) {
|
|
3036
3152
|
inner['width'] = '100%';
|
|
3037
3153
|
}
|
|
3038
|
-
const innerCss = this.compile(`iox-node-${nodeId}`, inner);
|
|
3039
|
-
const outerCss = this.compile(`iox-outer-${nodeId}`, outer);
|
|
3040
|
-
|
|
3041
|
-
if (combined) {
|
|
3042
|
-
this.rules.set(nodeId, combined);
|
|
3043
|
-
}
|
|
3044
|
-
else {
|
|
3045
|
-
this.rules.delete(nodeId);
|
|
3046
|
-
}
|
|
3047
|
-
this.flush();
|
|
3154
|
+
const innerCss = this.compile(`iox-node-${nodeId}`, inner, context);
|
|
3155
|
+
const outerCss = this.compile(`iox-outer-${nodeId}`, outer, context);
|
|
3156
|
+
return { main: [innerCss, outerCss].filter(Boolean).join('\n'), marker };
|
|
3048
3157
|
}
|
|
3049
3158
|
/**
|
|
3050
3159
|
* Write the org-level design token variables as a `:root { … }` block.
|
|
@@ -3074,20 +3183,30 @@ class StyleRegistryService {
|
|
|
3074
3183
|
this.rules.delete(key);
|
|
3075
3184
|
}
|
|
3076
3185
|
}
|
|
3186
|
+
for (const key of this.stateScopes.keys()) {
|
|
3187
|
+
if (key.startsWith(`${nodeId}:`))
|
|
3188
|
+
this.stateScopes.delete(key);
|
|
3189
|
+
}
|
|
3190
|
+
this.responsiveInputs.delete(nodeId);
|
|
3191
|
+
this.clearResponsive(nodeId);
|
|
3077
3192
|
this.flush();
|
|
3078
3193
|
}
|
|
3079
3194
|
destroy() {
|
|
3080
3195
|
this.rules.clear();
|
|
3196
|
+
this.responsiveRules.clear();
|
|
3197
|
+
this.responsiveInputs.clear();
|
|
3198
|
+
this.responsiveKeys.clear();
|
|
3199
|
+
this.stateScopes.clear();
|
|
3081
3200
|
if (this.styleEl) {
|
|
3082
3201
|
this.styleEl.remove();
|
|
3083
3202
|
this.styleEl = null;
|
|
3084
3203
|
}
|
|
3085
3204
|
}
|
|
3086
|
-
compile(className, styles) {
|
|
3205
|
+
compile(className, styles, context = DeclarationContext.Base) {
|
|
3087
3206
|
// Declaration compilation (kebab-case, viewport-unit rewrite, !important) lives in
|
|
3088
3207
|
// the shared style-compiler so the SSR engine produces byte-identical output.
|
|
3089
3208
|
// The inner/outer partition + selector emission stay here (builder-only concern).
|
|
3090
|
-
const decls = compileDeclarations(styles, StyleRegistryService.IMPORTANT_PROPS);
|
|
3209
|
+
const decls = compileDeclarations(styles, StyleRegistryService.IMPORTANT_PROPS, context);
|
|
3091
3210
|
if (!decls.length)
|
|
3092
3211
|
return '';
|
|
3093
3212
|
const body = decls.map(d => ` ${d};`).join('\n');
|
|
@@ -3106,14 +3225,20 @@ class StyleRegistryService {
|
|
|
3106
3225
|
const rest = Array.from(this.rules.entries())
|
|
3107
3226
|
.filter(([k]) => k !== '__tokens__')
|
|
3108
3227
|
.map(([, v]) => v);
|
|
3109
|
-
|
|
3228
|
+
// Breakpoint rules LAST, widest → narrowest, each as a canvas container query.
|
|
3229
|
+
const breakpoints = BREAKPOINTS
|
|
3230
|
+
.map(({ id }) => this.responsiveRules.get(id))
|
|
3231
|
+
.map((bucket, i) => bucket?.size
|
|
3232
|
+
? wrapInBreakpointQuery(BREAKPOINTS[i].id, Array.from(bucket.values()).join('\n'), BreakpointQueryKind.Container, BUILDER_CANVAS_CONTAINER)
|
|
3233
|
+
: '');
|
|
3234
|
+
this.styleEl.textContent = [tokenBlock, ...rest, ...breakpoints].filter(Boolean).join('\n');
|
|
3110
3235
|
this.changes$.next();
|
|
3111
3236
|
});
|
|
3112
3237
|
}
|
|
3113
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3114
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
3238
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: StyleRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3239
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: StyleRegistryService }); }
|
|
3115
3240
|
}
|
|
3116
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3241
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: StyleRegistryService, decorators: [{
|
|
3117
3242
|
type: Injectable
|
|
3118
3243
|
}] });
|
|
3119
3244
|
|
|
@@ -3460,10 +3585,10 @@ class MoveableCanvasService {
|
|
|
3460
3585
|
}
|
|
3461
3586
|
return idx;
|
|
3462
3587
|
}
|
|
3463
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3464
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
3588
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: MoveableCanvasService, deps: [{ token: DragEngineService }, { token: StyleRegistryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3589
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: MoveableCanvasService, providedIn: 'root' }); }
|
|
3465
3590
|
}
|
|
3466
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3591
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: MoveableCanvasService, decorators: [{
|
|
3467
3592
|
type: Injectable,
|
|
3468
3593
|
args: [{ providedIn: 'root' }]
|
|
3469
3594
|
}], ctorParameters: () => [{ type: DragEngineService }, { type: StyleRegistryService }] });
|
|
@@ -3523,10 +3648,10 @@ class SelectoCanvasService {
|
|
|
3523
3648
|
this.selecto?.destroy();
|
|
3524
3649
|
this.selecto = null;
|
|
3525
3650
|
}
|
|
3526
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3527
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
3651
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SelectoCanvasService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3652
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SelectoCanvasService, providedIn: 'root' }); }
|
|
3528
3653
|
}
|
|
3529
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3654
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SelectoCanvasService, decorators: [{
|
|
3530
3655
|
type: Injectable,
|
|
3531
3656
|
args: [{ providedIn: 'root' }]
|
|
3532
3657
|
}] });
|
|
@@ -3753,12 +3878,17 @@ class RenderDirective {
|
|
|
3753
3878
|
const composedBase = composeVirtualTraits(initialStyle);
|
|
3754
3879
|
this.styleRegistry.upsert(cssId, composedBase);
|
|
3755
3880
|
// Restore per-state overrides saved from a previous session.
|
|
3756
|
-
|
|
3881
|
+
// Every state set at base OR at any breakpoint — so a breakpoint-only state (a Mobile-only
|
|
3882
|
+
// parent-hover) still has its scope resolved and recorded for its breakpoint rule.
|
|
3883
|
+
const stateNames = stateNamesIn(node.stateStyles, node.responsive);
|
|
3884
|
+
if (stateNames.length) {
|
|
3757
3885
|
const childEl = componentRef.location?.nativeElement;
|
|
3758
|
-
for (const state of
|
|
3759
|
-
const
|
|
3760
|
-
|
|
3761
|
-
|
|
3886
|
+
for (const state of stateNames) {
|
|
3887
|
+
const baseMap = node.stateStyles?.[state] ?? {};
|
|
3888
|
+
// A state set only at a breakpoint has no base rule: upsert an EMPTY map (records the
|
|
3889
|
+
// scope, emits nothing) rather than composing an empty override against the base,
|
|
3890
|
+
// which would re-declare the base's transform/filter as a pointless hover rule.
|
|
3891
|
+
const stateMap = Object.keys(baseMap).length ? baseMap : null;
|
|
3762
3892
|
if (RELATIONAL_STATES.includes(state)) {
|
|
3763
3893
|
// Relational states (parent-hover) compile to
|
|
3764
3894
|
// `.iox-node-{parentId}:hover .iox-node-{childId}` — they need the CURRENT parent id.
|
|
@@ -3769,7 +3899,7 @@ class RenderDirective {
|
|
|
3769
3899
|
const relativeToId = this.resolveParentNodeId(childEl);
|
|
3770
3900
|
if (!relativeToId)
|
|
3771
3901
|
continue;
|
|
3772
|
-
this.styleRegistry.upsert(cssId, composeVirtualTraits(stateMap, initialStyle), state, relativeToId);
|
|
3902
|
+
this.styleRegistry.upsert(cssId, stateMap ? composeVirtualTraits(stateMap, initialStyle) : {}, state, relativeToId);
|
|
3773
3903
|
}
|
|
3774
3904
|
else if (TARGETED_STATES.includes(state)) {
|
|
3775
3905
|
// Targeted states (trigger-hover) compile to a `:has()` scoped to the nearest
|
|
@@ -3784,13 +3914,15 @@ class RenderDirective {
|
|
|
3784
3914
|
const scopeId = this.resolveTargetedScopeId(childEl, triggerCssId);
|
|
3785
3915
|
if (!scopeId)
|
|
3786
3916
|
continue;
|
|
3787
|
-
this.styleRegistry.upsert(cssId, composeVirtualTraits(stateMap, initialStyle), state, scopeId, triggerCssId);
|
|
3917
|
+
this.styleRegistry.upsert(cssId, stateMap ? composeVirtualTraits(stateMap, initialStyle) : {}, state, scopeId, triggerCssId);
|
|
3788
3918
|
}
|
|
3789
|
-
else {
|
|
3919
|
+
else if (stateMap) {
|
|
3790
3920
|
this.styleRegistry.upsert(cssId, composeVirtualTraits(stateMap, initialStyle), state);
|
|
3791
3921
|
}
|
|
3792
3922
|
}
|
|
3793
3923
|
}
|
|
3924
|
+
// Breakpoint layers — AFTER the state loop, so every scope resolved above is recorded.
|
|
3925
|
+
this.styleRegistry.upsertResponsive(cssId, initialStyle, node.stateStyles, node.responsive);
|
|
3794
3926
|
}
|
|
3795
3927
|
// Set nodeId — declared as @Input() on every builder component.
|
|
3796
3928
|
if (cssId) {
|
|
@@ -3907,10 +4039,10 @@ class RenderDirective {
|
|
|
3907
4039
|
this.interactionEngine.attachTo(node, nativeEl);
|
|
3908
4040
|
}
|
|
3909
4041
|
}
|
|
3910
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3911
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
4042
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: RenderDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.Injector }, { token: i0.EnvironmentInjector }, { token: DOCUMENT }, { token: ComponentRegistryService }, { token: OverlayService }, { token: StyleRegistryService }, { token: InteractionEngineService }, { token: i0.ChangeDetectorRef }, { token: PanelEventService }, { token: DragEngineService }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4043
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.31", type: RenderDirective, isStandalone: false, selector: "[ioxRender]", inputs: { ioxRender: "ioxRender", ioxDragSourceId: "ioxDragSourceId" }, outputs: { onClick: "onClick", onMouseEnter: "onMouseEnter", onMouseLeave: "onMouseLeave" }, ngImport: i0 }); }
|
|
3912
4044
|
}
|
|
3913
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4045
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: RenderDirective, decorators: [{
|
|
3914
4046
|
type: Directive,
|
|
3915
4047
|
args: [{
|
|
3916
4048
|
selector: '[ioxRender]',
|
|
@@ -3976,10 +4108,10 @@ class PresetRegistryService {
|
|
|
3976
4108
|
return { ...overrides };
|
|
3977
4109
|
return { ...preset.styleProps, ...overrides };
|
|
3978
4110
|
}
|
|
3979
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3980
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
4111
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PresetRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4112
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PresetRegistryService }); }
|
|
3981
4113
|
}
|
|
3982
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4114
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PresetRegistryService, decorators: [{
|
|
3983
4115
|
type: Injectable
|
|
3984
4116
|
}] });
|
|
3985
4117
|
|
|
@@ -4005,10 +4137,10 @@ class IoxDraggableDirective {
|
|
|
4005
4137
|
ngOnDestroy() {
|
|
4006
4138
|
this.dragEngine.unregisterDraggable(this.el.nativeElement);
|
|
4007
4139
|
}
|
|
4008
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4009
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
4140
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxDraggableDirective, deps: [{ token: i0.ElementRef }, { token: DragEngineService }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4141
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.31", type: IoxDraggableDirective, isStandalone: false, selector: "[ioxDraggable]", inputs: { ioxDragData: "ioxDragData", ioxDragSourceId: "ioxDragSourceId" }, ngImport: i0 }); }
|
|
4010
4142
|
}
|
|
4011
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxDraggableDirective, decorators: [{
|
|
4012
4144
|
type: Directive,
|
|
4013
4145
|
args: [{
|
|
4014
4146
|
selector: '[ioxDraggable]',
|
|
@@ -4513,10 +4645,10 @@ class OverlayComponent {
|
|
|
4513
4645
|
// is a zero-area line — prevents diagonal edge triangle artifacts.
|
|
4514
4646
|
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)`;
|
|
4515
4647
|
}
|
|
4516
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4517
|
-
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 badges container \u2014 below the outline, start-aligned -->\n <div class=\"preset-badge\" *ngIf=\"selectedPresetName || interactions.length\">\n <div *ngIf=\"selectedPresetName\"\n class=\"preset-badge__item\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'style'\"\n title=\"Style preset: {{ selectedPresetName }} \u2014 click to edit, right-click to copy\"\n (mousedown)=\"onEditPreset($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'style')\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n <div *ngFor=\"let ix of interactions\"\n class=\"preset-badge__item preset-badge__item--interaction\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'interaction'\"\n [title]=\"triggerLabel(ix.trigger) + ': ' + actionLabel(ix) + ' \u2014 click to edit, right-click to remove'\"\n (mousedown)=\"onEditInteractionPreset($event, ix)\"\n (click)=\"onBadgeClickSwallow($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'interaction', ix)\">\n <i [class]=\"triggerIcon(ix.trigger)\"></i>\n <span>{{ triggerLabel(ix.trigger) }}: {{ actionLabel(ix) }}</span>\n </div>\n </div>\n\n <div class=\"select-toolbar\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Drag handle \u2014 grab here to move the selected element. A click-and-hold ANYWHERE\n on the element body would otherwise grab whatever nested child the pointer lands\n on; DragEngineService redirects any drag starting here to the selected node. -->\n <button *ngIf=\"selectEntry?.node\" class=\"toolbar-btn toolbar-btn--drag-handle\"\n ioxDraggable data-iox-drag-handle\n [ioxDragData]=\"selectEntry?.node\"\n [ioxDragSourceId]=\"dragHandleSourceId\"\n title=\"Drag to move\">\n <i class=\"ph-thin ph-dots-six-vertical\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ selectEntry?.componentName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n <button *ngIf=\"isSliderContainer\" class=\"toolbar-btn toolbar-btn--add-slide\" title=\"Add slide\" (mousedown)=\"onAddSlide($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n <span class=\"toolbar-btn__label\">Add slide</span>\n </button>\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 *ngIf=\"isLinkedSymbol\" class=\"toolbar-btn toolbar-btn--symbol\"\n [title]=\"(linkedSymbolName ? linkedSymbolName : 'Symbol') + ' \u2014 click to detach'\"\n (mousedown)=\"onDetachSymbol($event)\">\n <i class=\"ph-thin ph-link\"></i>\n <span class=\"toolbar-btn__label\">{{ linkedSymbolName || 'Symbol' }}</span>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"toolbar-btn toolbar-btn--resync\"\n title=\"Detached \u2014 click to re-link\"\n (mousedown)=\"onResyncSymbol($event)\">\n <i class=\"ph-thin ph-link-break\"></i>\n <span class=\"toolbar-btn__label\">Detached</span>\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 <div *ngIf=\"canWrap\" class=\"more-item-submenu\"\n (mouseenter)=\"wrapSubmenuOpen = true\" (mouseleave)=\"wrapSubmenuOpen = false\">\n <button class=\"more-item\" (mousedown)=\"$event.stopPropagation()\">\n <i class=\"ph-thin ph-selection-plus\"></i>\n Wrap in\n <i class=\"ph-thin ph-caret-right more-item__chevron\"></i>\n </button>\n <div *ngIf=\"wrapSubmenuOpen\" class=\"more-submenu-flyout\">\n <button *ngFor=\"let target of wrapTargets\" class=\"more-item\"\n (mousedown)=\"onWrap($event, target.type); closeMoreMenu()\">\n <i [class]=\"target.icon\"></i>\n {{ target.label }}\n </button>\n </div>\n </div>\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)=\"onCopyNode($event)\">\n <i class=\"ph-thin ph-scissors\"></i>\n Copy element\n </button>\n <button *ngIf=\"hasCopiedNode\" class=\"more-item\" (mousedown)=\"onPasteNode($event)\">\n <i class=\"ph-thin ph-clipboard\"></i>\n Paste element\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"selectEntry?.node?.stylePresetId\" class=\"more-item\" (mousedown)=\"onCopyPreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Copy style preset\n </button>\n <button *ngIf=\"hasPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPastePreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Paste style preset\n </button>\n <button *ngIf=\"selectEntry?.node?.interactionPresetId\" class=\"more-item\" (mousedown)=\"onCopyInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Copy interaction preset\n </button>\n <button *ngIf=\"hasInteractionPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPasteInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Paste interaction preset\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"isLinkedSymbol\" class=\"more-item\" (mousedown)=\"onDetachSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link-break\"></i>\n Detach from symbol<ng-container *ngIf=\"linkedSymbolName\"> ({{ linkedSymbolName }})</ng-container>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"more-item more-item--resync\" (mousedown)=\"onResyncSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link\"></i>\n Re-link to symbol\n </button>\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 <!-- Badge context menu \u2014 options differ by badge type -->\n <div *ngIf=\"badgeMenuVisible\" class=\"badge-context-menu\"\n [ngStyle]=\"{ top: badgeMenuPos.y + 'px', left: badgeMenuPos.x + 'px' }\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <ng-container *ngIf=\"badgeMenuType === 'style'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeCopy()\">\n <i class=\"ph-thin ph-copy\"></i>\n Copy preset\n </button>\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit preset\n </button>\n </ng-container>\n <ng-container *ngIf=\"badgeMenuType === 'interaction'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit in panel\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onBadgeRemoveInteraction()\">\n <i class=\"ph-thin ph-trash\"></i>\n Remove interaction\n </button>\n </ng-container>\n </div>\n <div *ngIf=\"badgeMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeBadgeMenu()\">\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--drag-handle{cursor:grab}.select-toolbar .toolbar-btn--drag-handle:active{cursor:grabbing}.select-toolbar .toolbar-btn--symbol{width:auto;padding:0 7px;gap:4px;color:#fff;background:#f59e0b;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--symbol:hover{background:#d97706}.select-toolbar .toolbar-btn--resync{width:auto;padding:0 7px;gap:4px;color:#fff;background:#22c55e;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--resync:hover{background:#16a34a}.select-toolbar .toolbar-btn .toolbar-btn__label{font-size:11px;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.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-item--resync{color:#22c55e}.toolbar-more-dropdown .more-item--resync:hover{background:#22c55e14}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.toolbar-more-dropdown .more-item-submenu{position:relative}.toolbar-more-dropdown .more-item-submenu .more-item__chevron{margin-inline-start:auto;font-size:12px;opacity:.6}.toolbar-more-dropdown .more-item-submenu:hover>.more-item{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item-submenu .more-submenu-flyout{position:absolute;top:-4px;inset-inline-start:100%;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:180px;z-index:1001}.preset-badge{position:absolute;bottom:-26px;inset-inline-start:0;display:flex;align-items:center;gap:4px;pointer-events:none;white-space:nowrap}.preset-badge__item{display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s,outline-color .15s;outline:2px solid transparent;outline-offset:2px}.preset-badge__item i{font-size:12px}.preset-badge__item:hover{background:#be7474}.preset-badge__item--active{outline-color:#ffffffd9}.preset-badge__item--interaction{background:#7a9ecb}.preset-badge__item--interaction:hover{background:#5d89c0}.badge-context-menu{position:fixed;z-index:1001;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:160px;pointer-events:all}.badge-context-menu .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 14px;border:none;background:transparent;font-size:12px;color:#333;cursor:pointer;text-align:start;white-space:nowrap}.badge-context-menu .more-item:hover{background:var(--p-surface-50, #f9fafb)}.badge-context-menu .more-item i{font-size:13px;color:#888}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: IoxDraggableDirective, selector: "[ioxDraggable]", inputs: ["ioxDragData", "ioxDragSourceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4648
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: OverlayComponent, deps: [{ token: OverlayService }, { token: ViewportService }, { token: PresetRegistryService }, { token: SymbolRegistryService }, { token: InteractionPresetRegistryService }, { token: InteractionEngineService }, { token: BuilderClipboardService }, { token: StyleRegistryService }, { token: PanelEventService }, { token: i0.ChangeDetectorRef }, { token: DragEngineService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4649
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", 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 badges container \u2014 below the outline, start-aligned -->\n <div class=\"preset-badge\" *ngIf=\"selectedPresetName || interactions.length\">\n <div *ngIf=\"selectedPresetName\"\n class=\"preset-badge__item\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'style'\"\n title=\"Style preset: {{ selectedPresetName }} \u2014 click to edit, right-click to copy\"\n (mousedown)=\"onEditPreset($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'style')\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n <div *ngFor=\"let ix of interactions\"\n class=\"preset-badge__item preset-badge__item--interaction\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'interaction'\"\n [title]=\"triggerLabel(ix.trigger) + ': ' + actionLabel(ix) + ' \u2014 click to edit, right-click to remove'\"\n (mousedown)=\"onEditInteractionPreset($event, ix)\"\n (click)=\"onBadgeClickSwallow($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'interaction', ix)\">\n <i [class]=\"triggerIcon(ix.trigger)\"></i>\n <span>{{ triggerLabel(ix.trigger) }}: {{ actionLabel(ix) }}</span>\n </div>\n </div>\n\n <div class=\"select-toolbar\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Drag handle \u2014 grab here to move the selected element. A click-and-hold ANYWHERE\n on the element body would otherwise grab whatever nested child the pointer lands\n on; DragEngineService redirects any drag starting here to the selected node. -->\n <button *ngIf=\"selectEntry?.node\" class=\"toolbar-btn toolbar-btn--drag-handle\"\n ioxDraggable data-iox-drag-handle\n [ioxDragData]=\"selectEntry?.node\"\n [ioxDragSourceId]=\"dragHandleSourceId\"\n title=\"Drag to move\">\n <i class=\"ph-thin ph-dots-six-vertical\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ selectEntry?.componentName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n <button *ngIf=\"isSliderContainer\" class=\"toolbar-btn toolbar-btn--add-slide\" title=\"Add slide\" (mousedown)=\"onAddSlide($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n <span class=\"toolbar-btn__label\">Add slide</span>\n </button>\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 *ngIf=\"isLinkedSymbol\" class=\"toolbar-btn toolbar-btn--symbol\"\n [title]=\"(linkedSymbolName ? linkedSymbolName : 'Symbol') + ' \u2014 click to detach'\"\n (mousedown)=\"onDetachSymbol($event)\">\n <i class=\"ph-thin ph-link\"></i>\n <span class=\"toolbar-btn__label\">{{ linkedSymbolName || 'Symbol' }}</span>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"toolbar-btn toolbar-btn--resync\"\n title=\"Detached \u2014 click to re-link\"\n (mousedown)=\"onResyncSymbol($event)\">\n <i class=\"ph-thin ph-link-break\"></i>\n <span class=\"toolbar-btn__label\">Detached</span>\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 <div *ngIf=\"canWrap\" class=\"more-item-submenu\"\n (mouseenter)=\"wrapSubmenuOpen = true\" (mouseleave)=\"wrapSubmenuOpen = false\">\n <button class=\"more-item\" (mousedown)=\"$event.stopPropagation()\">\n <i class=\"ph-thin ph-selection-plus\"></i>\n Wrap in\n <i class=\"ph-thin ph-caret-right more-item__chevron\"></i>\n </button>\n <div *ngIf=\"wrapSubmenuOpen\" class=\"more-submenu-flyout\">\n <button *ngFor=\"let target of wrapTargets\" class=\"more-item\"\n (mousedown)=\"onWrap($event, target.type); closeMoreMenu()\">\n <i [class]=\"target.icon\"></i>\n {{ target.label }}\n </button>\n </div>\n </div>\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)=\"onCopyNode($event)\">\n <i class=\"ph-thin ph-scissors\"></i>\n Copy element\n </button>\n <button *ngIf=\"hasCopiedNode\" class=\"more-item\" (mousedown)=\"onPasteNode($event)\">\n <i class=\"ph-thin ph-clipboard\"></i>\n Paste element\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"selectEntry?.node?.stylePresetId\" class=\"more-item\" (mousedown)=\"onCopyPreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Copy style preset\n </button>\n <button *ngIf=\"hasPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPastePreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Paste style preset\n </button>\n <button *ngIf=\"selectEntry?.node?.interactionPresetId\" class=\"more-item\" (mousedown)=\"onCopyInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Copy interaction preset\n </button>\n <button *ngIf=\"hasInteractionPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPasteInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Paste interaction preset\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"isLinkedSymbol\" class=\"more-item\" (mousedown)=\"onDetachSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link-break\"></i>\n Detach from symbol<ng-container *ngIf=\"linkedSymbolName\"> ({{ linkedSymbolName }})</ng-container>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"more-item more-item--resync\" (mousedown)=\"onResyncSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link\"></i>\n Re-link to symbol\n </button>\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 <!-- Badge context menu \u2014 options differ by badge type -->\n <div *ngIf=\"badgeMenuVisible\" class=\"badge-context-menu\"\n [ngStyle]=\"{ top: badgeMenuPos.y + 'px', left: badgeMenuPos.x + 'px' }\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <ng-container *ngIf=\"badgeMenuType === 'style'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeCopy()\">\n <i class=\"ph-thin ph-copy\"></i>\n Copy preset\n </button>\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit preset\n </button>\n </ng-container>\n <ng-container *ngIf=\"badgeMenuType === 'interaction'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit in panel\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onBadgeRemoveInteraction()\">\n <i class=\"ph-thin ph-trash\"></i>\n Remove interaction\n </button>\n </ng-container>\n </div>\n <div *ngIf=\"badgeMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeBadgeMenu()\">\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--drag-handle{cursor:grab}.select-toolbar .toolbar-btn--drag-handle:active{cursor:grabbing}.select-toolbar .toolbar-btn--symbol{width:auto;padding:0 7px;gap:4px;color:#fff;background:#f59e0b;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--symbol:hover{background:#d97706}.select-toolbar .toolbar-btn--resync{width:auto;padding:0 7px;gap:4px;color:#fff;background:#22c55e;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--resync:hover{background:#16a34a}.select-toolbar .toolbar-btn .toolbar-btn__label{font-size:11px;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.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-item--resync{color:#22c55e}.toolbar-more-dropdown .more-item--resync:hover{background:#22c55e14}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.toolbar-more-dropdown .more-item-submenu{position:relative}.toolbar-more-dropdown .more-item-submenu .more-item__chevron{margin-inline-start:auto;font-size:12px;opacity:.6}.toolbar-more-dropdown .more-item-submenu:hover>.more-item{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item-submenu .more-submenu-flyout{position:absolute;top:-4px;inset-inline-start:100%;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:180px;z-index:1001}.preset-badge{position:absolute;bottom:-26px;inset-inline-start:0;display:flex;align-items:center;gap:4px;pointer-events:none;white-space:nowrap}.preset-badge__item{display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s,outline-color .15s;outline:2px solid transparent;outline-offset:2px}.preset-badge__item i{font-size:12px}.preset-badge__item:hover{background:#be7474}.preset-badge__item--active{outline-color:#ffffffd9}.preset-badge__item--interaction{background:#7a9ecb}.preset-badge__item--interaction:hover{background:#5d89c0}.badge-context-menu{position:fixed;z-index:1001;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:160px;pointer-events:all}.badge-context-menu .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 14px;border:none;background:transparent;font-size:12px;color:#333;cursor:pointer;text-align:start;white-space:nowrap}.badge-context-menu .more-item:hover{background:var(--p-surface-50, #f9fafb)}.badge-context-menu .more-item i{font-size:13px;color:#888}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: IoxDraggableDirective, selector: "[ioxDraggable]", inputs: ["ioxDragData", "ioxDragSourceId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4518
4650
|
}
|
|
4519
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4651
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: OverlayComponent, decorators: [{
|
|
4520
4652
|
type: Component,
|
|
4521
4653
|
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 badges container \u2014 below the outline, start-aligned -->\n <div class=\"preset-badge\" *ngIf=\"selectedPresetName || interactions.length\">\n <div *ngIf=\"selectedPresetName\"\n class=\"preset-badge__item\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'style'\"\n title=\"Style preset: {{ selectedPresetName }} \u2014 click to edit, right-click to copy\"\n (mousedown)=\"onEditPreset($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'style')\">\n <i class=\"ph-fill ph-paint-bucket\"></i>\n <span>{{ selectedPresetName }}</span>\n </div>\n <div *ngFor=\"let ix of interactions\"\n class=\"preset-badge__item preset-badge__item--interaction\"\n [class.preset-badge__item--active]=\"activeBadgeType === 'interaction'\"\n [title]=\"triggerLabel(ix.trigger) + ': ' + actionLabel(ix) + ' \u2014 click to edit, right-click to remove'\"\n (mousedown)=\"onEditInteractionPreset($event, ix)\"\n (click)=\"onBadgeClickSwallow($event)\"\n (contextmenu)=\"onBadgeContextMenu($event, 'interaction', ix)\">\n <i [class]=\"triggerIcon(ix.trigger)\"></i>\n <span>{{ triggerLabel(ix.trigger) }}: {{ actionLabel(ix) }}</span>\n </div>\n </div>\n\n <div class=\"select-toolbar\" (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n\n <!-- Drag handle \u2014 grab here to move the selected element. A click-and-hold ANYWHERE\n on the element body would otherwise grab whatever nested child the pointer lands\n on; DragEngineService redirects any drag starting here to the selected node. -->\n <button *ngIf=\"selectEntry?.node\" class=\"toolbar-btn toolbar-btn--drag-handle\"\n ioxDraggable data-iox-drag-handle\n [ioxDragData]=\"selectEntry?.node\"\n [ioxDragSourceId]=\"dragHandleSourceId\"\n title=\"Drag to move\">\n <i class=\"ph-thin ph-dots-six-vertical\"></i>\n </button>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Component name -->\n <span class=\"toolbar-name\">{{ selectEntry?.componentName }}</span>\n <span class=\"toolbar-sep\"></span>\n\n <!-- Quick actions -->\n <button *ngIf=\"isSliderContainer\" class=\"toolbar-btn toolbar-btn--add-slide\" title=\"Add slide\" (mousedown)=\"onAddSlide($event)\">\n <i class=\"ph-thin ph-plus\"></i>\n <span class=\"toolbar-btn__label\">Add slide</span>\n </button>\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 *ngIf=\"isLinkedSymbol\" class=\"toolbar-btn toolbar-btn--symbol\"\n [title]=\"(linkedSymbolName ? linkedSymbolName : 'Symbol') + ' \u2014 click to detach'\"\n (mousedown)=\"onDetachSymbol($event)\">\n <i class=\"ph-thin ph-link\"></i>\n <span class=\"toolbar-btn__label\">{{ linkedSymbolName || 'Symbol' }}</span>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"toolbar-btn toolbar-btn--resync\"\n title=\"Detached \u2014 click to re-link\"\n (mousedown)=\"onResyncSymbol($event)\">\n <i class=\"ph-thin ph-link-break\"></i>\n <span class=\"toolbar-btn__label\">Detached</span>\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 <div *ngIf=\"canWrap\" class=\"more-item-submenu\"\n (mouseenter)=\"wrapSubmenuOpen = true\" (mouseleave)=\"wrapSubmenuOpen = false\">\n <button class=\"more-item\" (mousedown)=\"$event.stopPropagation()\">\n <i class=\"ph-thin ph-selection-plus\"></i>\n Wrap in\n <i class=\"ph-thin ph-caret-right more-item__chevron\"></i>\n </button>\n <div *ngIf=\"wrapSubmenuOpen\" class=\"more-submenu-flyout\">\n <button *ngFor=\"let target of wrapTargets\" class=\"more-item\"\n (mousedown)=\"onWrap($event, target.type); closeMoreMenu()\">\n <i [class]=\"target.icon\"></i>\n {{ target.label }}\n </button>\n </div>\n </div>\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)=\"onCopyNode($event)\">\n <i class=\"ph-thin ph-scissors\"></i>\n Copy element\n </button>\n <button *ngIf=\"hasCopiedNode\" class=\"more-item\" (mousedown)=\"onPasteNode($event)\">\n <i class=\"ph-thin ph-clipboard\"></i>\n Paste element\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"selectEntry?.node?.stylePresetId\" class=\"more-item\" (mousedown)=\"onCopyPreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Copy style preset\n </button>\n <button *ngIf=\"hasPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPastePreset($event)\">\n <i class=\"ph-thin ph-paint-bucket\"></i>\n Paste style preset\n </button>\n <button *ngIf=\"selectEntry?.node?.interactionPresetId\" class=\"more-item\" (mousedown)=\"onCopyInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Copy interaction preset\n </button>\n <button *ngIf=\"hasInteractionPresetInClipboard\" class=\"more-item\" (mousedown)=\"onPasteInteractionPreset($event)\">\n <i class=\"ph-thin ph-lightning\"></i>\n Paste interaction preset\n </button>\n <div class=\"more-divider\"></div>\n <button *ngIf=\"isLinkedSymbol\" class=\"more-item\" (mousedown)=\"onDetachSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link-break\"></i>\n Detach from symbol<ng-container *ngIf=\"linkedSymbolName\"> ({{ linkedSymbolName }})</ng-container>\n </button>\n <button *ngIf=\"isDetachedSymbol\" class=\"more-item more-item--resync\" (mousedown)=\"onResyncSymbol($event); closeMoreMenu()\">\n <i class=\"ph-thin ph-link\"></i>\n Re-link to symbol\n </button>\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 <!-- Badge context menu \u2014 options differ by badge type -->\n <div *ngIf=\"badgeMenuVisible\" class=\"badge-context-menu\"\n [ngStyle]=\"{ top: badgeMenuPos.y + 'px', left: badgeMenuPos.x + 'px' }\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <ng-container *ngIf=\"badgeMenuType === 'style'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeCopy()\">\n <i class=\"ph-thin ph-copy\"></i>\n Copy preset\n </button>\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit preset\n </button>\n </ng-container>\n <ng-container *ngIf=\"badgeMenuType === 'interaction'\">\n <button class=\"more-item\" (mousedown)=\"onBadgeEdit()\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n Edit in panel\n </button>\n <button class=\"more-item more-item--danger\" (mousedown)=\"onBadgeRemoveInteraction()\">\n <i class=\"ph-thin ph-trash\"></i>\n Remove interaction\n </button>\n </ng-container>\n </div>\n <div *ngIf=\"badgeMenuVisible\" class=\"overlay-context-backdrop\"\n (mousedown)=\"closeBadgeMenu()\">\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--drag-handle{cursor:grab}.select-toolbar .toolbar-btn--drag-handle:active{cursor:grabbing}.select-toolbar .toolbar-btn--symbol{width:auto;padding:0 7px;gap:4px;color:#fff;background:#f59e0b;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--symbol:hover{background:#d97706}.select-toolbar .toolbar-btn--resync{width:auto;padding:0 7px;gap:4px;color:#fff;background:#22c55e;border-radius:3px;font-size:11px}.select-toolbar .toolbar-btn--resync:hover{background:#16a34a}.select-toolbar .toolbar-btn .toolbar-btn__label{font-size:11px;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.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-item--resync{color:#22c55e}.toolbar-more-dropdown .more-item--resync:hover{background:#22c55e14}.toolbar-more-dropdown .more-divider{height:1px;background:var(--p-surface-200, #e5e7eb);margin:4px 0}.toolbar-more-dropdown .more-item-submenu{position:relative}.toolbar-more-dropdown .more-item-submenu .more-item__chevron{margin-inline-start:auto;font-size:12px;opacity:.6}.toolbar-more-dropdown .more-item-submenu:hover>.more-item{background:var(--p-surface-100, #f5f5f5)}.toolbar-more-dropdown .more-item-submenu .more-submenu-flyout{position:absolute;top:-4px;inset-inline-start:100%;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:180px;z-index:1001}.preset-badge{position:absolute;bottom:-26px;inset-inline-start:0;display:flex;align-items:center;gap:4px;pointer-events:none;white-space:nowrap}.preset-badge__item{display:flex;align-items:center;gap:5px;padding:3px 9px;background:#cb9090;color:#fff;font-size:11px;font-weight:500;border-radius:20px;pointer-events:all;cursor:pointer;box-shadow:0 2px 6px #0000002e;transition:background .15s,outline-color .15s;outline:2px solid transparent;outline-offset:2px}.preset-badge__item i{font-size:12px}.preset-badge__item:hover{background:#be7474}.preset-badge__item--active{outline-color:#ffffffd9}.preset-badge__item--interaction{background:#7a9ecb}.preset-badge__item--interaction:hover{background:#5d89c0}.badge-context-menu{position:fixed;z-index:1001;background:#fff;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:6px;box-shadow:0 4px 16px #0000001f;padding:4px 0;min-width:160px;pointer-events:all}.badge-context-menu .more-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 14px;border:none;background:transparent;font-size:12px;color:#333;cursor:pointer;text-align:start;white-space:nowrap}.badge-context-menu .more-item:hover{background:var(--p-surface-50, #f9fafb)}.badge-context-menu .more-item i{font-size:13px;color:#888}.overlay-context-backdrop{position:fixed;inset:0;z-index:998;pointer-events:all}\n"] }]
|
|
4522
4654
|
}], ctorParameters: () => [{ type: OverlayService }, { type: ViewportService }, { type: PresetRegistryService }, { type: SymbolRegistryService }, { type: InteractionPresetRegistryService }, { type: InteractionEngineService }, { type: BuilderClipboardService }, { type: StyleRegistryService }, { type: PanelEventService }, { type: i0.ChangeDetectorRef }, { type: DragEngineService }], propDecorators: { toolbarAction: [{
|
|
@@ -4526,7 +4658,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
4526
4658
|
class ToolbarComponent {
|
|
4527
4659
|
constructor() {
|
|
4528
4660
|
this.activeMode = BuilderMode.Select;
|
|
4529
|
-
this.
|
|
4661
|
+
this.activeBreakpoint = Breakpoint.Base;
|
|
4662
|
+
/** Overrides per breakpoint — for the selection, or the page when nothing is selected. */
|
|
4663
|
+
this.breakpointCounts = {};
|
|
4530
4664
|
this.activeZoom = 100;
|
|
4531
4665
|
this.activeScreenWidth = 1440;
|
|
4532
4666
|
this.canUndo = false;
|
|
@@ -4534,7 +4668,7 @@ class ToolbarComponent {
|
|
|
4534
4668
|
this.isSaving = false;
|
|
4535
4669
|
this.pageStatus = 'draft';
|
|
4536
4670
|
this.modeChange = new EventEmitter();
|
|
4537
|
-
this.
|
|
4671
|
+
this.breakpointChange = new EventEmitter();
|
|
4538
4672
|
this.zoomChange = new EventEmitter();
|
|
4539
4673
|
this.screenWidthChange = new EventEmitter();
|
|
4540
4674
|
this.undo = new EventEmitter();
|
|
@@ -4543,8 +4677,14 @@ class ToolbarComponent {
|
|
|
4543
4677
|
this.preview = new EventEmitter();
|
|
4544
4678
|
this.publishToggle = new EventEmitter();
|
|
4545
4679
|
this.modes = BuilderMode;
|
|
4546
|
-
this.
|
|
4547
|
-
|
|
4680
|
+
this.breakpointIds = Breakpoint;
|
|
4681
|
+
/** Built once — the breakpoint set is fixed. Template binds fields, never method calls. */
|
|
4682
|
+
this.breakpointOptions = BREAKPOINTS.map(def => ({
|
|
4683
|
+
id: def.id,
|
|
4684
|
+
label: def.label,
|
|
4685
|
+
range: def.maxWidth === null ? 'default' : `≤ ${def.maxWidth}px`,
|
|
4686
|
+
...BREAKPOINT_PRESENTATION[def.id],
|
|
4687
|
+
}));
|
|
4548
4688
|
this.zoomOptions = ZOOM_OPTIONS;
|
|
4549
4689
|
this.screenWidthOptions = SCREEN_WIDTH_OPTIONS;
|
|
4550
4690
|
}
|
|
@@ -4567,9 +4707,6 @@ class ToolbarComponent {
|
|
|
4567
4707
|
default: return 'Select';
|
|
4568
4708
|
}
|
|
4569
4709
|
}
|
|
4570
|
-
get activeDeviceOption() {
|
|
4571
|
-
return this.deviceOptions.find(d => d.mode === this.activeDevice) || this.deviceOptions[0];
|
|
4572
|
-
}
|
|
4573
4710
|
get zoomLabel() {
|
|
4574
4711
|
return `${this.activeZoom}%`;
|
|
4575
4712
|
}
|
|
@@ -4586,15 +4723,10 @@ class ToolbarComponent {
|
|
|
4586
4723
|
}
|
|
4587
4724
|
this.modePopover.hide();
|
|
4588
4725
|
}
|
|
4589
|
-
// ──
|
|
4590
|
-
|
|
4591
|
-
this.
|
|
4592
|
-
|
|
4593
|
-
selectDevice(mode) {
|
|
4594
|
-
if (this.activeDevice !== mode) {
|
|
4595
|
-
this.deviceChange.emit(mode);
|
|
4596
|
-
}
|
|
4597
|
-
this.devicePopover.hide();
|
|
4726
|
+
// ── Breakpoint ──────────────────────────────────────────
|
|
4727
|
+
selectBreakpoint(bp) {
|
|
4728
|
+
if (this.activeBreakpoint !== bp)
|
|
4729
|
+
this.breakpointChange.emit(bp);
|
|
4598
4730
|
}
|
|
4599
4731
|
// ── Zoom slider ──────────────────────────────────────────
|
|
4600
4732
|
onSliderChange(event) {
|
|
@@ -4619,15 +4751,17 @@ class ToolbarComponent {
|
|
|
4619
4751
|
this.zoomChange.emit(value);
|
|
4620
4752
|
this.zoomPopover.hide();
|
|
4621
4753
|
}
|
|
4622
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4623
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: ToolbarComponent, isStandalone: false, selector: "app-toolbar", inputs: { activeMode: "activeMode", activeDevice: "activeDevice", activeZoom: "activeZoom", activeScreenWidth: "activeScreenWidth", canUndo: "canUndo", canRedo: "canRedo", isSaving: "isSaving", pageStatus: "pageStatus" }, outputs: { modeChange: "modeChange", deviceChange: "deviceChange", zoomChange: "zoomChange", screenWidthChange: "screenWidthChange", undo: "undo", redo: "redo", save: "save", preview: "preview", publishToggle: "publishToggle" }, viewQueries: [{ propertyName: "modePopover", first: true, predicate: ["modePopover"], descendants: true }, { propertyName: "devicePopover", first: true, predicate: ["devicePopover"], descendants: true }, { propertyName: "zoomPopover", first: true, predicate: ["zoomPopover"], descendants: true }, { propertyName: "widthPopover", first: true, predicate: ["widthPopover"], descendants: true }], ngImport: i0, template: "<div class=\"builder-toolbar\">\n <!-- \u2500\u2500 Mode switcher (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful\"\n (click)=\"toggleModePopover($event)\"\n [title]=\"activeModeLabel\">\n <i [class]=\"activeModeIcon\"></i>\n </button>\n\n <p-popover #modePopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Select\"\n (click)=\"selectMode(modes.Select)\">\n <i class=\"ph-thin ph-cursor\"></i>\n <span>Select</span>\n </button>\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Pan\"\n (click)=\"selectMode(modes.Pan)\">\n <i class=\"ph-thin ph-hand\"></i>\n <span>Pan</span>\n </button>\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Style\"\n (click)=\"selectMode(modes.Style)\">\n <i class=\"ph-thin ph-paint-brush-broad\"></i>\n <span>Style</span>\n </button>\n </div>\n </p-popover>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Undo / Redo (action) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn\" title=\"Undo\" [disabled]=\"!canUndo\" (click)=\"undo.emit()\">\n <i class=\"ph-thin ph-arrow-counter-clockwise\"></i>\n </button>\n <button class=\"tool-btn\" title=\"Redo\" [disabled]=\"!canRedo\" (click)=\"redo.emit()\">\n <i class=\"ph-thin ph-arrow-clockwise\"></i>\n </button>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Device switcher (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful\"\n (click)=\"toggleDevicePopover($event)\"\n [title]=\"activeDeviceOption.label\">\n <i [class]=\"activeDeviceOption.icon\"></i>\n </button>\n\n <p-popover #devicePopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let d of deviceOptions\"\n [class.is-active]=\"activeDevice === d.mode\"\n (click)=\"selectDevice(d.mode)\">\n <i [class]=\"d.icon\"></i>\n <span>{{ d.label }}</span>\n </button>\n </div>\n </p-popover>\n\n <!-- \u2500\u2500 Screen width \u2014 Desktop only \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeDevice === deviceModes.Desktop) {\n <button class=\"tool-btn stateful width-btn\"\n (click)=\"toggleWidthPopover($event)\"\n title=\"Screen width\">\n <span class=\"width-label\">{{ activeScreenWidth }}</span>\n </button>\n }\n\n <p-popover #widthPopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let w of screenWidthOptions\"\n [class.is-active]=\"activeScreenWidth === w.width\"\n (click)=\"selectScreenWidth(w.width)\">\n <span>{{ w.label }}</span>\n </button>\n </div>\n </p-popover>\n\n <!-- \u2500\u2500 Zoom (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful zoom-btn\"\n (click)=\"toggleZoomPopover($event)\"\n title=\"Zoom\">\n <span class=\"zoom-label\">{{ zoomLabel }}</span>\n </button>\n\n <p-popover #zoomPopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"zoom-popover\">\n <div class=\"zoom-slider-row\">\n <input class=\"zoom-slider\"\n type=\"range\"\n min=\"20\" max=\"100\" step=\"1\"\n [value]=\"sliderZoom\"\n (input)=\"onSliderChange($event)\">\n <span class=\"zoom-slider-value\">{{ zoomLabel }}</span>\n </div>\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let z of zoomOptions\"\n [class.is-active]=\"z.value === activeZoom\"\n (click)=\"selectZoom(z.value)\">\n <span>{{ z.label }}</span>\n </button>\n </div>\n </div>\n </p-popover>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn save-btn\"\n [class.is-saving]=\"isSaving\"\n [disabled]=\"isSaving\"\n title=\"Save\"\n (click)=\"save.emit()\">\n <i class=\"ph-thin ph-floppy-disk\"></i>\n </button>\n\n <!-- \u2500\u2500 Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn preview-btn\"\n title=\"Preview\"\n (click)=\"preview.emit()\">\n <i class=\"ph-thin ph-eye\"></i>\n </button>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Publish / Unpublish \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn publish-btn\"\n [class.is-published]=\"isPublished\"\n [title]=\"isPublished ? 'Unpublish' : 'Publish'\"\n (click)=\"publishToggle.emit()\">\n <i [class]=\"isPublished ? 'ph-thin ph-cloud-slash' : 'ph-thin ph-cloud-arrow-up'\"></i>\n <span class=\"publish-label\">{{ isPublished ? 'Unpublish' : 'Publish' }}</span>\n </button>\n</div>\n", styles: [".builder-toolbar{display:flex;align-items:center;gap:.125rem}.divider{width:1px;height:1.25rem;background:var(--p-surface-200);margin:0 .375rem;flex-shrink:0}.tool-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.tool-btn:hover:not(:disabled){background:var(--p-surface-50);color:var(--p-text-color)}.tool-btn:disabled{opacity:.35;cursor:default}.tool-btn.stateful{position:relative}.tool-btn.stateful:after{content:\"\";position:absolute;inset-block-end:3px;width:4px;height:4px;border-radius:50%;background:#cb9090}.zoom-btn{width:auto;border-radius:999px;padding:0 .5rem;min-width:2.5rem}.zoom-btn .zoom-label{font-size:.7rem;font-weight:500;letter-spacing:.02em}.width-btn{width:auto;border-radius:999px;padding:0 .5rem;min-width:2.8rem}.width-btn .width-label{font-size:.7rem;font-weight:500;letter-spacing:.02em}.save-btn{background:#cb9090;color:#fff}.save-btn:hover:not(:disabled){background:#b37373;color:#fff}.save-btn.is-saving{opacity:.7}.preview-btn{border:1px solid var(--p-surface-200)}.preview-btn:hover:not(:disabled){background:var(--p-surface-50);color:var(--p-text-color);border-color:var(--p-surface-100)}.publish-btn{width:auto;border-radius:999px;padding:0 .65rem;gap:.35rem;font-size:.75rem;font-weight:500;background:#22c55e;color:#fff;border:none}.publish-btn .publish-label{font-size:.72rem;letter-spacing:.02em}.publish-btn:hover:not(:disabled){background:color-mix(in srgb,#22c55e 85%,#000);color:#fff}.publish-btn.is-published{background:transparent;color:var(--p-text-muted-color);border:1px solid var(--p-surface-200)}.publish-btn.is-published:hover:not(:disabled){background:color-mix(in srgb,#ef4444 10%,transparent);color:#ef4444;border-color:color-mix(in srgb,#ef4444 40%,transparent)}::ng-deep .toolbar-popover .p-popover-content{padding:.25rem!important;background:var(--p-surface-0)!important;border:1px solid var(--p-surface-200)!important;border-radius:10px!important;box-shadow:0 4px 16px #0f172a1a!important}.popover-strip{display:flex;flex-direction:column;gap:2px;min-width:120px}.popover-option{display:flex;align-items:center;gap:.5rem;width:100%;padding:.4rem .65rem;border:none;background:transparent;color:var(--p-text-color);cursor:pointer;font-size:.8rem;border-radius:6px;transition:background .12s ease-out,color .12s ease-out;white-space:nowrap}.popover-option i{font-size:1rem;color:var(--p-text-muted-color)}.popover-option:hover{background:var(--p-surface-50)}.popover-option.is-active{background:#cb9090;color:#fff}.popover-option.is-active i{color:#fff}::ng-deep .toolbar-popover .zoom-popover{display:flex;flex-direction:column;gap:4px;padding:.15rem 0}::ng-deep .toolbar-popover .zoom-slider-row{display:flex;align-items:center;gap:.5rem;padding:.3rem .65rem .1rem}::ng-deep .toolbar-popover .zoom-slider{flex:1;-webkit-appearance:none;appearance:none;height:3px;border-radius:999px;background:var(--p-surface-200);outline:none;cursor:pointer}::ng-deep .toolbar-popover .zoom-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:14px;height:14px;border-radius:50%;background:#cb9090;cursor:pointer;transition:transform .12s ease-out}::ng-deep .toolbar-popover .zoom-slider::-webkit-slider-thumb:hover{transform:scale(1.2)}::ng-deep .toolbar-popover .zoom-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;border:none;background:#cb9090;cursor:pointer}::ng-deep .toolbar-popover .zoom-slider-value{font-size:.68rem;font-weight:500;color:var(--p-text-muted-color);min-width:2.4rem;text-align:end;letter-spacing:.02em}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i2$1.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }] }); }
|
|
4754
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: ToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4755
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: ToolbarComponent, isStandalone: false, selector: "app-toolbar", inputs: { activeMode: "activeMode", activeBreakpoint: "activeBreakpoint", breakpointCounts: "breakpointCounts", activeZoom: "activeZoom", activeScreenWidth: "activeScreenWidth", canUndo: "canUndo", canRedo: "canRedo", isSaving: "isSaving", pageStatus: "pageStatus" }, outputs: { modeChange: "modeChange", breakpointChange: "breakpointChange", zoomChange: "zoomChange", screenWidthChange: "screenWidthChange", undo: "undo", redo: "redo", save: "save", preview: "preview", publishToggle: "publishToggle" }, viewQueries: [{ propertyName: "modePopover", first: true, predicate: ["modePopover"], descendants: true }, { propertyName: "zoomPopover", first: true, predicate: ["zoomPopover"], descendants: true }, { propertyName: "widthPopover", first: true, predicate: ["widthPopover"], descendants: true }], ngImport: i0, template: "<div class=\"builder-toolbar\">\n <!-- \u2500\u2500 Mode switcher (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful\"\n (click)=\"toggleModePopover($event)\"\n [title]=\"activeModeLabel\">\n <i [class]=\"activeModeIcon\"></i>\n </button>\n\n <p-popover #modePopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Select\"\n (click)=\"selectMode(modes.Select)\">\n <i class=\"ph-thin ph-cursor\"></i>\n <span>Select</span>\n </button>\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Pan\"\n (click)=\"selectMode(modes.Pan)\">\n <i class=\"ph-thin ph-hand\"></i>\n <span>Pan</span>\n </button>\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Style\"\n (click)=\"selectMode(modes.Style)\">\n <i class=\"ph-thin ph-paint-brush-broad\"></i>\n <span>Style</span>\n </button>\n </div>\n </p-popover>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Undo / Redo (action) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn\" title=\"Undo\" [disabled]=\"!canUndo\" (click)=\"undo.emit()\">\n <i class=\"ph-thin ph-arrow-counter-clockwise\"></i>\n </button>\n <button class=\"tool-btn\" title=\"Redo\" [disabled]=\"!canRedo\" (click)=\"redo.emit()\">\n <i class=\"ph-thin ph-arrow-clockwise\"></i>\n </button>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Breakpoint bar \u2014 the EDITING SCOPE, not just a preview size \u2500\u2500 -->\n <div class=\"breakpoint-bar\" role=\"group\" aria-label=\"Breakpoint\">\n @for (bp of breakpointOptions; track bp.id) {\n <button type=\"button\"\n class=\"bp-btn\"\n [class.is-active]=\"activeBreakpoint === bp.id\"\n [attr.aria-pressed]=\"activeBreakpoint === bp.id\"\n [title]=\"bp.label + ' \u00B7 ' + bp.range\"\n [attr.aria-label]=\"bp.label\"\n (click)=\"selectBreakpoint(bp.id)\">\n <i [class]=\"bp.icon\" [class.bp-icon--landscape]=\"bp.landscape\" aria-hidden=\"true\"></i>\n @if (breakpointCounts[bp.id]) {\n <span class=\"bp-dot\" aria-hidden=\"true\"></span>\n }\n </button>\n }\n </div>\n\n <!-- \u2500\u2500 Screen width \u2014 Base only (any width above Laptop) \u2500\u2500 -->\n @if (activeBreakpoint === breakpointIds.Base) {\n <button class=\"tool-btn stateful width-btn\"\n (click)=\"toggleWidthPopover($event)\"\n title=\"Screen width\">\n <span class=\"width-label\">{{ activeScreenWidth }}</span>\n </button>\n }\n\n <p-popover #widthPopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let w of screenWidthOptions\"\n [class.is-active]=\"activeScreenWidth === w.width\"\n (click)=\"selectScreenWidth(w.width)\">\n <span>{{ w.label }}</span>\n </button>\n </div>\n </p-popover>\n\n <!-- \u2500\u2500 Zoom (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful zoom-btn\"\n (click)=\"toggleZoomPopover($event)\"\n title=\"Zoom\">\n <span class=\"zoom-label\">{{ zoomLabel }}</span>\n </button>\n\n <p-popover #zoomPopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"zoom-popover\">\n <div class=\"zoom-slider-row\">\n <input class=\"zoom-slider\"\n type=\"range\"\n min=\"20\" max=\"100\" step=\"1\"\n [value]=\"sliderZoom\"\n (input)=\"onSliderChange($event)\">\n <span class=\"zoom-slider-value\">{{ zoomLabel }}</span>\n </div>\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let z of zoomOptions\"\n [class.is-active]=\"z.value === activeZoom\"\n (click)=\"selectZoom(z.value)\">\n <span>{{ z.label }}</span>\n </button>\n </div>\n </div>\n </p-popover>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn save-btn\"\n [class.is-saving]=\"isSaving\"\n [disabled]=\"isSaving\"\n title=\"Save\"\n (click)=\"save.emit()\">\n <i class=\"ph-thin ph-floppy-disk\"></i>\n </button>\n\n <!-- \u2500\u2500 Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn preview-btn\"\n title=\"Preview\"\n (click)=\"preview.emit()\">\n <i class=\"ph-thin ph-eye\"></i>\n </button>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Publish / Unpublish \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn publish-btn\"\n [class.is-published]=\"isPublished\"\n [title]=\"isPublished ? 'Unpublish' : 'Publish'\"\n (click)=\"publishToggle.emit()\">\n <i [class]=\"isPublished ? 'ph-thin ph-cloud-slash' : 'ph-thin ph-cloud-arrow-up'\"></i>\n <span class=\"publish-label\">{{ isPublished ? 'Unpublish' : 'Publish' }}</span>\n </button>\n</div>\n", styles: [".builder-toolbar{display:flex;align-items:center;gap:.125rem}.divider{width:1px;height:1.25rem;background:var(--p-surface-200);margin:0 .375rem;flex-shrink:0}.tool-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.tool-btn:hover:not(:disabled){background:var(--p-surface-50);color:var(--p-text-color)}.tool-btn:disabled{opacity:.35;cursor:default}.tool-btn.stateful{position:relative}.tool-btn.stateful:after{content:\"\";position:absolute;inset-block-end:3px;width:4px;height:4px;border-radius:50%;background:#cb9090}.breakpoint-bar{display:flex;align-items:center;gap:1px;padding:2px;border-radius:8px;background:var(--p-surface-100)}.bp-btn{position:relative;display:flex;align-items:center;justify-content:center;width:1.875rem;height:1.75rem;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--p-text-muted-color);font-size:.95rem;cursor:pointer;transition:background .15s ease-out,color .15s ease-out,border-color .15s ease-out}.bp-btn:hover{background:var(--p-surface-0);color:var(--p-text-color)}.bp-btn:focus-visible{outline:2px solid #cb9090;outline-offset:1px}.bp-btn.is-active{background:var(--p-surface-0);border-color:#cb9090;color:#a05c5c}.bp-icon--landscape{transform:rotate(90deg)}.bp-dot{position:absolute;inset-block-start:3px;inset-inline-end:3px;width:5px;height:5px;border-radius:50%;background:#d9924e}.zoom-btn{width:auto;border-radius:999px;padding:0 .5rem;min-width:2.5rem}.zoom-btn .zoom-label{font-size:.7rem;font-weight:500;letter-spacing:.02em}.width-btn{width:auto;border-radius:999px;padding:0 .5rem;min-width:2.8rem}.width-btn .width-label{font-size:.7rem;font-weight:500;letter-spacing:.02em}.save-btn{background:#cb9090;color:#fff}.save-btn:hover:not(:disabled){background:#b37373;color:#fff}.save-btn.is-saving{opacity:.7}.preview-btn{border:1px solid var(--p-surface-200)}.preview-btn:hover:not(:disabled){background:var(--p-surface-50);color:var(--p-text-color);border-color:var(--p-surface-100)}.publish-btn{width:auto;border-radius:999px;padding:0 .65rem;gap:.35rem;font-size:.75rem;font-weight:500;background:#22c55e;color:#fff;border:none}.publish-btn .publish-label{font-size:.72rem;letter-spacing:.02em}.publish-btn:hover:not(:disabled){background:color-mix(in srgb,#22c55e 85%,#000);color:#fff}.publish-btn.is-published{background:transparent;color:var(--p-text-muted-color);border:1px solid var(--p-surface-200)}.publish-btn.is-published:hover:not(:disabled){background:color-mix(in srgb,#ef4444 10%,transparent);color:#ef4444;border-color:color-mix(in srgb,#ef4444 40%,transparent)}::ng-deep .toolbar-popover .p-popover-content{padding:.25rem!important;background:var(--p-surface-0)!important;border:1px solid var(--p-surface-200)!important;border-radius:10px!important;box-shadow:0 4px 16px #0f172a1a!important}.popover-strip{display:flex;flex-direction:column;gap:2px;min-width:120px}.popover-option{display:flex;align-items:center;gap:.5rem;width:100%;padding:.4rem .65rem;border:none;background:transparent;color:var(--p-text-color);cursor:pointer;font-size:.8rem;border-radius:6px;transition:background .12s ease-out,color .12s ease-out;white-space:nowrap}.popover-option i{font-size:1rem;color:var(--p-text-muted-color)}.popover-option:hover{background:var(--p-surface-50)}.popover-option.is-active{background:#cb9090;color:#fff}.popover-option.is-active i{color:#fff}::ng-deep .toolbar-popover .zoom-popover{display:flex;flex-direction:column;gap:4px;padding:.15rem 0}::ng-deep .toolbar-popover .zoom-slider-row{display:flex;align-items:center;gap:.5rem;padding:.3rem .65rem .1rem}::ng-deep .toolbar-popover .zoom-slider{flex:1;-webkit-appearance:none;appearance:none;height:3px;border-radius:999px;background:var(--p-surface-200);outline:none;cursor:pointer}::ng-deep .toolbar-popover .zoom-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:14px;height:14px;border-radius:50%;background:#cb9090;cursor:pointer;transition:transform .12s ease-out}::ng-deep .toolbar-popover .zoom-slider::-webkit-slider-thumb:hover{transform:scale(1.2)}::ng-deep .toolbar-popover .zoom-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;border:none;background:#cb9090;cursor:pointer}::ng-deep .toolbar-popover .zoom-slider-value{font-size:.68rem;font-weight:500;color:var(--p-text-muted-color);min-width:2.4rem;text-align:end;letter-spacing:.02em}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i2$1.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }] }); }
|
|
4624
4756
|
}
|
|
4625
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4757
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: ToolbarComponent, decorators: [{
|
|
4626
4758
|
type: Component,
|
|
4627
|
-
args: [{ selector: 'app-toolbar', standalone: false, template: "<div class=\"builder-toolbar\">\n <!-- \u2500\u2500 Mode switcher (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful\"\n (click)=\"toggleModePopover($event)\"\n [title]=\"activeModeLabel\">\n <i [class]=\"activeModeIcon\"></i>\n </button>\n\n <p-popover #modePopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Select\"\n (click)=\"selectMode(modes.Select)\">\n <i class=\"ph-thin ph-cursor\"></i>\n <span>Select</span>\n </button>\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Pan\"\n (click)=\"selectMode(modes.Pan)\">\n <i class=\"ph-thin ph-hand\"></i>\n <span>Pan</span>\n </button>\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Style\"\n (click)=\"selectMode(modes.Style)\">\n <i class=\"ph-thin ph-paint-brush-broad\"></i>\n <span>Style</span>\n </button>\n </div>\n </p-popover>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Undo / Redo (action) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn\" title=\"Undo\" [disabled]=\"!canUndo\" (click)=\"undo.emit()\">\n <i class=\"ph-thin ph-arrow-counter-clockwise\"></i>\n </button>\n <button class=\"tool-btn\" title=\"Redo\" [disabled]=\"!canRedo\" (click)=\"redo.emit()\">\n <i class=\"ph-thin ph-arrow-clockwise\"></i>\n </button>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Device switcher (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful\"\n (click)=\"toggleDevicePopover($event)\"\n [title]=\"activeDeviceOption.label\">\n <i [class]=\"activeDeviceOption.icon\"></i>\n </button>\n\n <p-popover #devicePopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let d of deviceOptions\"\n [class.is-active]=\"activeDevice === d.mode\"\n (click)=\"selectDevice(d.mode)\">\n <i [class]=\"d.icon\"></i>\n <span>{{ d.label }}</span>\n </button>\n </div>\n </p-popover>\n\n <!-- \u2500\u2500 Screen width \u2014 Desktop only \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeDevice === deviceModes.Desktop) {\n <button class=\"tool-btn stateful width-btn\"\n (click)=\"toggleWidthPopover($event)\"\n title=\"Screen width\">\n <span class=\"width-label\">{{ activeScreenWidth }}</span>\n </button>\n }\n\n <p-popover #widthPopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let w of screenWidthOptions\"\n [class.is-active]=\"activeScreenWidth === w.width\"\n (click)=\"selectScreenWidth(w.width)\">\n <span>{{ w.label }}</span>\n </button>\n </div>\n </p-popover>\n\n <!-- \u2500\u2500 Zoom (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful zoom-btn\"\n (click)=\"toggleZoomPopover($event)\"\n title=\"Zoom\">\n <span class=\"zoom-label\">{{ zoomLabel }}</span>\n </button>\n\n <p-popover #zoomPopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"zoom-popover\">\n <div class=\"zoom-slider-row\">\n <input class=\"zoom-slider\"\n type=\"range\"\n min=\"20\" max=\"100\" step=\"1\"\n [value]=\"sliderZoom\"\n (input)=\"onSliderChange($event)\">\n <span class=\"zoom-slider-value\">{{ zoomLabel }}</span>\n </div>\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let z of zoomOptions\"\n [class.is-active]=\"z.value === activeZoom\"\n (click)=\"selectZoom(z.value)\">\n <span>{{ z.label }}</span>\n </button>\n </div>\n </div>\n </p-popover>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn save-btn\"\n [class.is-saving]=\"isSaving\"\n [disabled]=\"isSaving\"\n title=\"Save\"\n (click)=\"save.emit()\">\n <i class=\"ph-thin ph-floppy-disk\"></i>\n </button>\n\n <!-- \u2500\u2500 Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn preview-btn\"\n title=\"Preview\"\n (click)=\"preview.emit()\">\n <i class=\"ph-thin ph-eye\"></i>\n </button>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Publish / Unpublish \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn publish-btn\"\n [class.is-published]=\"isPublished\"\n [title]=\"isPublished ? 'Unpublish' : 'Publish'\"\n (click)=\"publishToggle.emit()\">\n <i [class]=\"isPublished ? 'ph-thin ph-cloud-slash' : 'ph-thin ph-cloud-arrow-up'\"></i>\n <span class=\"publish-label\">{{ isPublished ? 'Unpublish' : 'Publish' }}</span>\n </button>\n</div>\n", styles: [".builder-toolbar{display:flex;align-items:center;gap:.125rem}.divider{width:1px;height:1.25rem;background:var(--p-surface-200);margin:0 .375rem;flex-shrink:0}.tool-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.tool-btn:hover:not(:disabled){background:var(--p-surface-50);color:var(--p-text-color)}.tool-btn:disabled{opacity:.35;cursor:default}.tool-btn.stateful{position:relative}.tool-btn.stateful:after{content:\"\";position:absolute;inset-block-end:3px;width:4px;height:4px;border-radius:50%;background:#cb9090}.zoom-btn{width:auto;border-radius:999px;padding:0 .5rem;min-width:2.5rem}.zoom-btn .zoom-label{font-size:.7rem;font-weight:500;letter-spacing:.02em}.width-btn{width:auto;border-radius:999px;padding:0 .5rem;min-width:2.8rem}.width-btn .width-label{font-size:.7rem;font-weight:500;letter-spacing:.02em}.save-btn{background:#cb9090;color:#fff}.save-btn:hover:not(:disabled){background:#b37373;color:#fff}.save-btn.is-saving{opacity:.7}.preview-btn{border:1px solid var(--p-surface-200)}.preview-btn:hover:not(:disabled){background:var(--p-surface-50);color:var(--p-text-color);border-color:var(--p-surface-100)}.publish-btn{width:auto;border-radius:999px;padding:0 .65rem;gap:.35rem;font-size:.75rem;font-weight:500;background:#22c55e;color:#fff;border:none}.publish-btn .publish-label{font-size:.72rem;letter-spacing:.02em}.publish-btn:hover:not(:disabled){background:color-mix(in srgb,#22c55e 85%,#000);color:#fff}.publish-btn.is-published{background:transparent;color:var(--p-text-muted-color);border:1px solid var(--p-surface-200)}.publish-btn.is-published:hover:not(:disabled){background:color-mix(in srgb,#ef4444 10%,transparent);color:#ef4444;border-color:color-mix(in srgb,#ef4444 40%,transparent)}::ng-deep .toolbar-popover .p-popover-content{padding:.25rem!important;background:var(--p-surface-0)!important;border:1px solid var(--p-surface-200)!important;border-radius:10px!important;box-shadow:0 4px 16px #0f172a1a!important}.popover-strip{display:flex;flex-direction:column;gap:2px;min-width:120px}.popover-option{display:flex;align-items:center;gap:.5rem;width:100%;padding:.4rem .65rem;border:none;background:transparent;color:var(--p-text-color);cursor:pointer;font-size:.8rem;border-radius:6px;transition:background .12s ease-out,color .12s ease-out;white-space:nowrap}.popover-option i{font-size:1rem;color:var(--p-text-muted-color)}.popover-option:hover{background:var(--p-surface-50)}.popover-option.is-active{background:#cb9090;color:#fff}.popover-option.is-active i{color:#fff}::ng-deep .toolbar-popover .zoom-popover{display:flex;flex-direction:column;gap:4px;padding:.15rem 0}::ng-deep .toolbar-popover .zoom-slider-row{display:flex;align-items:center;gap:.5rem;padding:.3rem .65rem .1rem}::ng-deep .toolbar-popover .zoom-slider{flex:1;-webkit-appearance:none;appearance:none;height:3px;border-radius:999px;background:var(--p-surface-200);outline:none;cursor:pointer}::ng-deep .toolbar-popover .zoom-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:14px;height:14px;border-radius:50%;background:#cb9090;cursor:pointer;transition:transform .12s ease-out}::ng-deep .toolbar-popover .zoom-slider::-webkit-slider-thumb:hover{transform:scale(1.2)}::ng-deep .toolbar-popover .zoom-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;border:none;background:#cb9090;cursor:pointer}::ng-deep .toolbar-popover .zoom-slider-value{font-size:.68rem;font-weight:500;color:var(--p-text-muted-color);min-width:2.4rem;text-align:end;letter-spacing:.02em}\n"] }]
|
|
4759
|
+
args: [{ selector: 'app-toolbar', standalone: false, template: "<div class=\"builder-toolbar\">\n <!-- \u2500\u2500 Mode switcher (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful\"\n (click)=\"toggleModePopover($event)\"\n [title]=\"activeModeLabel\">\n <i [class]=\"activeModeIcon\"></i>\n </button>\n\n <p-popover #modePopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Select\"\n (click)=\"selectMode(modes.Select)\">\n <i class=\"ph-thin ph-cursor\"></i>\n <span>Select</span>\n </button>\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Pan\"\n (click)=\"selectMode(modes.Pan)\">\n <i class=\"ph-thin ph-hand\"></i>\n <span>Pan</span>\n </button>\n <button class=\"popover-option\"\n [class.is-active]=\"activeMode === modes.Style\"\n (click)=\"selectMode(modes.Style)\">\n <i class=\"ph-thin ph-paint-brush-broad\"></i>\n <span>Style</span>\n </button>\n </div>\n </p-popover>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Undo / Redo (action) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn\" title=\"Undo\" [disabled]=\"!canUndo\" (click)=\"undo.emit()\">\n <i class=\"ph-thin ph-arrow-counter-clockwise\"></i>\n </button>\n <button class=\"tool-btn\" title=\"Redo\" [disabled]=\"!canRedo\" (click)=\"redo.emit()\">\n <i class=\"ph-thin ph-arrow-clockwise\"></i>\n </button>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Breakpoint bar \u2014 the EDITING SCOPE, not just a preview size \u2500\u2500 -->\n <div class=\"breakpoint-bar\" role=\"group\" aria-label=\"Breakpoint\">\n @for (bp of breakpointOptions; track bp.id) {\n <button type=\"button\"\n class=\"bp-btn\"\n [class.is-active]=\"activeBreakpoint === bp.id\"\n [attr.aria-pressed]=\"activeBreakpoint === bp.id\"\n [title]=\"bp.label + ' \u00B7 ' + bp.range\"\n [attr.aria-label]=\"bp.label\"\n (click)=\"selectBreakpoint(bp.id)\">\n <i [class]=\"bp.icon\" [class.bp-icon--landscape]=\"bp.landscape\" aria-hidden=\"true\"></i>\n @if (breakpointCounts[bp.id]) {\n <span class=\"bp-dot\" aria-hidden=\"true\"></span>\n }\n </button>\n }\n </div>\n\n <!-- \u2500\u2500 Screen width \u2014 Base only (any width above Laptop) \u2500\u2500 -->\n @if (activeBreakpoint === breakpointIds.Base) {\n <button class=\"tool-btn stateful width-btn\"\n (click)=\"toggleWidthPopover($event)\"\n title=\"Screen width\">\n <span class=\"width-label\">{{ activeScreenWidth }}</span>\n </button>\n }\n\n <p-popover #widthPopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let w of screenWidthOptions\"\n [class.is-active]=\"activeScreenWidth === w.width\"\n (click)=\"selectScreenWidth(w.width)\">\n <span>{{ w.label }}</span>\n </button>\n </div>\n </p-popover>\n\n <!-- \u2500\u2500 Zoom (stateful) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn stateful zoom-btn\"\n (click)=\"toggleZoomPopover($event)\"\n title=\"Zoom\">\n <span class=\"zoom-label\">{{ zoomLabel }}</span>\n </button>\n\n <p-popover #zoomPopover [appendTo]=\"'body'\" styleClass=\"toolbar-popover\">\n <div class=\"zoom-popover\">\n <div class=\"zoom-slider-row\">\n <input class=\"zoom-slider\"\n type=\"range\"\n min=\"20\" max=\"100\" step=\"1\"\n [value]=\"sliderZoom\"\n (input)=\"onSliderChange($event)\">\n <span class=\"zoom-slider-value\">{{ zoomLabel }}</span>\n </div>\n <div class=\"popover-strip\">\n <button class=\"popover-option\"\n *ngFor=\"let z of zoomOptions\"\n [class.is-active]=\"z.value === activeZoom\"\n (click)=\"selectZoom(z.value)\">\n <span>{{ z.label }}</span>\n </button>\n </div>\n </div>\n </p-popover>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn save-btn\"\n [class.is-saving]=\"isSaving\"\n [disabled]=\"isSaving\"\n title=\"Save\"\n (click)=\"save.emit()\">\n <i class=\"ph-thin ph-floppy-disk\"></i>\n </button>\n\n <!-- \u2500\u2500 Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn preview-btn\"\n title=\"Preview\"\n (click)=\"preview.emit()\">\n <i class=\"ph-thin ph-eye\"></i>\n </button>\n\n <span class=\"divider\"></span>\n\n <!-- \u2500\u2500 Publish / Unpublish \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <button class=\"tool-btn publish-btn\"\n [class.is-published]=\"isPublished\"\n [title]=\"isPublished ? 'Unpublish' : 'Publish'\"\n (click)=\"publishToggle.emit()\">\n <i [class]=\"isPublished ? 'ph-thin ph-cloud-slash' : 'ph-thin ph-cloud-arrow-up'\"></i>\n <span class=\"publish-label\">{{ isPublished ? 'Unpublish' : 'Publish' }}</span>\n </button>\n</div>\n", styles: [".builder-toolbar{display:flex;align-items:center;gap:.125rem}.divider{width:1px;height:1.25rem;background:var(--p-surface-200);margin:0 .375rem;flex-shrink:0}.tool-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.tool-btn:hover:not(:disabled){background:var(--p-surface-50);color:var(--p-text-color)}.tool-btn:disabled{opacity:.35;cursor:default}.tool-btn.stateful{position:relative}.tool-btn.stateful:after{content:\"\";position:absolute;inset-block-end:3px;width:4px;height:4px;border-radius:50%;background:#cb9090}.breakpoint-bar{display:flex;align-items:center;gap:1px;padding:2px;border-radius:8px;background:var(--p-surface-100)}.bp-btn{position:relative;display:flex;align-items:center;justify-content:center;width:1.875rem;height:1.75rem;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--p-text-muted-color);font-size:.95rem;cursor:pointer;transition:background .15s ease-out,color .15s ease-out,border-color .15s ease-out}.bp-btn:hover{background:var(--p-surface-0);color:var(--p-text-color)}.bp-btn:focus-visible{outline:2px solid #cb9090;outline-offset:1px}.bp-btn.is-active{background:var(--p-surface-0);border-color:#cb9090;color:#a05c5c}.bp-icon--landscape{transform:rotate(90deg)}.bp-dot{position:absolute;inset-block-start:3px;inset-inline-end:3px;width:5px;height:5px;border-radius:50%;background:#d9924e}.zoom-btn{width:auto;border-radius:999px;padding:0 .5rem;min-width:2.5rem}.zoom-btn .zoom-label{font-size:.7rem;font-weight:500;letter-spacing:.02em}.width-btn{width:auto;border-radius:999px;padding:0 .5rem;min-width:2.8rem}.width-btn .width-label{font-size:.7rem;font-weight:500;letter-spacing:.02em}.save-btn{background:#cb9090;color:#fff}.save-btn:hover:not(:disabled){background:#b37373;color:#fff}.save-btn.is-saving{opacity:.7}.preview-btn{border:1px solid var(--p-surface-200)}.preview-btn:hover:not(:disabled){background:var(--p-surface-50);color:var(--p-text-color);border-color:var(--p-surface-100)}.publish-btn{width:auto;border-radius:999px;padding:0 .65rem;gap:.35rem;font-size:.75rem;font-weight:500;background:#22c55e;color:#fff;border:none}.publish-btn .publish-label{font-size:.72rem;letter-spacing:.02em}.publish-btn:hover:not(:disabled){background:color-mix(in srgb,#22c55e 85%,#000);color:#fff}.publish-btn.is-published{background:transparent;color:var(--p-text-muted-color);border:1px solid var(--p-surface-200)}.publish-btn.is-published:hover:not(:disabled){background:color-mix(in srgb,#ef4444 10%,transparent);color:#ef4444;border-color:color-mix(in srgb,#ef4444 40%,transparent)}::ng-deep .toolbar-popover .p-popover-content{padding:.25rem!important;background:var(--p-surface-0)!important;border:1px solid var(--p-surface-200)!important;border-radius:10px!important;box-shadow:0 4px 16px #0f172a1a!important}.popover-strip{display:flex;flex-direction:column;gap:2px;min-width:120px}.popover-option{display:flex;align-items:center;gap:.5rem;width:100%;padding:.4rem .65rem;border:none;background:transparent;color:var(--p-text-color);cursor:pointer;font-size:.8rem;border-radius:6px;transition:background .12s ease-out,color .12s ease-out;white-space:nowrap}.popover-option i{font-size:1rem;color:var(--p-text-muted-color)}.popover-option:hover{background:var(--p-surface-50)}.popover-option.is-active{background:#cb9090;color:#fff}.popover-option.is-active i{color:#fff}::ng-deep .toolbar-popover .zoom-popover{display:flex;flex-direction:column;gap:4px;padding:.15rem 0}::ng-deep .toolbar-popover .zoom-slider-row{display:flex;align-items:center;gap:.5rem;padding:.3rem .65rem .1rem}::ng-deep .toolbar-popover .zoom-slider{flex:1;-webkit-appearance:none;appearance:none;height:3px;border-radius:999px;background:var(--p-surface-200);outline:none;cursor:pointer}::ng-deep .toolbar-popover .zoom-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:14px;height:14px;border-radius:50%;background:#cb9090;cursor:pointer;transition:transform .12s ease-out}::ng-deep .toolbar-popover .zoom-slider::-webkit-slider-thumb:hover{transform:scale(1.2)}::ng-deep .toolbar-popover .zoom-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;border:none;background:#cb9090;cursor:pointer}::ng-deep .toolbar-popover .zoom-slider-value{font-size:.68rem;font-weight:500;color:var(--p-text-muted-color);min-width:2.4rem;text-align:end;letter-spacing:.02em}\n"] }]
|
|
4628
4760
|
}], propDecorators: { activeMode: [{
|
|
4629
4761
|
type: Input
|
|
4630
|
-
}],
|
|
4762
|
+
}], activeBreakpoint: [{
|
|
4763
|
+
type: Input
|
|
4764
|
+
}], breakpointCounts: [{
|
|
4631
4765
|
type: Input
|
|
4632
4766
|
}], activeZoom: [{
|
|
4633
4767
|
type: Input
|
|
@@ -4643,7 +4777,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
4643
4777
|
type: Input
|
|
4644
4778
|
}], modeChange: [{
|
|
4645
4779
|
type: Output
|
|
4646
|
-
}],
|
|
4780
|
+
}], breakpointChange: [{
|
|
4647
4781
|
type: Output
|
|
4648
4782
|
}], zoomChange: [{
|
|
4649
4783
|
type: Output
|
|
@@ -4662,9 +4796,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
4662
4796
|
}], modePopover: [{
|
|
4663
4797
|
type: ViewChild,
|
|
4664
4798
|
args: ['modePopover']
|
|
4665
|
-
}], devicePopover: [{
|
|
4666
|
-
type: ViewChild,
|
|
4667
|
-
args: ['devicePopover']
|
|
4668
4799
|
}], zoomPopover: [{
|
|
4669
4800
|
type: ViewChild,
|
|
4670
4801
|
args: ['zoomPopover']
|
|
@@ -4847,10 +4978,10 @@ class LayerTreeComponent {
|
|
|
4847
4978
|
}
|
|
4848
4979
|
}
|
|
4849
4980
|
}
|
|
4850
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4851
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: LayerTreeComponent, isStandalone: false, selector: "app-layer-tree", inputs: { layout: "layout", globalElements: "globalElements" }, outputs: { nodeSelect: "nodeSelect", nodeAction: "nodeAction", nodeMove: "nodeMove" }, ngImport: i0, template: "<div class=\"layer-tree\">\n <div class=\"tree-header\">\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'page'\" (click)=\"activeSection = 'page'\">\n <i class=\"ph-thin ph-stack\"></i> Page\n </button>\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'global'\" (click)=\"activeSection = 'global'\">\n <i class=\"ph-thin ph-globe\"></i> Global\n <span *ngIf=\"flatGlobalTree.length\" class=\"section-tab-badge\">{{ flatGlobalTree.length }}</span>\n </button>\n </div>\n\n <!-- \u2500\u2500 Page elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div *ngIf=\"activeSection === 'page'\"\n class=\"tree-body\"\n cdkDropList\n [cdkDropListData]=\"flatTree\"\n (cdkDropListDropped)=\"onTreeDrop($event)\">\n <div *ngIf=\"!flatTree.length\" class=\"tree-empty\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n <span>No layers yet</span>\n </div>\n\n <div *ngFor=\"let tn of flatTree\"\n class=\"tree-row\"\n cdkDrag\n [cdkDragData]=\"tn\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <i class=\"ph-thin ph-dots-six-vertical drag-handle\" cdkDragHandle></i>\n\n <button *ngIf=\"tn.hasChildren\" class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n <span *ngIf=\"!tn.hasChildren\" class=\"expand-spacer\"></span>\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <ng-container *ngIf=\"editingNodeId === tn.node.id; else staticLabel\">\n <input class=\"node-rename-input\"\n [value]=\"editingValue\"\n (input)=\"editingValue = $any($event.target).value\"\n (keydown.enter)=\"saveRename(tn)\"\n (keydown.escape)=\"cancelRename()\"\n (blur)=\"saveRename(tn)\"\n (click)=\"$event.stopPropagation()\"\n autofocus>\n </ng-container>\n <ng-template #staticLabel>\n <span class=\"node-label\" [class.node-label--named]=\"tn.node.label\">{{ tn.label }}</span>\n </ng-template>\n\n <span class=\"node-actions\">\n <button class=\"action-btn\" title=\"Rename\" (click)=\"startRename(tn, $event)\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n </button>\n <button class=\"action-btn\" title=\"Duplicate\" (click)=\"onDuplicateNode(tn, $event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button class=\"action-btn action-btn--delete\" title=\"Delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n </div>\n\n <!-- \u2500\u2500 Global elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div *ngIf=\"activeSection === 'global'\" class=\"tree-body\">\n <div *ngIf=\"!flatGlobalTree.length\" class=\"tree-empty\">\n <i class=\"ph-thin ph-globe\"></i>\n <span>No global elements</span>\n </div>\n\n <div *ngFor=\"let tn of flatGlobalTree\"\n class=\"tree-row tree-row--global\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <button *ngIf=\"tn.hasChildren\" class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n <span *ngIf=\"!tn.hasChildren\" class=\"expand-spacer\"></span>\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <span class=\"node-label\">{{ tn.label }}</span>\n <span class=\"node-position-badge\">{{ tn.node.globalPosition }}</span>\n\n <span class=\"node-actions\">\n <button class=\"action-btn action-btn--delete\" title=\"Delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n </div>\n</div>\n", styles: [".layer-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.layer-tree .tree-header{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--p-surface-200);flex-shrink:0}.layer-tree .section-tab{display:inline-flex;align-items:center;gap:4px;flex:1;justify-content:center;padding:4px 8px;font-size:11px;font-weight:500;border:1px solid var(--p-surface-200);border-radius:4px;background:transparent;color:var(--p-text-muted-color);cursor:pointer;transition:background .12s,color .12s,border-color .12s;white-space:nowrap}.layer-tree .section-tab i{font-size:11px}.layer-tree .section-tab:hover{background:var(--p-surface-100);color:var(--p-text-color)}.layer-tree .section-tab--active{background:#cb909026;border-color:#cb9090;color:#cb9090}.layer-tree .section-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;background:#cb9090;color:#fff;border-radius:8px}.layer-tree .tree-body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding-block:4px}.layer-tree .tree-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2rem 1rem;color:var(--p-text-muted-color);font-size:12px}.layer-tree .tree-empty i{font-size:22px}.layer-tree .tree-row{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;cursor:pointer;font-size:12px;color:var(--p-text-color);border-inline-start:2px solid transparent;transition:background .12s,border-color .12s;-webkit-user-select:none;user-select:none}.layer-tree .tree-row:hover,.layer-tree .tree-row.is-hovered{background:var(--p-surface-100)}.layer-tree .tree-row.is-selected{background:#cb90901a;border-inline-start-color:#cb9090;font-weight:500}.layer-tree .drag-handle{font-size:10px;color:var(--p-text-muted-color);opacity:0;cursor:grab;flex-shrink:0;transition:opacity .12s}.layer-tree .tree-row:hover .drag-handle{opacity:.5}.layer-tree .drag-handle:hover{opacity:1!important}.layer-tree .cdk-drag-preview{box-sizing:border-box;display:flex;align-items:center;gap:6px;height:28px;padding:0 8px 0 12px;border-radius:6px;background:var(--p-surface-0);border:1px solid #cb9090;box-shadow:0 4px 12px #0000001f;font-size:12px}.layer-tree .cdk-drag-placeholder{height:2px;background:#cb9090;border-radius:1px;opacity:.6}.layer-tree .cdk-drag-placeholder>*{visibility:hidden}.layer-tree .cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.layer-tree .expand-btn{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;flex-shrink:0;border-radius:2px}.layer-tree .expand-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .expand-btn i{font-size:10px}.layer-tree .expand-spacer{width:16px;flex-shrink:0}.layer-tree .node-icon{font-size:14px;color:var(--p-text-muted-color);flex-shrink:0}.layer-tree .node-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.layer-tree .node-label.node-label--named{color:var(--p-primary-color, #cb9090);font-weight:500}.layer-tree .node-rename-input{flex:1;min-width:0;border:1px solid var(--p-primary-color, #cb9090);border-radius:4px;background:var(--p-surface-0, #fff);color:var(--p-text-color);font-family:inherit;font-size:.72rem;padding:1px 4px;outline:none}.layer-tree .node-actions{display:flex;gap:2px;margin-inline-start:auto;opacity:0;transition:opacity .12s;flex-shrink:0}.layer-tree .tree-row:hover .node-actions,.layer-tree .tree-row.is-selected .node-actions{opacity:1}.layer-tree .tree-section-header{display:flex;align-items:center;gap:6px;padding:6px 12px 4px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);border-top:1px solid var(--p-surface-200);margin-top:4px}.layer-tree .tree-section-header i{font-size:12px}.layer-tree .tree-body--global{flex:0 0 auto}.layer-tree .tree-row--global{border-inline-start-color:transparent}.layer-tree .tree-row--global.is-selected{background:#638fcb1a;border-inline-start-color:#638fcb}.layer-tree .node-position-badge{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#638fcb;background:#638fcb1f;padding:1px 5px;border-radius:3px;flex-shrink:0}.layer-tree .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;font-size:12px;transition:background .12s,color .12s}.layer-tree .action-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .action-btn--delete:hover{background:#dc26261a;color:#dc2626}\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: i4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }] }); }
|
|
4981
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: LayerTreeComponent, deps: [{ token: ComponentRegistryService }, { token: OverlayService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4982
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: LayerTreeComponent, isStandalone: false, selector: "app-layer-tree", inputs: { layout: "layout", globalElements: "globalElements" }, outputs: { nodeSelect: "nodeSelect", nodeAction: "nodeAction", nodeMove: "nodeMove" }, ngImport: i0, template: "<div class=\"layer-tree\">\n <div class=\"tree-header\">\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'page'\" (click)=\"activeSection = 'page'\">\n <i class=\"ph-thin ph-stack\"></i> Page\n </button>\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'global'\" (click)=\"activeSection = 'global'\">\n <i class=\"ph-thin ph-globe\"></i> Global\n <span *ngIf=\"flatGlobalTree.length\" class=\"section-tab-badge\">{{ flatGlobalTree.length }}</span>\n </button>\n </div>\n\n <!-- \u2500\u2500 Page elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div *ngIf=\"activeSection === 'page'\"\n class=\"tree-body\"\n cdkDropList\n [cdkDropListData]=\"flatTree\"\n (cdkDropListDropped)=\"onTreeDrop($event)\">\n <div *ngIf=\"!flatTree.length\" class=\"tree-empty\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n <span>No layers yet</span>\n </div>\n\n <div *ngFor=\"let tn of flatTree\"\n class=\"tree-row\"\n cdkDrag\n [cdkDragData]=\"tn\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <i class=\"ph-thin ph-dots-six-vertical drag-handle\" cdkDragHandle></i>\n\n <button *ngIf=\"tn.hasChildren\" class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n <span *ngIf=\"!tn.hasChildren\" class=\"expand-spacer\"></span>\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <ng-container *ngIf=\"editingNodeId === tn.node.id; else staticLabel\">\n <input class=\"node-rename-input\"\n [value]=\"editingValue\"\n (input)=\"editingValue = $any($event.target).value\"\n (keydown.enter)=\"saveRename(tn)\"\n (keydown.escape)=\"cancelRename()\"\n (blur)=\"saveRename(tn)\"\n (click)=\"$event.stopPropagation()\"\n autofocus>\n </ng-container>\n <ng-template #staticLabel>\n <span class=\"node-label\" [class.node-label--named]=\"tn.node.label\">{{ tn.label }}</span>\n </ng-template>\n\n <span class=\"node-actions\">\n <button class=\"action-btn\" title=\"Rename\" (click)=\"startRename(tn, $event)\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n </button>\n <button class=\"action-btn\" title=\"Duplicate\" (click)=\"onDuplicateNode(tn, $event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button class=\"action-btn action-btn--delete\" title=\"Delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n </div>\n\n <!-- \u2500\u2500 Global elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div *ngIf=\"activeSection === 'global'\" class=\"tree-body\">\n <div *ngIf=\"!flatGlobalTree.length\" class=\"tree-empty\">\n <i class=\"ph-thin ph-globe\"></i>\n <span>No global elements</span>\n </div>\n\n <div *ngFor=\"let tn of flatGlobalTree\"\n class=\"tree-row tree-row--global\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <button *ngIf=\"tn.hasChildren\" class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n <span *ngIf=\"!tn.hasChildren\" class=\"expand-spacer\"></span>\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <span class=\"node-label\">{{ tn.label }}</span>\n <span class=\"node-position-badge\">{{ tn.node.globalPosition }}</span>\n\n <span class=\"node-actions\">\n <button class=\"action-btn action-btn--delete\" title=\"Delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n </div>\n</div>\n", styles: [".layer-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.layer-tree .tree-header{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--p-surface-200);flex-shrink:0}.layer-tree .section-tab{display:inline-flex;align-items:center;gap:4px;flex:1;justify-content:center;padding:4px 8px;font-size:11px;font-weight:500;border:1px solid var(--p-surface-200);border-radius:4px;background:transparent;color:var(--p-text-muted-color);cursor:pointer;transition:background .12s,color .12s,border-color .12s;white-space:nowrap}.layer-tree .section-tab i{font-size:11px}.layer-tree .section-tab:hover{background:var(--p-surface-100);color:var(--p-text-color)}.layer-tree .section-tab--active{background:#cb909026;border-color:#cb9090;color:#cb9090}.layer-tree .section-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;background:#cb9090;color:#fff;border-radius:8px}.layer-tree .tree-body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding-block:4px}.layer-tree .tree-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2rem 1rem;color:var(--p-text-muted-color);font-size:12px}.layer-tree .tree-empty i{font-size:22px}.layer-tree .tree-row{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;cursor:pointer;font-size:12px;color:var(--p-text-color);border-inline-start:2px solid transparent;transition:background .12s,border-color .12s;-webkit-user-select:none;user-select:none}.layer-tree .tree-row:hover,.layer-tree .tree-row.is-hovered{background:var(--p-surface-100)}.layer-tree .tree-row.is-selected{background:#cb90901a;border-inline-start-color:#cb9090;font-weight:500}.layer-tree .drag-handle{font-size:10px;color:var(--p-text-muted-color);opacity:0;cursor:grab;flex-shrink:0;transition:opacity .12s}.layer-tree .tree-row:hover .drag-handle{opacity:.5}.layer-tree .drag-handle:hover{opacity:1!important}.layer-tree .cdk-drag-preview{box-sizing:border-box;display:flex;align-items:center;gap:6px;height:28px;padding:0 8px 0 12px;border-radius:6px;background:var(--p-surface-0);border:1px solid #cb9090;box-shadow:0 4px 12px #0000001f;font-size:12px}.layer-tree .cdk-drag-placeholder{height:2px;background:#cb9090;border-radius:1px;opacity:.6}.layer-tree .cdk-drag-placeholder>*{visibility:hidden}.layer-tree .cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.layer-tree .expand-btn{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;flex-shrink:0;border-radius:2px}.layer-tree .expand-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .expand-btn i{font-size:10px}.layer-tree .expand-spacer{width:16px;flex-shrink:0}.layer-tree .node-icon{font-size:14px;color:var(--p-text-muted-color);flex-shrink:0}.layer-tree .node-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.layer-tree .node-label.node-label--named{color:var(--p-primary-color, #cb9090);font-weight:500}.layer-tree .node-rename-input{flex:1;min-width:0;border:1px solid var(--p-primary-color, #cb9090);border-radius:4px;background:var(--p-surface-0, #fff);color:var(--p-text-color);font-family:inherit;font-size:.72rem;padding:1px 4px;outline:none}.layer-tree .node-actions{display:flex;gap:2px;margin-inline-start:auto;opacity:0;transition:opacity .12s;flex-shrink:0}.layer-tree .tree-row:hover .node-actions,.layer-tree .tree-row.is-selected .node-actions{opacity:1}.layer-tree .tree-section-header{display:flex;align-items:center;gap:6px;padding:6px 12px 4px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);border-top:1px solid var(--p-surface-200);margin-top:4px}.layer-tree .tree-section-header i{font-size:12px}.layer-tree .tree-body--global{flex:0 0 auto}.layer-tree .tree-row--global{border-inline-start-color:transparent}.layer-tree .tree-row--global.is-selected{background:#638fcb1a;border-inline-start-color:#638fcb}.layer-tree .node-position-badge{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#638fcb;background:#638fcb1f;padding:1px 5px;border-radius:3px;flex-shrink:0}.layer-tree .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;font-size:12px;transition:background .12s,color .12s}.layer-tree .action-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .action-btn--delete:hover{background:#dc26261a;color:#dc2626}\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: i4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }] }); }
|
|
4852
4983
|
}
|
|
4853
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4984
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: LayerTreeComponent, decorators: [{
|
|
4854
4985
|
type: Component,
|
|
4855
4986
|
args: [{ selector: 'app-layer-tree', standalone: false, template: "<div class=\"layer-tree\">\n <div class=\"tree-header\">\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'page'\" (click)=\"activeSection = 'page'\">\n <i class=\"ph-thin ph-stack\"></i> Page\n </button>\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'global'\" (click)=\"activeSection = 'global'\">\n <i class=\"ph-thin ph-globe\"></i> Global\n <span *ngIf=\"flatGlobalTree.length\" class=\"section-tab-badge\">{{ flatGlobalTree.length }}</span>\n </button>\n </div>\n\n <!-- \u2500\u2500 Page elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div *ngIf=\"activeSection === 'page'\"\n class=\"tree-body\"\n cdkDropList\n [cdkDropListData]=\"flatTree\"\n (cdkDropListDropped)=\"onTreeDrop($event)\">\n <div *ngIf=\"!flatTree.length\" class=\"tree-empty\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n <span>No layers yet</span>\n </div>\n\n <div *ngFor=\"let tn of flatTree\"\n class=\"tree-row\"\n cdkDrag\n [cdkDragData]=\"tn\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <i class=\"ph-thin ph-dots-six-vertical drag-handle\" cdkDragHandle></i>\n\n <button *ngIf=\"tn.hasChildren\" class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n <span *ngIf=\"!tn.hasChildren\" class=\"expand-spacer\"></span>\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <ng-container *ngIf=\"editingNodeId === tn.node.id; else staticLabel\">\n <input class=\"node-rename-input\"\n [value]=\"editingValue\"\n (input)=\"editingValue = $any($event.target).value\"\n (keydown.enter)=\"saveRename(tn)\"\n (keydown.escape)=\"cancelRename()\"\n (blur)=\"saveRename(tn)\"\n (click)=\"$event.stopPropagation()\"\n autofocus>\n </ng-container>\n <ng-template #staticLabel>\n <span class=\"node-label\" [class.node-label--named]=\"tn.node.label\">{{ tn.label }}</span>\n </ng-template>\n\n <span class=\"node-actions\">\n <button class=\"action-btn\" title=\"Rename\" (click)=\"startRename(tn, $event)\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n </button>\n <button class=\"action-btn\" title=\"Duplicate\" (click)=\"onDuplicateNode(tn, $event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n <button class=\"action-btn action-btn--delete\" title=\"Delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n </div>\n\n <!-- \u2500\u2500 Global elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div *ngIf=\"activeSection === 'global'\" class=\"tree-body\">\n <div *ngIf=\"!flatGlobalTree.length\" class=\"tree-empty\">\n <i class=\"ph-thin ph-globe\"></i>\n <span>No global elements</span>\n </div>\n\n <div *ngFor=\"let tn of flatGlobalTree\"\n class=\"tree-row tree-row--global\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <button *ngIf=\"tn.hasChildren\" class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n <span *ngIf=\"!tn.hasChildren\" class=\"expand-spacer\"></span>\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <span class=\"node-label\">{{ tn.label }}</span>\n <span class=\"node-position-badge\">{{ tn.node.globalPosition }}</span>\n\n <span class=\"node-actions\">\n <button class=\"action-btn action-btn--delete\" title=\"Delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n </div>\n</div>\n", styles: [".layer-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.layer-tree .tree-header{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--p-surface-200);flex-shrink:0}.layer-tree .section-tab{display:inline-flex;align-items:center;gap:4px;flex:1;justify-content:center;padding:4px 8px;font-size:11px;font-weight:500;border:1px solid var(--p-surface-200);border-radius:4px;background:transparent;color:var(--p-text-muted-color);cursor:pointer;transition:background .12s,color .12s,border-color .12s;white-space:nowrap}.layer-tree .section-tab i{font-size:11px}.layer-tree .section-tab:hover{background:var(--p-surface-100);color:var(--p-text-color)}.layer-tree .section-tab--active{background:#cb909026;border-color:#cb9090;color:#cb9090}.layer-tree .section-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;background:#cb9090;color:#fff;border-radius:8px}.layer-tree .tree-body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding-block:4px}.layer-tree .tree-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2rem 1rem;color:var(--p-text-muted-color);font-size:12px}.layer-tree .tree-empty i{font-size:22px}.layer-tree .tree-row{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;cursor:pointer;font-size:12px;color:var(--p-text-color);border-inline-start:2px solid transparent;transition:background .12s,border-color .12s;-webkit-user-select:none;user-select:none}.layer-tree .tree-row:hover,.layer-tree .tree-row.is-hovered{background:var(--p-surface-100)}.layer-tree .tree-row.is-selected{background:#cb90901a;border-inline-start-color:#cb9090;font-weight:500}.layer-tree .drag-handle{font-size:10px;color:var(--p-text-muted-color);opacity:0;cursor:grab;flex-shrink:0;transition:opacity .12s}.layer-tree .tree-row:hover .drag-handle{opacity:.5}.layer-tree .drag-handle:hover{opacity:1!important}.layer-tree .cdk-drag-preview{box-sizing:border-box;display:flex;align-items:center;gap:6px;height:28px;padding:0 8px 0 12px;border-radius:6px;background:var(--p-surface-0);border:1px solid #cb9090;box-shadow:0 4px 12px #0000001f;font-size:12px}.layer-tree .cdk-drag-placeholder{height:2px;background:#cb9090;border-radius:1px;opacity:.6}.layer-tree .cdk-drag-placeholder>*{visibility:hidden}.layer-tree .cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.layer-tree .expand-btn{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;flex-shrink:0;border-radius:2px}.layer-tree .expand-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .expand-btn i{font-size:10px}.layer-tree .expand-spacer{width:16px;flex-shrink:0}.layer-tree .node-icon{font-size:14px;color:var(--p-text-muted-color);flex-shrink:0}.layer-tree .node-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.layer-tree .node-label.node-label--named{color:var(--p-primary-color, #cb9090);font-weight:500}.layer-tree .node-rename-input{flex:1;min-width:0;border:1px solid var(--p-primary-color, #cb9090);border-radius:4px;background:var(--p-surface-0, #fff);color:var(--p-text-color);font-family:inherit;font-size:.72rem;padding:1px 4px;outline:none}.layer-tree .node-actions{display:flex;gap:2px;margin-inline-start:auto;opacity:0;transition:opacity .12s;flex-shrink:0}.layer-tree .tree-row:hover .node-actions,.layer-tree .tree-row.is-selected .node-actions{opacity:1}.layer-tree .tree-section-header{display:flex;align-items:center;gap:6px;padding:6px 12px 4px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);border-top:1px solid var(--p-surface-200);margin-top:4px}.layer-tree .tree-section-header i{font-size:12px}.layer-tree .tree-body--global{flex:0 0 auto}.layer-tree .tree-row--global{border-inline-start-color:transparent}.layer-tree .tree-row--global.is-selected{background:#638fcb1a;border-inline-start-color:#638fcb}.layer-tree .node-position-badge{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#638fcb;background:#638fcb1f;padding:1px 5px;border-radius:3px;flex-shrink:0}.layer-tree .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;font-size:12px;transition:background .12s,color .12s}.layer-tree .action-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .action-btn--delete:hover{background:#dc26261a;color:#dc2626}\n"] }]
|
|
4856
4987
|
}], ctorParameters: () => [{ type: ComponentRegistryService }, { type: OverlayService }], propDecorators: { layout: [{
|
|
@@ -4937,10 +5068,10 @@ class BreadcrumbBarComponent {
|
|
|
4937
5068
|
.filter(([on]) => on)
|
|
4938
5069
|
.map(([, icon, label, title]) => ({ icon, label, title }));
|
|
4939
5070
|
}
|
|
4940
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4941
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
5071
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BreadcrumbBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5072
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: BreadcrumbBarComponent, isStandalone: false, selector: "app-breadcrumb-bar", inputs: { path: "path" }, outputs: { nodeSelect: "nodeSelect", nodePeek: "nodePeek" }, ngImport: i0, template: "<nav class=\"breadcrumb-bar\" aria-label=\"Selected element path\">\n @if (crumbs.length) {\n <ol class=\"crumbs\" #crumbList>\n @for (crumb of crumbs; track trackCrumb($index, crumb)) {\n <li class=\"crumb-item\">\n @if (!$first) {\n <i class=\"crumb-sep ph-thin ph-caret-right\" aria-hidden=\"true\"></i>\n }\n <button type=\"button\"\n class=\"crumb\"\n [class.crumb--current]=\"crumb.isCurrent\"\n [attr.aria-current]=\"crumb.isCurrent ? 'true' : null\"\n [title]=\"crumb.label\"\n (mouseenter)=\"onPeek(crumb)\"\n (mouseleave)=\"onPeekEnd()\"\n (focus)=\"onPeek(crumb)\"\n (blur)=\"onPeekEnd()\"\n (click)=\"onSelect(crumb)\">{{ crumb.label }}</button>\n </li>\n }\n </ol>\n\n <div class=\"badges\">\n @for (badge of badges; track trackBadge($index, badge)) {\n <span class=\"badge\" [title]=\"badge.title\">\n <i [class]=\"badge.icon\" aria-hidden=\"true\"></i>\n <span class=\"badge-label\">{{ badge.label }}</span>\n </span>\n }\n </div>\n } @else {\n <span class=\"crumb-empty\">Nothing selected \u2014 click an element on the canvas</span>\n }\n</nav>\n", styles: [".breadcrumb-bar{display:flex;align-items:center;gap:10px;block-size:34px;padding-inline:14px;background:var(--p-content-background);border-block-end:1px solid var(--p-content-border-color);flex:none;overflow:hidden}.crumbs{display:flex;align-items:center;gap:2px;flex:1;min-inline-size:0;margin:0;padding:0;list-style:none;overflow-x:auto;scrollbar-width:none}.crumbs::-webkit-scrollbar{display:none}.crumb-item{display:flex;align-items:center;gap:2px;flex:none}.crumb-sep{font-size:11px;color:var(--p-text-muted-color);opacity:.6}.crumb{max-inline-size:180px;padding:3px 8px;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--p-text-muted-color);font-family:inherit;font-size:11px;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;transition:background-color .15s ease,color .15s ease}.crumb:hover{background:var(--p-content-hover-background);color:var(--p-text-color)}.crumb:focus-visible{outline:2px solid #cb9090;outline-offset:1px}.crumb--current{background:#cb909029;border-color:#cb9090;color:var(--p-text-color);font-weight:600}.crumb-empty{font-size:11px;color:var(--p-text-muted-color);opacity:.75}.badges{display:flex;align-items:center;gap:5px;flex:none}.badge{display:inline-flex;align-items:center;gap:4px;padding:2px 7px;border:1px solid var(--p-content-border-color);border-radius:20px;color:var(--p-text-muted-color);font-size:10px;white-space:nowrap}.badge i{font-size:12px}.badge-label{line-height:1.4}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4942
5073
|
}
|
|
4943
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
5074
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BreadcrumbBarComponent, decorators: [{
|
|
4944
5075
|
type: Component,
|
|
4945
5076
|
args: [{ selector: 'app-breadcrumb-bar', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<nav class=\"breadcrumb-bar\" aria-label=\"Selected element path\">\n @if (crumbs.length) {\n <ol class=\"crumbs\" #crumbList>\n @for (crumb of crumbs; track trackCrumb($index, crumb)) {\n <li class=\"crumb-item\">\n @if (!$first) {\n <i class=\"crumb-sep ph-thin ph-caret-right\" aria-hidden=\"true\"></i>\n }\n <button type=\"button\"\n class=\"crumb\"\n [class.crumb--current]=\"crumb.isCurrent\"\n [attr.aria-current]=\"crumb.isCurrent ? 'true' : null\"\n [title]=\"crumb.label\"\n (mouseenter)=\"onPeek(crumb)\"\n (mouseleave)=\"onPeekEnd()\"\n (focus)=\"onPeek(crumb)\"\n (blur)=\"onPeekEnd()\"\n (click)=\"onSelect(crumb)\">{{ crumb.label }}</button>\n </li>\n }\n </ol>\n\n <div class=\"badges\">\n @for (badge of badges; track trackBadge($index, badge)) {\n <span class=\"badge\" [title]=\"badge.title\">\n <i [class]=\"badge.icon\" aria-hidden=\"true\"></i>\n <span class=\"badge-label\">{{ badge.label }}</span>\n </span>\n }\n </div>\n } @else {\n <span class=\"crumb-empty\">Nothing selected \u2014 click an element on the canvas</span>\n }\n</nav>\n", styles: [".breadcrumb-bar{display:flex;align-items:center;gap:10px;block-size:34px;padding-inline:14px;background:var(--p-content-background);border-block-end:1px solid var(--p-content-border-color);flex:none;overflow:hidden}.crumbs{display:flex;align-items:center;gap:2px;flex:1;min-inline-size:0;margin:0;padding:0;list-style:none;overflow-x:auto;scrollbar-width:none}.crumbs::-webkit-scrollbar{display:none}.crumb-item{display:flex;align-items:center;gap:2px;flex:none}.crumb-sep{font-size:11px;color:var(--p-text-muted-color);opacity:.6}.crumb{max-inline-size:180px;padding:3px 8px;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--p-text-muted-color);font-family:inherit;font-size:11px;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;transition:background-color .15s ease,color .15s ease}.crumb:hover{background:var(--p-content-hover-background);color:var(--p-text-color)}.crumb:focus-visible{outline:2px solid #cb9090;outline-offset:1px}.crumb--current{background:#cb909029;border-color:#cb9090;color:var(--p-text-color);font-weight:600}.crumb-empty{font-size:11px;color:var(--p-text-muted-color);opacity:.75}.badges{display:flex;align-items:center;gap:5px;flex:none}.badge{display:inline-flex;align-items:center;gap:4px;padding:2px 7px;border:1px solid var(--p-content-border-color);border-radius:20px;color:var(--p-text-muted-color);font-size:10px;white-space:nowrap}.badge i{font-size:12px}.badge-label{line-height:1.4}\n"] }]
|
|
4946
5077
|
}], propDecorators: { path: [{
|
|
@@ -4956,8 +5087,8 @@ class BuilderComponent {
|
|
|
4956
5087
|
handleToolbarModeChange(mode) {
|
|
4957
5088
|
this.onModeChange(mode);
|
|
4958
5089
|
}
|
|
4959
|
-
|
|
4960
|
-
this.
|
|
5090
|
+
handleToolbarBreakpointChange(bp) {
|
|
5091
|
+
this.onBreakpointChange(bp);
|
|
4961
5092
|
}
|
|
4962
5093
|
handleToolbarZoomChange(value) {
|
|
4963
5094
|
this.onZoomChange(value);
|
|
@@ -5044,7 +5175,7 @@ class BuilderComponent {
|
|
|
5044
5175
|
if (!slotKeys.size)
|
|
5045
5176
|
return;
|
|
5046
5177
|
this.applyContextBindings(this.layout, withContextSlots({}, slotValues), slotKeys);
|
|
5047
|
-
}, ...(ngDevMode ? [{ debugName: "contextEffect" }] :
|
|
5178
|
+
}, ...(ngDevMode ? [{ debugName: "contextEffect" }] : []));
|
|
5048
5179
|
this.layout = [];
|
|
5049
5180
|
this.dataSources = [];
|
|
5050
5181
|
this.orgId = 'default';
|
|
@@ -5076,7 +5207,11 @@ class BuilderComponent {
|
|
|
5076
5207
|
this.panelTypes = PanelTypes;
|
|
5077
5208
|
this.activeMode = BuilderMode.Select;
|
|
5078
5209
|
this.builderModes = BuilderMode;
|
|
5079
|
-
|
|
5210
|
+
/** The breakpoint being edited — derived from the canvas width by ViewportService. */
|
|
5211
|
+
this.activeBreakpoint = Breakpoint.Base;
|
|
5212
|
+
/** Overrides per breakpoint for the selection (or the whole page when nothing is selected) —
|
|
5213
|
+
* the breakpoint bar's dots. A field recomputed on change, never a getter (OnPush input). */
|
|
5214
|
+
this.breakpointCounts = {};
|
|
5080
5215
|
this.activeZoom = 100;
|
|
5081
5216
|
this.activeScreenWidth = 1440;
|
|
5082
5217
|
this.selectedItem = null;
|
|
@@ -5135,7 +5270,7 @@ class BuilderComponent {
|
|
|
5135
5270
|
}));
|
|
5136
5271
|
this.panelEventService.emit(PanelEventTypes.PANEL_OPEN, PanelTypes.STYLES);
|
|
5137
5272
|
this.viewportSub = this.viewportService.state$.subscribe(state => {
|
|
5138
|
-
this.
|
|
5273
|
+
this.activeBreakpoint = state.breakpoint;
|
|
5139
5274
|
this.activeZoom = Math.round(state.scale * 100);
|
|
5140
5275
|
this.activeScreenWidth = state.width;
|
|
5141
5276
|
this.dragEngine.setScale(state.scale);
|
|
@@ -5160,6 +5295,9 @@ class BuilderComponent {
|
|
|
5160
5295
|
// globalOverlayRef is in the DOM before we try to set CSS vars on it.
|
|
5161
5296
|
setTimeout(() => this.updatePreviewVh());
|
|
5162
5297
|
}
|
|
5298
|
+
// A newly loaded page: the bar's dots must reflect its overrides before anything is selected.
|
|
5299
|
+
if (changes['layout'] || changes['globalElements'])
|
|
5300
|
+
this.refreshBreakpointCounts();
|
|
5163
5301
|
}
|
|
5164
5302
|
ngAfterViewInit() {
|
|
5165
5303
|
this.updatePreviewVh();
|
|
@@ -5450,8 +5588,8 @@ class BuilderComponent {
|
|
|
5450
5588
|
this.panY = 0;
|
|
5451
5589
|
}
|
|
5452
5590
|
}
|
|
5453
|
-
|
|
5454
|
-
this.viewportService.
|
|
5591
|
+
onBreakpointChange(bp) {
|
|
5592
|
+
this.viewportService.setBreakpoint(bp);
|
|
5455
5593
|
this.panX = 0;
|
|
5456
5594
|
this.panY = 0;
|
|
5457
5595
|
this.autoFitViewport();
|
|
@@ -5537,6 +5675,7 @@ class BuilderComponent {
|
|
|
5537
5675
|
this.selectedItem = null;
|
|
5538
5676
|
this.selectedPath = [];
|
|
5539
5677
|
this.overlayService.clearSelect();
|
|
5678
|
+
this.refreshBreakpointCounts();
|
|
5540
5679
|
}
|
|
5541
5680
|
/** Breadcrumb crumb clicked — select that ancestor. Mirrors a layer-tree click. */
|
|
5542
5681
|
onCrumbSelect(node) {
|
|
@@ -5933,6 +6072,12 @@ class BuilderComponent {
|
|
|
5933
6072
|
// array would make the OnPush input look changed on every change-detection pass.
|
|
5934
6073
|
this.selectedPath = nodeAncestorPathInEither(this.layout, this.globalElements, node) ?? [node];
|
|
5935
6074
|
this.panelEventService.emit(PanelEventTypes.ELEMENT_SELECT, { node, componentRef, symbolAncestor, repeaterAncestor, parentDisplay });
|
|
6075
|
+
this.refreshBreakpointCounts();
|
|
6076
|
+
}
|
|
6077
|
+
refreshBreakpointCounts() {
|
|
6078
|
+
this.breakpointCounts = this.selectedItem
|
|
6079
|
+
? nodeBreakpointCounts(this.selectedItem)
|
|
6080
|
+
: treeBreakpointCounts(this.layout, this.globalElements);
|
|
5936
6081
|
}
|
|
5937
6082
|
/** Read a node's current `display` value. The style panel mutates `styleTraits` in place at edit
|
|
5938
6083
|
* time, so that is the live source of truth; fall back to a preset's `styleOverrides` map, then
|
|
@@ -5945,6 +6090,11 @@ class BuilderComponent {
|
|
|
5945
6090
|
return node.styleOverrides?.['display'] ?? 'block';
|
|
5946
6091
|
}
|
|
5947
6092
|
handlePanelEvents(panelEvent) {
|
|
6093
|
+
// Every style or structural edit — including a breakpoint override — emits LAYOUT_CHANGED.
|
|
6094
|
+
if (panelEvent.type === PanelEventTypes.LAYOUT_CHANGED) {
|
|
6095
|
+
this.refreshBreakpointCounts();
|
|
6096
|
+
return;
|
|
6097
|
+
}
|
|
5948
6098
|
if (panelEvent.type === PanelEventTypes.PANEL_CLOSE) {
|
|
5949
6099
|
this.isPanelOpen = false;
|
|
5950
6100
|
return;
|
|
@@ -5953,12 +6103,12 @@ class BuilderComponent {
|
|
|
5953
6103
|
this.isPanelOpen = true;
|
|
5954
6104
|
}
|
|
5955
6105
|
}
|
|
5956
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5957
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: BuilderComponent, isStandalone: false, selector: "app-builder", inputs: { layout: "layout", dataSources: "dataSources", orgId: "orgId", routeParams: "routeParams", pageName: "pageName", isSaving: "isSaving", pageStatus: "pageStatus", pageSettings: "pageSettings", globalElements: "globalElements", canUndo: "canUndo", canRedo: "canRedo", moveableMode: "moveableMode" }, outputs: { save: "save", undo: "undo", redo: "redo", back: "back", preview: "preview", publishToggle: "publishToggle", pageSettingsChange: "pageSettingsChange", applyAnimationToAll: "applyAnimationToAll", saveBlock: "saveBlock", globalElementsChange: "globalElementsChange" }, viewQueries: [{ propertyName: "previewCanvas", first: true, predicate: ["previewCanvas"], descendants: true }, { propertyName: "previewScrollRef", first: true, predicate: ["previewScroll"], descendants: true }, { propertyName: "lenisContentRef", first: true, predicate: ["lenisContent"], descendants: true }, { propertyName: "globalOverlayRef", first: true, predicate: ["globalOverlay"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"builder\">\n <header class=\"builder-header\">\n <div class=\"sidebar-switcher\">\n <button (click)=\"activeSidebar = 'pages'\" [class.active]=\"activeSidebar === 'pages'\" title=\"Pages\" aria-label=\"Pages\">\n <i class=\"ph-thin ph-browsers\"></i>\n </button>\n <button (click)=\"activeSidebar = 'components'\" [class.active]=\"activeSidebar === 'components'\" title=\"Components\" aria-label=\"Components\">\n <i class=\"ph-thin ph-cube\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tree'\" [class.active]=\"activeSidebar === 'tree'\" title=\"Layers\" aria-label=\"Layers\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tokens'\" [class.active]=\"activeSidebar === 'tokens'\" title=\"Design Tokens\" aria-label=\"Design Tokens\">\n <i class=\"ph-thin ph-circles-three\"></i>\n </button>\n </div>\n\n <app-toolbar\n [activeMode]=\"activeMode\"\n [activeDevice]=\"activeDevice\"\n [activeZoom]=\"activeZoom\"\n [activeScreenWidth]=\"activeScreenWidth\"\n [isSaving]=\"isSaving\"\n [pageStatus]=\"pageStatus\"\n [canUndo]=\"canUndo\"\n [canRedo]=\"canRedo\"\n (modeChange)=\"handleToolbarModeChange($event)\"\n (deviceChange)=\"handleToolbarDeviceChange($event)\"\n (zoomChange)=\"handleToolbarZoomChange($event)\"\n (screenWidthChange)=\"handleToolbarScreenWidthChange($event)\"\n (save)=\"save.emit()\"\n (preview)=\"preview.emit()\"\n (publishToggle)=\"publishToggle.emit()\"\n (undo)=\"undo.emit()\"\n (redo)=\"redo.emit()\">\n </app-toolbar>\n\n <div class=\"panel-switcher\">\n <button (click)=\"selectPanel(panelTypes.BINDINGS)\" [class.active]=\"activePanel === panelTypes.BINDINGS\" title=\"Bindings\">\n <i class=\"ph-thin ph-plugs-connected\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.STYLES)\" [class.active]=\"activePanel === panelTypes.STYLES\" title=\"Styles\">\n <i class=\"ph-thin ph-paint-brush\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.PAGE)\" [class.active]=\"activePanel === panelTypes.PAGE\" title=\"Page settings\" aria-label=\"Page settings\">\n <i class=\"ph-thin ph-gear-six\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.INTERACTIONS)\" [class.active]=\"activePanel === panelTypes.INTERACTIONS\" title=\"Interactions\">\n <i class=\"ph-thin ph-lightning\"></i>\n </button>\n </div> \n </header>\n\n <app-breadcrumb-bar\n [path]=\"selectedPath\"\n (nodeSelect)=\"onCrumbSelect($event)\"\n (nodePeek)=\"onCrumbPeek($event)\">\n </app-breadcrumb-bar>\n\n <div class=\"builder-main\" [class.panel-open]=\"isPanelOpen\">\n <aside class=\"sidebar\">\n <div *ngIf=\"activeSidebar === 'pages'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderPages]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'components'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderComponents]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'tokens'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderTokens]\"></ng-content>\n </div>\n <app-layer-tree *ngIf=\"activeSidebar === 'tree'\"\n [layout]=\"layout\"\n [globalElements]=\"globalElements\"\n (nodeSelect)=\"onTreeNodeSelect($event)\"\n (nodeAction)=\"onTreeNodeAction($event)\"\n (nodeMove)=\"onTreeNodeMove()\"></app-layer-tree>\n </aside>\n\n <main #previewCanvas class=\"preview\"\n [class.grab-mode]=\"activeMode === builderModes.Pan\"\n [class.grabbing]=\"isPanning\"\n (click)=\"handleCanvasClick()\"\n (mousedown)=\"onBoardMouseDown($event)\"\n (mousemove)=\"onBoardMouseMove($event)\"\n (mouseup)=\"onBoardMouseUp()\"\n (mouseleave)=\"onBoardMouseUp()\">\n <app-overlay (toolbarAction)=\"onToolbarAction($event)\"></app-overlay>\n\n <!-- Custom Lenis scrollbar \u2014 lives in .preview (not .preview-scroll) so it\n stays in the right gutter and never overlaps the canvas at large widths.\n No translateY counteract needed since it isn't inside the Lenis wrapper. -->\n <div class=\"canvas-scrollbar\"\n [class.visible]=\"isScrollbarVisible\">\n <div class=\"canvas-scrollbar-thumb\"\n [style.height.px]=\"scrollThumbHeight\"\n [style.top.px]=\"scrollThumbTop\">\n </div>\n </div>\n\n <!-- Global elements overlay \u2014 outside Lenis so position:fixed children\n stay pinned to the canvas viewport rather than scrolling with content.\n Shares viewportTransform so elements scale correctly at any zoom level.\n Height matches viewportHeight so position:fixed + inset:0 fills the\n simulated viewport correctly (CSS calc(100%) would give the wrong\n containing-block height and break full-screen fixed overlays). -->\n <div *ngIf=\"globalElements.length\"\n #globalOverlay\n class=\"global-elements-overlay\"\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n <ng-container *ngFor=\"let item of globalElementsBefore\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n <ng-container *ngFor=\"let item of globalElementsAfter\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n </div>\n\n <div class=\"preview-scroll\"\n #previewScroll\n [style.width.px]=\"viewportScaledWidth\"\n [class.pan-mode]=\"activeMode === builderModes.Pan\">\n\n <!-- Lenis content proxy: height = realContentHeight \u00D7 scale.\n Lenis scrolls against this value so scroll range is always in\n visual px \u2014 correct at any zoom level. -->\n <div class=\"preview-lenis-content\" #lenisContent\n [style.height.px]=\"scaledContentHeight\">\n\n <iox-page-component\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n\n <div class=\"canvas-viewport\"\n id=\"canvas-preview\"\n [style.min-height.px]=\"canvasMinHeight\">\n\n <!-- WRAPPER COLLAPSE (task 9c): top-level nodes render DIRECTLY into the\n canvas viewport \u2014 no .preview-node wrapper; iox-outer + drag move to the\n host (RenderDirective, via ioxDragSourceId). -->\n <ng-container *ngFor=\"let item of layout\"\n [ioxRender]=\"item\"\n [ioxDragSourceId]=\"'canvas-preview'\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </div>\n </iox-page-component>\n </div>\n </div>\n </main>\n\n <ng-content select=\"[builderPanel]\"></ng-content>\n </div>\n\n <!-- Save as Reusable Block dialog -->\n @if (showSaveBlockDialog) {\n <div class=\"save-block-backdrop\" (click)=\"cancelSaveBlock()\"></div>\n <div class=\"save-block-dialog\" (click)=\"$event.stopPropagation()\">\n <h4 class=\"save-block-title\">Save as Reusable Block</h4>\n <input class=\"save-block-input\"\n type=\"text\"\n placeholder=\"Block name...\"\n [(ngModel)]=\"saveBlockName\"\n (keydown.enter)=\"confirmSaveBlock()\"\n (keydown.escape)=\"cancelSaveBlock()\"\n autofocus>\n <div class=\"save-block-actions\">\n <p-button size=\"small\" severity=\"secondary\" label=\"Cancel\" (click)=\"cancelSaveBlock()\"></p-button>\n <p-button size=\"small\" label=\"Save\" [disabled]=\"!saveBlockName.trim()\" (click)=\"confirmSaveBlock()\"></p-button>\n </div>\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex:1;min-height:0;overflow:hidden}.builder{display:flex;flex-direction:column;direction:ltr;width:100%;height:100%;min-height:0;border-radius:0;overflow:hidden;position:relative}.builder .builder-header{background:var(--p-surface-0);padding:.375rem .75rem;border-bottom:1px solid var(--p-surface-200);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:.5rem;flex-shrink:0}.builder .builder-header .header-back{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;cursor:pointer;color:var(--p-text-muted-color);font-size:16px;transition:background .15s ease-out;margin-inline-end:.25rem}.builder .builder-header .header-back:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .builder-header .header-page-name{flex:1;text-align:center;font-size:.8rem;font-weight:500;color:var(--p-text-muted-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-inline:1rem}.builder .sidebar-switcher,.builder .panel-switcher{display:flex;gap:.25rem}.builder .sidebar-switcher button,.builder .panel-switcher button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.builder .sidebar-switcher button i,.builder .panel-switcher button i{pointer-events:none}.builder .sidebar-switcher button:hover,.builder .panel-switcher button:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .sidebar-switcher button.active,.builder .panel-switcher button.active{background:#cb9090;color:#fff}.builder .panel-switcher{justify-self:end}.builder .builder-main{display:flex;flex:1 1 0;min-height:0;position:relative;overflow:hidden}.builder .sidebar{width:260px;min-width:260px;background:var(--p-surface-0);border-inline-end:1px solid var(--p-surface-200);overflow-y:auto;overflow-x:hidden;flex-shrink:0}.builder .preview{flex:1 1 0;min-width:0;min-height:0;position:relative;overflow:hidden}.builder .preview.grab-mode{cursor:grab}.builder .preview.grab-mode iox-page-component{pointer-events:none}.builder .preview.grabbing{cursor:grabbing}.builder .canvas-scrollbar{position:absolute;right:4px;top:20px;bottom:20px;width:6px;z-index:20;opacity:0;transition:opacity .2s ease;pointer-events:none}.builder .canvas-scrollbar.visible{opacity:1}.builder .canvas-scrollbar-thumb{position:absolute;left:0;width:100%;background:#00000059;border-radius:3px;transition:top .05s linear}.builder .preview-scroll{position:absolute;inset:20px auto;inset-inline-start:50%;transform:translate(-50%);max-width:calc(100% - 40px);height:calc(100% - 40px);overflow:hidden}.builder .preview-lenis-content{position:relative;width:100%;overflow:hidden;contain:paint}.builder iox-page-component{position:absolute!important;top:0;bottom:auto!important;right:auto!important;left:50%;transform-origin:top center;overflow:visible!important;box-shadow:0 1px 4px #00000014,0 4px 16px #0000000a;transition:width .25s ease,transform .25s ease}.builder iox-page-component ::ng-deep .iox-page-wrapper{height:auto!important;overflow:visible!important}.builder #canvas-preview{background:#fff}.builder .global-elements-overlay{position:absolute;top:20px;left:50%;transform-origin:top center;pointer-events:none;z-index:9;overflow:hidden}.builder .global-elements-overlay ::ng-deep>*{pointer-events:auto}.builder .preview-node.is-selected{cursor:grab}.builder .empty-state{min-height:240px;border:1px dashed var(--p-surface-200);border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--p-text-muted-color);text-align:center;padding:1rem}.save-block-backdrop{position:fixed;inset:0;z-index:1000;background:#00000040}.save-block-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#fff;border-radius:8px;box-shadow:0 8px 32px #0000002e;padding:24px;width:320px}.save-block-dialog .save-block-title{margin:0 0 16px;font-size:14px;font-weight:600;color:var(--p-text-color, #333)}.save-block-dialog .save-block-input{width:100%;padding:8px 10px;border:1px solid var(--p-surface-300, #d1d5db);border-radius:6px;font-size:13px;outline:none;box-sizing:border-box;margin-bottom:16px}.save-block-dialog .save-block-input:focus{border-color:#cb9090;box-shadow:0 0 0 2px #cb909033}.save-block-dialog .save-block-actions{display:flex;justify-content:flex-end;gap:8px}::ng-deep .moveable-control-box.iox-moveable-silent{z-index:1000!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-line,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation-line{display:none!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-control{display:block!important;width:10px!important;height:10px!important;margin-top:-5px!important;margin-left:-5px!important;background:#fff!important;border:1.5px solid #cb9090!important;border-radius:2px!important;box-shadow:0 1px 3px #0003!important}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i15.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i16.IoxPageComponent, selector: "iox-page-component", inputs: ["class"], outputs: ["scrollEvent"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "component", type: OverlayComponent, selector: "app-overlay", outputs: ["toolbarAction"] }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["activeMode", "activeDevice", "activeZoom", "activeScreenWidth", "canUndo", "canRedo", "isSaving", "pageStatus"], outputs: ["modeChange", "deviceChange", "zoomChange", "screenWidthChange", "undo", "redo", "save", "preview", "publishToggle"] }, { kind: "component", type: LayerTreeComponent, selector: "app-layer-tree", inputs: ["layout", "globalElements"], outputs: ["nodeSelect", "nodeAction", "nodeMove"] }, { kind: "component", type: BreadcrumbBarComponent, selector: "app-breadcrumb-bar", inputs: ["path"], outputs: ["nodeSelect", "nodePeek"] }] }); }
|
|
6106
|
+
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: InteractionEngineService }, { token: InteractionPresetRegistryService }, { token: BuilderClipboardService }, { token: SymbolRegistryService }, { token: i0.ChangeDetectorRef }, { token: i0.ApplicationRef }, { token: MoveableCanvasService }, { token: SelectoCanvasService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6107
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: BuilderComponent, isStandalone: false, selector: "app-builder", inputs: { layout: "layout", dataSources: "dataSources", orgId: "orgId", routeParams: "routeParams", pageName: "pageName", isSaving: "isSaving", pageStatus: "pageStatus", pageSettings: "pageSettings", globalElements: "globalElements", canUndo: "canUndo", canRedo: "canRedo", moveableMode: "moveableMode" }, outputs: { save: "save", undo: "undo", redo: "redo", back: "back", preview: "preview", publishToggle: "publishToggle", pageSettingsChange: "pageSettingsChange", applyAnimationToAll: "applyAnimationToAll", saveBlock: "saveBlock", globalElementsChange: "globalElementsChange" }, viewQueries: [{ propertyName: "previewCanvas", first: true, predicate: ["previewCanvas"], descendants: true }, { propertyName: "previewScrollRef", first: true, predicate: ["previewScroll"], descendants: true }, { propertyName: "lenisContentRef", first: true, predicate: ["lenisContent"], descendants: true }, { propertyName: "globalOverlayRef", first: true, predicate: ["globalOverlay"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"builder\">\n <header class=\"builder-header\">\n <div class=\"sidebar-switcher\">\n <button (click)=\"activeSidebar = 'pages'\" [class.active]=\"activeSidebar === 'pages'\" title=\"Pages\" aria-label=\"Pages\">\n <i class=\"ph-thin ph-browsers\"></i>\n </button>\n <button (click)=\"activeSidebar = 'components'\" [class.active]=\"activeSidebar === 'components'\" title=\"Components\" aria-label=\"Components\">\n <i class=\"ph-thin ph-cube\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tree'\" [class.active]=\"activeSidebar === 'tree'\" title=\"Layers\" aria-label=\"Layers\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tokens'\" [class.active]=\"activeSidebar === 'tokens'\" title=\"Design Tokens\" aria-label=\"Design Tokens\">\n <i class=\"ph-thin ph-circles-three\"></i>\n </button>\n </div>\n\n <app-toolbar\n [activeMode]=\"activeMode\"\n [activeBreakpoint]=\"activeBreakpoint\"\n [breakpointCounts]=\"breakpointCounts\"\n [activeZoom]=\"activeZoom\"\n [activeScreenWidth]=\"activeScreenWidth\"\n [isSaving]=\"isSaving\"\n [pageStatus]=\"pageStatus\"\n [canUndo]=\"canUndo\"\n [canRedo]=\"canRedo\"\n (modeChange)=\"handleToolbarModeChange($event)\"\n (breakpointChange)=\"handleToolbarBreakpointChange($event)\"\n (zoomChange)=\"handleToolbarZoomChange($event)\"\n (screenWidthChange)=\"handleToolbarScreenWidthChange($event)\"\n (save)=\"save.emit()\"\n (preview)=\"preview.emit()\"\n (publishToggle)=\"publishToggle.emit()\"\n (undo)=\"undo.emit()\"\n (redo)=\"redo.emit()\">\n </app-toolbar>\n\n <div class=\"panel-switcher\">\n <button (click)=\"selectPanel(panelTypes.BINDINGS)\" [class.active]=\"activePanel === panelTypes.BINDINGS\" title=\"Bindings\">\n <i class=\"ph-thin ph-plugs-connected\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.STYLES)\" [class.active]=\"activePanel === panelTypes.STYLES\" title=\"Styles\">\n <i class=\"ph-thin ph-paint-brush\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.PAGE)\" [class.active]=\"activePanel === panelTypes.PAGE\" title=\"Page settings\" aria-label=\"Page settings\">\n <i class=\"ph-thin ph-gear-six\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.INTERACTIONS)\" [class.active]=\"activePanel === panelTypes.INTERACTIONS\" title=\"Interactions\">\n <i class=\"ph-thin ph-lightning\"></i>\n </button>\n </div> \n </header>\n\n <app-breadcrumb-bar\n [path]=\"selectedPath\"\n (nodeSelect)=\"onCrumbSelect($event)\"\n (nodePeek)=\"onCrumbPeek($event)\">\n </app-breadcrumb-bar>\n\n <div class=\"builder-main\" [class.panel-open]=\"isPanelOpen\">\n <aside class=\"sidebar\">\n <div *ngIf=\"activeSidebar === 'pages'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderPages]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'components'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderComponents]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'tokens'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderTokens]\"></ng-content>\n </div>\n <app-layer-tree *ngIf=\"activeSidebar === 'tree'\"\n [layout]=\"layout\"\n [globalElements]=\"globalElements\"\n (nodeSelect)=\"onTreeNodeSelect($event)\"\n (nodeAction)=\"onTreeNodeAction($event)\"\n (nodeMove)=\"onTreeNodeMove()\"></app-layer-tree>\n </aside>\n\n <main #previewCanvas class=\"preview\"\n [class.grab-mode]=\"activeMode === builderModes.Pan\"\n [class.grabbing]=\"isPanning\"\n (click)=\"handleCanvasClick()\"\n (mousedown)=\"onBoardMouseDown($event)\"\n (mousemove)=\"onBoardMouseMove($event)\"\n (mouseup)=\"onBoardMouseUp()\"\n (mouseleave)=\"onBoardMouseUp()\">\n <app-overlay (toolbarAction)=\"onToolbarAction($event)\"></app-overlay>\n\n <!-- Custom Lenis scrollbar \u2014 lives in .preview (not .preview-scroll) so it\n stays in the right gutter and never overlaps the canvas at large widths.\n No translateY counteract needed since it isn't inside the Lenis wrapper. -->\n <div class=\"canvas-scrollbar\"\n [class.visible]=\"isScrollbarVisible\">\n <div class=\"canvas-scrollbar-thumb\"\n [style.height.px]=\"scrollThumbHeight\"\n [style.top.px]=\"scrollThumbTop\">\n </div>\n </div>\n\n <!-- Global elements overlay \u2014 outside Lenis so position:fixed children\n stay pinned to the canvas viewport rather than scrolling with content.\n Shares viewportTransform so elements scale correctly at any zoom level.\n Height matches viewportHeight so position:fixed + inset:0 fills the\n simulated viewport correctly (CSS calc(100%) would give the wrong\n containing-block height and break full-screen fixed overlays). -->\n <div *ngIf=\"globalElements.length\"\n #globalOverlay\n class=\"global-elements-overlay\"\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n <ng-container *ngFor=\"let item of globalElementsBefore\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n <ng-container *ngFor=\"let item of globalElementsAfter\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n </div>\n\n <div class=\"preview-scroll\"\n #previewScroll\n [style.width.px]=\"viewportScaledWidth\"\n [class.pan-mode]=\"activeMode === builderModes.Pan\">\n\n <!-- Lenis content proxy: height = realContentHeight \u00D7 scale.\n Lenis scrolls against this value so scroll range is always in\n visual px \u2014 correct at any zoom level. -->\n <div class=\"preview-lenis-content\" #lenisContent\n [style.height.px]=\"scaledContentHeight\">\n\n <iox-page-component\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n\n <div class=\"canvas-viewport\"\n id=\"canvas-preview\"\n [style.min-height.px]=\"canvasMinHeight\">\n\n <!-- WRAPPER COLLAPSE (task 9c): top-level nodes render DIRECTLY into the\n canvas viewport \u2014 no .preview-node wrapper; iox-outer + drag move to the\n host (RenderDirective, via ioxDragSourceId). -->\n <ng-container *ngFor=\"let item of layout\"\n [ioxRender]=\"item\"\n [ioxDragSourceId]=\"'canvas-preview'\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </div>\n </iox-page-component>\n </div>\n </div>\n </main>\n\n <ng-content select=\"[builderPanel]\"></ng-content>\n </div>\n\n <!-- Save as Reusable Block dialog -->\n @if (showSaveBlockDialog) {\n <div class=\"save-block-backdrop\" (click)=\"cancelSaveBlock()\"></div>\n <div class=\"save-block-dialog\" (click)=\"$event.stopPropagation()\">\n <h4 class=\"save-block-title\">Save as Reusable Block</h4>\n <input class=\"save-block-input\"\n type=\"text\"\n placeholder=\"Block name...\"\n [(ngModel)]=\"saveBlockName\"\n (keydown.enter)=\"confirmSaveBlock()\"\n (keydown.escape)=\"cancelSaveBlock()\"\n autofocus>\n <div class=\"save-block-actions\">\n <p-button size=\"small\" severity=\"secondary\" label=\"Cancel\" (click)=\"cancelSaveBlock()\"></p-button>\n <p-button size=\"small\" label=\"Save\" [disabled]=\"!saveBlockName.trim()\" (click)=\"confirmSaveBlock()\"></p-button>\n </div>\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex:1;min-height:0;overflow:hidden}.builder{display:flex;flex-direction:column;direction:ltr;width:100%;height:100%;min-height:0;border-radius:0;overflow:hidden;position:relative}.builder .builder-header{background:var(--p-surface-0);padding:.375rem .75rem;border-bottom:1px solid var(--p-surface-200);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:.5rem;flex-shrink:0}.builder .builder-header .header-back{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;cursor:pointer;color:var(--p-text-muted-color);font-size:16px;transition:background .15s ease-out;margin-inline-end:.25rem}.builder .builder-header .header-back:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .builder-header .header-page-name{flex:1;text-align:center;font-size:.8rem;font-weight:500;color:var(--p-text-muted-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-inline:1rem}.builder .sidebar-switcher,.builder .panel-switcher{display:flex;gap:.25rem}.builder .sidebar-switcher button,.builder .panel-switcher button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.builder .sidebar-switcher button i,.builder .panel-switcher button i{pointer-events:none}.builder .sidebar-switcher button:hover,.builder .panel-switcher button:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .sidebar-switcher button.active,.builder .panel-switcher button.active{background:#cb9090;color:#fff}.builder .panel-switcher{justify-self:end}.builder .builder-main{display:flex;flex:1 1 0;min-height:0;position:relative;overflow:hidden}.builder .sidebar{width:260px;min-width:260px;background:var(--p-surface-0);border-inline-end:1px solid var(--p-surface-200);overflow-y:auto;overflow-x:hidden;flex-shrink:0}.builder .preview{flex:1 1 0;min-width:0;min-height:0;position:relative;overflow:hidden}.builder .preview.grab-mode{cursor:grab}.builder .preview.grab-mode iox-page-component{pointer-events:none}.builder .preview.grabbing{cursor:grabbing}.builder .canvas-scrollbar{position:absolute;right:4px;top:20px;bottom:20px;width:6px;z-index:20;opacity:0;transition:opacity .2s ease;pointer-events:none}.builder .canvas-scrollbar.visible{opacity:1}.builder .canvas-scrollbar-thumb{position:absolute;left:0;width:100%;background:#00000059;border-radius:3px;transition:top .05s linear}.builder .preview-scroll{position:absolute;inset:20px auto;inset-inline-start:50%;transform:translate(-50%);max-width:calc(100% - 40px);height:calc(100% - 40px);overflow:hidden}.builder .preview-lenis-content{position:relative;width:100%;overflow:hidden;contain:paint}.builder iox-page-component{position:absolute!important;top:0;bottom:auto!important;right:auto!important;left:50%;transform-origin:top center;overflow:visible!important;container:iox-canvas/inline-size;box-shadow:0 1px 4px #00000014,0 4px 16px #0000000a;transition:width .25s ease,transform .25s ease}.builder iox-page-component ::ng-deep .iox-page-wrapper{height:auto!important;overflow:visible!important}.builder #canvas-preview{background:#fff}.builder .global-elements-overlay{position:absolute;top:20px;left:50%;transform-origin:top center;pointer-events:none;z-index:9;overflow:hidden;container:iox-canvas/inline-size}.builder .global-elements-overlay ::ng-deep>*{pointer-events:auto}.builder .preview-node.is-selected{cursor:grab}.builder .empty-state{min-height:240px;border:1px dashed var(--p-surface-200);border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--p-text-muted-color);text-align:center;padding:1rem}.save-block-backdrop{position:fixed;inset:0;z-index:1000;background:#00000040}.save-block-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#fff;border-radius:8px;box-shadow:0 8px 32px #0000002e;padding:24px;width:320px}.save-block-dialog .save-block-title{margin:0 0 16px;font-size:14px;font-weight:600;color:var(--p-text-color, #333)}.save-block-dialog .save-block-input{width:100%;padding:8px 10px;border:1px solid var(--p-surface-300, #d1d5db);border-radius:6px;font-size:13px;outline:none;box-sizing:border-box;margin-bottom:16px}.save-block-dialog .save-block-input:focus{border-color:#cb9090;box-shadow:0 0 0 2px #cb909033}.save-block-dialog .save-block-actions{display:flex;justify-content:flex-end;gap:8px}::ng-deep .moveable-control-box.iox-moveable-silent{z-index:1000!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-line,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation-line{display:none!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-control{display:block!important;width:10px!important;height:10px!important;margin-top:-5px!important;margin-left:-5px!important;background:#fff!important;border:1.5px solid #cb9090!important;border-radius:2px!important;box-shadow:0 1px 3px #0003!important}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i15.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i16.IoxPageComponent, selector: "iox-page-component", inputs: ["class"], outputs: ["scrollEvent"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "component", type: OverlayComponent, selector: "app-overlay", outputs: ["toolbarAction"] }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["activeMode", "activeBreakpoint", "breakpointCounts", "activeZoom", "activeScreenWidth", "canUndo", "canRedo", "isSaving", "pageStatus"], outputs: ["modeChange", "breakpointChange", "zoomChange", "screenWidthChange", "undo", "redo", "save", "preview", "publishToggle"] }, { kind: "component", type: LayerTreeComponent, selector: "app-layer-tree", inputs: ["layout", "globalElements"], outputs: ["nodeSelect", "nodeAction", "nodeMove"] }, { kind: "component", type: BreadcrumbBarComponent, selector: "app-breadcrumb-bar", inputs: ["path"], outputs: ["nodeSelect", "nodePeek"] }] }); }
|
|
5958
6108
|
}
|
|
5959
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6109
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderComponent, decorators: [{
|
|
5960
6110
|
type: Component,
|
|
5961
|
-
args: [{ selector: 'app-builder', standalone: false, template: "<div class=\"builder\">\n <header class=\"builder-header\">\n <div class=\"sidebar-switcher\">\n <button (click)=\"activeSidebar = 'pages'\" [class.active]=\"activeSidebar === 'pages'\" title=\"Pages\" aria-label=\"Pages\">\n <i class=\"ph-thin ph-browsers\"></i>\n </button>\n <button (click)=\"activeSidebar = 'components'\" [class.active]=\"activeSidebar === 'components'\" title=\"Components\" aria-label=\"Components\">\n <i class=\"ph-thin ph-cube\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tree'\" [class.active]=\"activeSidebar === 'tree'\" title=\"Layers\" aria-label=\"Layers\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tokens'\" [class.active]=\"activeSidebar === 'tokens'\" title=\"Design Tokens\" aria-label=\"Design Tokens\">\n <i class=\"ph-thin ph-circles-three\"></i>\n </button>\n </div>\n\n <app-toolbar\n [activeMode]=\"activeMode\"\n [activeDevice]=\"activeDevice\"\n [activeZoom]=\"activeZoom\"\n [activeScreenWidth]=\"activeScreenWidth\"\n [isSaving]=\"isSaving\"\n [pageStatus]=\"pageStatus\"\n [canUndo]=\"canUndo\"\n [canRedo]=\"canRedo\"\n (modeChange)=\"handleToolbarModeChange($event)\"\n (deviceChange)=\"handleToolbarDeviceChange($event)\"\n (zoomChange)=\"handleToolbarZoomChange($event)\"\n (screenWidthChange)=\"handleToolbarScreenWidthChange($event)\"\n (save)=\"save.emit()\"\n (preview)=\"preview.emit()\"\n (publishToggle)=\"publishToggle.emit()\"\n (undo)=\"undo.emit()\"\n (redo)=\"redo.emit()\">\n </app-toolbar>\n\n <div class=\"panel-switcher\">\n <button (click)=\"selectPanel(panelTypes.BINDINGS)\" [class.active]=\"activePanel === panelTypes.BINDINGS\" title=\"Bindings\">\n <i class=\"ph-thin ph-plugs-connected\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.STYLES)\" [class.active]=\"activePanel === panelTypes.STYLES\" title=\"Styles\">\n <i class=\"ph-thin ph-paint-brush\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.PAGE)\" [class.active]=\"activePanel === panelTypes.PAGE\" title=\"Page settings\" aria-label=\"Page settings\">\n <i class=\"ph-thin ph-gear-six\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.INTERACTIONS)\" [class.active]=\"activePanel === panelTypes.INTERACTIONS\" title=\"Interactions\">\n <i class=\"ph-thin ph-lightning\"></i>\n </button>\n </div> \n </header>\n\n <app-breadcrumb-bar\n [path]=\"selectedPath\"\n (nodeSelect)=\"onCrumbSelect($event)\"\n (nodePeek)=\"onCrumbPeek($event)\">\n </app-breadcrumb-bar>\n\n <div class=\"builder-main\" [class.panel-open]=\"isPanelOpen\">\n <aside class=\"sidebar\">\n <div *ngIf=\"activeSidebar === 'pages'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderPages]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'components'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderComponents]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'tokens'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderTokens]\"></ng-content>\n </div>\n <app-layer-tree *ngIf=\"activeSidebar === 'tree'\"\n [layout]=\"layout\"\n [globalElements]=\"globalElements\"\n (nodeSelect)=\"onTreeNodeSelect($event)\"\n (nodeAction)=\"onTreeNodeAction($event)\"\n (nodeMove)=\"onTreeNodeMove()\"></app-layer-tree>\n </aside>\n\n <main #previewCanvas class=\"preview\"\n [class.grab-mode]=\"activeMode === builderModes.Pan\"\n [class.grabbing]=\"isPanning\"\n (click)=\"handleCanvasClick()\"\n (mousedown)=\"onBoardMouseDown($event)\"\n (mousemove)=\"onBoardMouseMove($event)\"\n (mouseup)=\"onBoardMouseUp()\"\n (mouseleave)=\"onBoardMouseUp()\">\n <app-overlay (toolbarAction)=\"onToolbarAction($event)\"></app-overlay>\n\n <!-- Custom Lenis scrollbar \u2014 lives in .preview (not .preview-scroll) so it\n stays in the right gutter and never overlaps the canvas at large widths.\n No translateY counteract needed since it isn't inside the Lenis wrapper. -->\n <div class=\"canvas-scrollbar\"\n [class.visible]=\"isScrollbarVisible\">\n <div class=\"canvas-scrollbar-thumb\"\n [style.height.px]=\"scrollThumbHeight\"\n [style.top.px]=\"scrollThumbTop\">\n </div>\n </div>\n\n <!-- Global elements overlay \u2014 outside Lenis so position:fixed children\n stay pinned to the canvas viewport rather than scrolling with content.\n Shares viewportTransform so elements scale correctly at any zoom level.\n Height matches viewportHeight so position:fixed + inset:0 fills the\n simulated viewport correctly (CSS calc(100%) would give the wrong\n containing-block height and break full-screen fixed overlays). -->\n <div *ngIf=\"globalElements.length\"\n #globalOverlay\n class=\"global-elements-overlay\"\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n <ng-container *ngFor=\"let item of globalElementsBefore\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n <ng-container *ngFor=\"let item of globalElementsAfter\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n </div>\n\n <div class=\"preview-scroll\"\n #previewScroll\n [style.width.px]=\"viewportScaledWidth\"\n [class.pan-mode]=\"activeMode === builderModes.Pan\">\n\n <!-- Lenis content proxy: height = realContentHeight \u00D7 scale.\n Lenis scrolls against this value so scroll range is always in\n visual px \u2014 correct at any zoom level. -->\n <div class=\"preview-lenis-content\" #lenisContent\n [style.height.px]=\"scaledContentHeight\">\n\n <iox-page-component\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n\n <div class=\"canvas-viewport\"\n id=\"canvas-preview\"\n [style.min-height.px]=\"canvasMinHeight\">\n\n <!-- WRAPPER COLLAPSE (task 9c): top-level nodes render DIRECTLY into the\n canvas viewport \u2014 no .preview-node wrapper; iox-outer + drag move to the\n host (RenderDirective, via ioxDragSourceId). -->\n <ng-container *ngFor=\"let item of layout\"\n [ioxRender]=\"item\"\n [ioxDragSourceId]=\"'canvas-preview'\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </div>\n </iox-page-component>\n </div>\n </div>\n </main>\n\n <ng-content select=\"[builderPanel]\"></ng-content>\n </div>\n\n <!-- Save as Reusable Block dialog -->\n @if (showSaveBlockDialog) {\n <div class=\"save-block-backdrop\" (click)=\"cancelSaveBlock()\"></div>\n <div class=\"save-block-dialog\" (click)=\"$event.stopPropagation()\">\n <h4 class=\"save-block-title\">Save as Reusable Block</h4>\n <input class=\"save-block-input\"\n type=\"text\"\n placeholder=\"Block name...\"\n [(ngModel)]=\"saveBlockName\"\n (keydown.enter)=\"confirmSaveBlock()\"\n (keydown.escape)=\"cancelSaveBlock()\"\n autofocus>\n <div class=\"save-block-actions\">\n <p-button size=\"small\" severity=\"secondary\" label=\"Cancel\" (click)=\"cancelSaveBlock()\"></p-button>\n <p-button size=\"small\" label=\"Save\" [disabled]=\"!saveBlockName.trim()\" (click)=\"confirmSaveBlock()\"></p-button>\n </div>\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex:1;min-height:0;overflow:hidden}.builder{display:flex;flex-direction:column;direction:ltr;width:100%;height:100%;min-height:0;border-radius:0;overflow:hidden;position:relative}.builder .builder-header{background:var(--p-surface-0);padding:.375rem .75rem;border-bottom:1px solid var(--p-surface-200);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:.5rem;flex-shrink:0}.builder .builder-header .header-back{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;cursor:pointer;color:var(--p-text-muted-color);font-size:16px;transition:background .15s ease-out;margin-inline-end:.25rem}.builder .builder-header .header-back:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .builder-header .header-page-name{flex:1;text-align:center;font-size:.8rem;font-weight:500;color:var(--p-text-muted-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-inline:1rem}.builder .sidebar-switcher,.builder .panel-switcher{display:flex;gap:.25rem}.builder .sidebar-switcher button,.builder .panel-switcher button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.builder .sidebar-switcher button i,.builder .panel-switcher button i{pointer-events:none}.builder .sidebar-switcher button:hover,.builder .panel-switcher button:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .sidebar-switcher button.active,.builder .panel-switcher button.active{background:#cb9090;color:#fff}.builder .panel-switcher{justify-self:end}.builder .builder-main{display:flex;flex:1 1 0;min-height:0;position:relative;overflow:hidden}.builder .sidebar{width:260px;min-width:260px;background:var(--p-surface-0);border-inline-end:1px solid var(--p-surface-200);overflow-y:auto;overflow-x:hidden;flex-shrink:0}.builder .preview{flex:1 1 0;min-width:0;min-height:0;position:relative;overflow:hidden}.builder .preview.grab-mode{cursor:grab}.builder .preview.grab-mode iox-page-component{pointer-events:none}.builder .preview.grabbing{cursor:grabbing}.builder .canvas-scrollbar{position:absolute;right:4px;top:20px;bottom:20px;width:6px;z-index:20;opacity:0;transition:opacity .2s ease;pointer-events:none}.builder .canvas-scrollbar.visible{opacity:1}.builder .canvas-scrollbar-thumb{position:absolute;left:0;width:100%;background:#00000059;border-radius:3px;transition:top .05s linear}.builder .preview-scroll{position:absolute;inset:20px auto;inset-inline-start:50%;transform:translate(-50%);max-width:calc(100% - 40px);height:calc(100% - 40px);overflow:hidden}.builder .preview-lenis-content{position:relative;width:100%;overflow:hidden;contain:paint}.builder iox-page-component{position:absolute!important;top:0;bottom:auto!important;right:auto!important;left:50%;transform-origin:top center;overflow:visible!important;box-shadow:0 1px 4px #00000014,0 4px 16px #0000000a;transition:width .25s ease,transform .25s ease}.builder iox-page-component ::ng-deep .iox-page-wrapper{height:auto!important;overflow:visible!important}.builder #canvas-preview{background:#fff}.builder .global-elements-overlay{position:absolute;top:20px;left:50%;transform-origin:top center;pointer-events:none;z-index:9;overflow:hidden}.builder .global-elements-overlay ::ng-deep>*{pointer-events:auto}.builder .preview-node.is-selected{cursor:grab}.builder .empty-state{min-height:240px;border:1px dashed var(--p-surface-200);border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--p-text-muted-color);text-align:center;padding:1rem}.save-block-backdrop{position:fixed;inset:0;z-index:1000;background:#00000040}.save-block-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#fff;border-radius:8px;box-shadow:0 8px 32px #0000002e;padding:24px;width:320px}.save-block-dialog .save-block-title{margin:0 0 16px;font-size:14px;font-weight:600;color:var(--p-text-color, #333)}.save-block-dialog .save-block-input{width:100%;padding:8px 10px;border:1px solid var(--p-surface-300, #d1d5db);border-radius:6px;font-size:13px;outline:none;box-sizing:border-box;margin-bottom:16px}.save-block-dialog .save-block-input:focus{border-color:#cb9090;box-shadow:0 0 0 2px #cb909033}.save-block-dialog .save-block-actions{display:flex;justify-content:flex-end;gap:8px}::ng-deep .moveable-control-box.iox-moveable-silent{z-index:1000!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-line,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation-line{display:none!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-control{display:block!important;width:10px!important;height:10px!important;margin-top:-5px!important;margin-left:-5px!important;background:#fff!important;border:1.5px solid #cb9090!important;border-radius:2px!important;box-shadow:0 1px 3px #0003!important}\n"] }]
|
|
6111
|
+
args: [{ selector: 'app-builder', standalone: false, template: "<div class=\"builder\">\n <header class=\"builder-header\">\n <div class=\"sidebar-switcher\">\n <button (click)=\"activeSidebar = 'pages'\" [class.active]=\"activeSidebar === 'pages'\" title=\"Pages\" aria-label=\"Pages\">\n <i class=\"ph-thin ph-browsers\"></i>\n </button>\n <button (click)=\"activeSidebar = 'components'\" [class.active]=\"activeSidebar === 'components'\" title=\"Components\" aria-label=\"Components\">\n <i class=\"ph-thin ph-cube\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tree'\" [class.active]=\"activeSidebar === 'tree'\" title=\"Layers\" aria-label=\"Layers\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n </button>\n <button (click)=\"activeSidebar = 'tokens'\" [class.active]=\"activeSidebar === 'tokens'\" title=\"Design Tokens\" aria-label=\"Design Tokens\">\n <i class=\"ph-thin ph-circles-three\"></i>\n </button>\n </div>\n\n <app-toolbar\n [activeMode]=\"activeMode\"\n [activeBreakpoint]=\"activeBreakpoint\"\n [breakpointCounts]=\"breakpointCounts\"\n [activeZoom]=\"activeZoom\"\n [activeScreenWidth]=\"activeScreenWidth\"\n [isSaving]=\"isSaving\"\n [pageStatus]=\"pageStatus\"\n [canUndo]=\"canUndo\"\n [canRedo]=\"canRedo\"\n (modeChange)=\"handleToolbarModeChange($event)\"\n (breakpointChange)=\"handleToolbarBreakpointChange($event)\"\n (zoomChange)=\"handleToolbarZoomChange($event)\"\n (screenWidthChange)=\"handleToolbarScreenWidthChange($event)\"\n (save)=\"save.emit()\"\n (preview)=\"preview.emit()\"\n (publishToggle)=\"publishToggle.emit()\"\n (undo)=\"undo.emit()\"\n (redo)=\"redo.emit()\">\n </app-toolbar>\n\n <div class=\"panel-switcher\">\n <button (click)=\"selectPanel(panelTypes.BINDINGS)\" [class.active]=\"activePanel === panelTypes.BINDINGS\" title=\"Bindings\">\n <i class=\"ph-thin ph-plugs-connected\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.STYLES)\" [class.active]=\"activePanel === panelTypes.STYLES\" title=\"Styles\">\n <i class=\"ph-thin ph-paint-brush\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.PAGE)\" [class.active]=\"activePanel === panelTypes.PAGE\" title=\"Page settings\" aria-label=\"Page settings\">\n <i class=\"ph-thin ph-gear-six\"></i>\n </button>\n <button (click)=\"selectPanel(panelTypes.INTERACTIONS)\" [class.active]=\"activePanel === panelTypes.INTERACTIONS\" title=\"Interactions\">\n <i class=\"ph-thin ph-lightning\"></i>\n </button>\n </div> \n </header>\n\n <app-breadcrumb-bar\n [path]=\"selectedPath\"\n (nodeSelect)=\"onCrumbSelect($event)\"\n (nodePeek)=\"onCrumbPeek($event)\">\n </app-breadcrumb-bar>\n\n <div class=\"builder-main\" [class.panel-open]=\"isPanelOpen\">\n <aside class=\"sidebar\">\n <div *ngIf=\"activeSidebar === 'pages'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderPages]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'components'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderComponents]\"></ng-content>\n </div>\n <div *ngIf=\"activeSidebar === 'tokens'\" class=\"sidebar-slot\">\n <ng-content select=\"[builderTokens]\"></ng-content>\n </div>\n <app-layer-tree *ngIf=\"activeSidebar === 'tree'\"\n [layout]=\"layout\"\n [globalElements]=\"globalElements\"\n (nodeSelect)=\"onTreeNodeSelect($event)\"\n (nodeAction)=\"onTreeNodeAction($event)\"\n (nodeMove)=\"onTreeNodeMove()\"></app-layer-tree>\n </aside>\n\n <main #previewCanvas class=\"preview\"\n [class.grab-mode]=\"activeMode === builderModes.Pan\"\n [class.grabbing]=\"isPanning\"\n (click)=\"handleCanvasClick()\"\n (mousedown)=\"onBoardMouseDown($event)\"\n (mousemove)=\"onBoardMouseMove($event)\"\n (mouseup)=\"onBoardMouseUp()\"\n (mouseleave)=\"onBoardMouseUp()\">\n <app-overlay (toolbarAction)=\"onToolbarAction($event)\"></app-overlay>\n\n <!-- Custom Lenis scrollbar \u2014 lives in .preview (not .preview-scroll) so it\n stays in the right gutter and never overlaps the canvas at large widths.\n No translateY counteract needed since it isn't inside the Lenis wrapper. -->\n <div class=\"canvas-scrollbar\"\n [class.visible]=\"isScrollbarVisible\">\n <div class=\"canvas-scrollbar-thumb\"\n [style.height.px]=\"scrollThumbHeight\"\n [style.top.px]=\"scrollThumbTop\">\n </div>\n </div>\n\n <!-- Global elements overlay \u2014 outside Lenis so position:fixed children\n stay pinned to the canvas viewport rather than scrolling with content.\n Shares viewportTransform so elements scale correctly at any zoom level.\n Height matches viewportHeight so position:fixed + inset:0 fills the\n simulated viewport correctly (CSS calc(100%) would give the wrong\n containing-block height and break full-screen fixed overlays). -->\n <div *ngIf=\"globalElements.length\"\n #globalOverlay\n class=\"global-elements-overlay\"\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n <ng-container *ngFor=\"let item of globalElementsBefore\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n <ng-container *ngFor=\"let item of globalElementsAfter\">\n <ng-container [ioxRender]=\"item\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </ng-container>\n </div>\n\n <div class=\"preview-scroll\"\n #previewScroll\n [style.width.px]=\"viewportScaledWidth\"\n [class.pan-mode]=\"activeMode === builderModes.Pan\">\n\n <!-- Lenis content proxy: height = realContentHeight \u00D7 scale.\n Lenis scrolls against this value so scroll range is always in\n visual px \u2014 correct at any zoom level. -->\n <div class=\"preview-lenis-content\" #lenisContent\n [style.height.px]=\"scaledContentHeight\">\n\n <iox-page-component\n [style.width.px]=\"viewportWidth\"\n [style.height.px]=\"canvasFrameHeight || viewportHeight\"\n [style.transform]=\"viewportTransform\">\n\n <div class=\"canvas-viewport\"\n id=\"canvas-preview\"\n [style.min-height.px]=\"canvasMinHeight\">\n\n <!-- WRAPPER COLLAPSE (task 9c): top-level nodes render DIRECTLY into the\n canvas viewport \u2014 no .preview-node wrapper; iox-outer + drag move to the\n host (RenderDirective, via ioxDragSourceId). -->\n <ng-container *ngFor=\"let item of layout\"\n [ioxRender]=\"item\"\n [ioxDragSourceId]=\"'canvas-preview'\"\n (onClick)=\"handleClick($event)\"\n (onMouseEnter)=\"handleMouseEnter($event)\"\n (onMouseLeave)=\"handleMouseLeave()\">\n </ng-container>\n </div>\n </iox-page-component>\n </div>\n </div>\n </main>\n\n <ng-content select=\"[builderPanel]\"></ng-content>\n </div>\n\n <!-- Save as Reusable Block dialog -->\n @if (showSaveBlockDialog) {\n <div class=\"save-block-backdrop\" (click)=\"cancelSaveBlock()\"></div>\n <div class=\"save-block-dialog\" (click)=\"$event.stopPropagation()\">\n <h4 class=\"save-block-title\">Save as Reusable Block</h4>\n <input class=\"save-block-input\"\n type=\"text\"\n placeholder=\"Block name...\"\n [(ngModel)]=\"saveBlockName\"\n (keydown.enter)=\"confirmSaveBlock()\"\n (keydown.escape)=\"cancelSaveBlock()\"\n autofocus>\n <div class=\"save-block-actions\">\n <p-button size=\"small\" severity=\"secondary\" label=\"Cancel\" (click)=\"cancelSaveBlock()\"></p-button>\n <p-button size=\"small\" label=\"Save\" [disabled]=\"!saveBlockName.trim()\" (click)=\"confirmSaveBlock()\"></p-button>\n </div>\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;flex:1;min-height:0;overflow:hidden}.builder{display:flex;flex-direction:column;direction:ltr;width:100%;height:100%;min-height:0;border-radius:0;overflow:hidden;position:relative}.builder .builder-header{background:var(--p-surface-0);padding:.375rem .75rem;border-bottom:1px solid var(--p-surface-200);display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:.5rem;flex-shrink:0}.builder .builder-header .header-back{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;cursor:pointer;color:var(--p-text-muted-color);font-size:16px;transition:background .15s ease-out;margin-inline-end:.25rem}.builder .builder-header .header-back:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .builder-header .header-page-name{flex:1;text-align:center;font-size:.8rem;font-weight:500;color:var(--p-text-muted-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-inline:1rem}.builder .sidebar-switcher,.builder .panel-switcher{display:flex;gap:.25rem}.builder .sidebar-switcher button,.builder .panel-switcher button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:6px;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;font-size:1rem;transition:background .15s ease-out,color .15s ease-out}.builder .sidebar-switcher button i,.builder .panel-switcher button i{pointer-events:none}.builder .sidebar-switcher button:hover,.builder .panel-switcher button:hover{background:var(--p-surface-50);color:var(--p-text-color)}.builder .sidebar-switcher button.active,.builder .panel-switcher button.active{background:#cb9090;color:#fff}.builder .panel-switcher{justify-self:end}.builder .builder-main{display:flex;flex:1 1 0;min-height:0;position:relative;overflow:hidden}.builder .sidebar{width:260px;min-width:260px;background:var(--p-surface-0);border-inline-end:1px solid var(--p-surface-200);overflow-y:auto;overflow-x:hidden;flex-shrink:0}.builder .preview{flex:1 1 0;min-width:0;min-height:0;position:relative;overflow:hidden}.builder .preview.grab-mode{cursor:grab}.builder .preview.grab-mode iox-page-component{pointer-events:none}.builder .preview.grabbing{cursor:grabbing}.builder .canvas-scrollbar{position:absolute;right:4px;top:20px;bottom:20px;width:6px;z-index:20;opacity:0;transition:opacity .2s ease;pointer-events:none}.builder .canvas-scrollbar.visible{opacity:1}.builder .canvas-scrollbar-thumb{position:absolute;left:0;width:100%;background:#00000059;border-radius:3px;transition:top .05s linear}.builder .preview-scroll{position:absolute;inset:20px auto;inset-inline-start:50%;transform:translate(-50%);max-width:calc(100% - 40px);height:calc(100% - 40px);overflow:hidden}.builder .preview-lenis-content{position:relative;width:100%;overflow:hidden;contain:paint}.builder iox-page-component{position:absolute!important;top:0;bottom:auto!important;right:auto!important;left:50%;transform-origin:top center;overflow:visible!important;container:iox-canvas/inline-size;box-shadow:0 1px 4px #00000014,0 4px 16px #0000000a;transition:width .25s ease,transform .25s ease}.builder iox-page-component ::ng-deep .iox-page-wrapper{height:auto!important;overflow:visible!important}.builder #canvas-preview{background:#fff}.builder .global-elements-overlay{position:absolute;top:20px;left:50%;transform-origin:top center;pointer-events:none;z-index:9;overflow:hidden;container:iox-canvas/inline-size}.builder .global-elements-overlay ::ng-deep>*{pointer-events:auto}.builder .preview-node.is-selected{cursor:grab}.builder .empty-state{min-height:240px;border:1px dashed var(--p-surface-200);border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--p-text-muted-color);text-align:center;padding:1rem}.save-block-backdrop{position:fixed;inset:0;z-index:1000;background:#00000040}.save-block-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#fff;border-radius:8px;box-shadow:0 8px 32px #0000002e;padding:24px;width:320px}.save-block-dialog .save-block-title{margin:0 0 16px;font-size:14px;font-weight:600;color:var(--p-text-color, #333)}.save-block-dialog .save-block-input{width:100%;padding:8px 10px;border:1px solid var(--p-surface-300, #d1d5db);border-radius:6px;font-size:13px;outline:none;box-sizing:border-box;margin-bottom:16px}.save-block-dialog .save-block-input:focus{border-color:#cb9090;box-shadow:0 0 0 2px #cb909033}.save-block-dialog .save-block-actions{display:flex;justify-content:flex-end;gap:8px}::ng-deep .moveable-control-box.iox-moveable-silent{z-index:1000!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-line,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation,::ng-deep .moveable-control-box.iox-moveable-silent .moveable-rotation-line{display:none!important}::ng-deep .moveable-control-box.iox-moveable-silent .moveable-control{display:block!important;width:10px!important;height:10px!important;margin-top:-5px!important;margin-left:-5px!important;background:#fff!important;border:1.5px solid #cb9090!important;border-radius:2px!important;box-shadow:0 1px 3px #0003!important}\n"] }]
|
|
5962
6112
|
}], ctorParameters: () => [{ type: ComponentRegistryService }, { type: OverlayService }, { type: PanelEventService }, { type: DragEngineService }, { type: DataSourceRegistryService }, { type: ViewportService }, { type: InteractionEngineService }, { type: InteractionPresetRegistryService }, { type: BuilderClipboardService }, { type: SymbolRegistryService }, { type: i0.ChangeDetectorRef }, { type: i0.ApplicationRef }, { type: MoveableCanvasService }, { type: SelectoCanvasService }], propDecorators: { layout: [{
|
|
5963
6113
|
type: Input
|
|
5964
6114
|
}], dataSources: [{
|
|
@@ -6056,8 +6206,8 @@ class SectionComponent {
|
|
|
6056
6206
|
onDrop(event) {
|
|
6057
6207
|
this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr);
|
|
6058
6208
|
}
|
|
6059
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6060
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
6209
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SectionComponent, deps: [{ token: i0.ElementRef }, { token: DragEngineService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6210
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: SectionComponent, isStandalone: false, selector: "section[iox-section]", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, host: { properties: { "class": "'section-root iox-node-' + nodeId + (listOrientation === 'horizontal' ? ' is-horizontal' : '')" } }, ngImport: i0, template: `
|
|
6061
6211
|
<div *ngIf="!children.length" class="section-placeholder">
|
|
6062
6212
|
<i class="ph-thin ph-rows"></i>
|
|
6063
6213
|
<span>Drop components here</span>
|
|
@@ -6073,7 +6223,7 @@ class SectionComponent {
|
|
|
6073
6223
|
</ng-container>
|
|
6074
6224
|
`, isInline: true, styles: [":host{position:relative;box-sizing:border-box}.section-placeholder{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none;z-index:0;opacity:0;transition:opacity .15s}:host(:hover) .section-placeholder,:host(.iox-drag-over) .section-placeholder{opacity:1}.section-placeholder i{font-size:22px}:host ::ng-deep>[class*=iox-outer-]{min-width:0}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }] }); }
|
|
6075
6225
|
}
|
|
6076
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6226
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SectionComponent, decorators: [{
|
|
6077
6227
|
type: Component,
|
|
6078
6228
|
args: [{ selector: 'section[iox-section]', template: `
|
|
6079
6229
|
<div *ngIf="!children.length" class="section-placeholder">
|
|
@@ -6151,8 +6301,8 @@ class BuilderContainerComponent {
|
|
|
6151
6301
|
onDrop(event) {
|
|
6152
6302
|
this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr);
|
|
6153
6303
|
}
|
|
6154
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6155
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
6304
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderContainerComponent, deps: [{ token: i0.ElementRef }, { token: DragEngineService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6305
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: BuilderContainerComponent, isStandalone: false, selector: "div[iox-container],section[iox-container],article[iox-container],header[iox-container],footer[iox-container],main[iox-container],nav[iox-container],ul[iox-container],ol[iox-container],li[iox-container]", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", htmlTag: "htmlTag", start: "start", reversed: "reversed" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, host: { properties: { "class": "'container-root iox-node-' + nodeId + (listOrientation === 'horizontal' ? ' is-horizontal' : '')", "attr.start": "htmlTag === 'ol' && start !== 1 ? start : null", "attr.reversed": "htmlTag === 'ol' && reversed ? '' : null" } }, ngImport: i0, template: `
|
|
6156
6306
|
<div *ngIf="!children.length" class="container-placeholder">
|
|
6157
6307
|
<i class="ph-thin ph-square"></i>
|
|
6158
6308
|
<span>Drop components here</span>
|
|
@@ -6171,7 +6321,7 @@ class BuilderContainerComponent {
|
|
|
6171
6321
|
</ng-container>
|
|
6172
6322
|
`, isInline: true, styles: [":host{position:relative;box-sizing:border-box}.container-placeholder{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none;z-index:0;opacity:0;transition:opacity .15s}:host(:hover) .container-placeholder,:host(.iox-drag-over) .container-placeholder{opacity:1}.container-placeholder i{font-size:18px}:host ::ng-deep>[class*=iox-outer-]{min-width:0}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }] }); }
|
|
6173
6323
|
}
|
|
6174
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderContainerComponent, decorators: [{
|
|
6175
6325
|
type: Component,
|
|
6176
6326
|
args: [{ selector: 'div[iox-container],section[iox-container],article[iox-container],header[iox-container],footer[iox-container],main[iox-container],nav[iox-container],ul[iox-container],ol[iox-container],li[iox-container]', template: `
|
|
6177
6327
|
<div *ngIf="!children.length" class="container-placeholder">
|
|
@@ -6232,10 +6382,10 @@ class IoxDropzoneDirective {
|
|
|
6232
6382
|
ngOnDestroy() {
|
|
6233
6383
|
this.dragEngine.unregisterDropzone(this.ioxDropzoneId, this.el.nativeElement);
|
|
6234
6384
|
}
|
|
6235
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6236
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
6385
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxDropzoneDirective, deps: [{ token: i0.ElementRef }, { token: DragEngineService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
6386
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.31", type: IoxDropzoneDirective, isStandalone: false, selector: "[ioxDropzone]", inputs: { ioxDropzoneId: "ioxDropzoneId", ioxDropzoneData: "ioxDropzoneData", ioxDropzonePostDrop: "ioxDropzonePostDrop" }, outputs: { ioxDrop: "ioxDrop" }, ngImport: i0 }); }
|
|
6237
6387
|
}
|
|
6238
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6388
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxDropzoneDirective, decorators: [{
|
|
6239
6389
|
type: Directive,
|
|
6240
6390
|
args: [{
|
|
6241
6391
|
selector: '[ioxDropzone]',
|
|
@@ -6297,8 +6447,8 @@ class BuilderLinkedContainerComponent {
|
|
|
6297
6447
|
onDrop(event) {
|
|
6298
6448
|
this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr);
|
|
6299
6449
|
}
|
|
6300
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6301
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
6450
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderLinkedContainerComponent, deps: [{ token: DragEngineService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: IS_PREVIEW, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6451
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: BuilderLinkedContainerComponent, isStandalone: false, selector: "app-builder-linked-container", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", linkType: "linkType", url: "url", pageRoute: "pageRoute", target: "target" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
|
|
6302
6452
|
<a [href]="resolvedHref"
|
|
6303
6453
|
[target]="target"
|
|
6304
6454
|
[ngStyle]="style"
|
|
@@ -6326,7 +6476,7 @@ class BuilderLinkedContainerComponent {
|
|
|
6326
6476
|
</a>
|
|
6327
6477
|
`, isInline: true, styles: [".linked-container-root{display:block;position:relative;box-sizing:border-box;text-decoration:none;color:inherit;cursor:pointer}.linked-container-placeholder{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none;opacity:0;transition:opacity .15s}.linked-container-root:hover .linked-container-placeholder,.linked-container-root.iox-drag-over .linked-container-placeholder{opacity:1}.linked-container-placeholder i{font-size:18px}:host ::ng-deep .linked-container-root>[class*=iox-outer-]{min-width:0}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
|
|
6328
6478
|
}
|
|
6329
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6479
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderLinkedContainerComponent, decorators: [{
|
|
6330
6480
|
type: Component,
|
|
6331
6481
|
args: [{ selector: 'app-builder-linked-container', template: `
|
|
6332
6482
|
<a [href]="resolvedHref"
|
|
@@ -6530,10 +6680,10 @@ class BuilderDataSourceService {
|
|
|
6530
6680
|
fetchRepeaterItemsByAlias(alias, findByAlias, sourcePath) {
|
|
6531
6681
|
return this.fetchByAlias(alias, findByAlias).pipe(map(value => resolveRepeaterItems(value, sourcePath)));
|
|
6532
6682
|
}
|
|
6533
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6534
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
6683
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDataSourceService, deps: [{ token: i1.HttpClient }, { token: IOX_DATA_SOURCE_ENDPOINTS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6684
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDataSourceService }); }
|
|
6535
6685
|
}
|
|
6536
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6686
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDataSourceService, decorators: [{
|
|
6537
6687
|
type: Injectable
|
|
6538
6688
|
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
|
|
6539
6689
|
type: Optional
|
|
@@ -6712,8 +6862,8 @@ class BuilderRepeaterComponent {
|
|
|
6712
6862
|
if (this.items.length)
|
|
6713
6863
|
setTimeout(() => this.refreshPreviews());
|
|
6714
6864
|
}
|
|
6715
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6716
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
6865
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderRepeaterComponent, deps: [{ token: DragEngineService }, { token: OverlayService }, { token: BuilderDataSourceService }, { token: DataSourceRegistryService }, { token: PanelEventService }, { token: i0.ChangeDetectorRef }, { token: InteractionEngineService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6866
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: BuilderRepeaterComponent, isStandalone: false, selector: "app-builder-repeater", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", source: "source", sourcePath: "sourcePath", limit: "limit" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
|
|
6717
6867
|
<ng-template #badgeContent>
|
|
6718
6868
|
<i class="ph-thin ph-repeat"></i>
|
|
6719
6869
|
<span *ngIf="source">{{ source }}</span>
|
|
@@ -6793,7 +6943,7 @@ class BuilderRepeaterComponent {
|
|
|
6793
6943
|
</div>
|
|
6794
6944
|
`, isInline: true, styles: [".repeater-wrapper{position:relative;box-sizing:border-box}.repeater-badge{display:flex;align-items:center;gap:.4rem;padding:4px 8px;font-size:11px;color:#cb9090;background:#cb909014;border:1px dashed rgba(203,144,144,.4);border-bottom:none;border-radius:4px 4px 0 0;-webkit-user-select:none;user-select:none}.repeater-wrapper.has-children>.repeater-badge{position:absolute;top:0;left:0;z-index:10;border-radius:0 0 4px;border:1px solid rgba(203,144,144,.5);opacity:0;cursor:pointer;transition:opacity .15s}.repeater-wrapper.has-children:hover>.repeater-badge{opacity:1}.repeater-badge i{font-size:13px}.repeater-badge-empty{opacity:.55}.repeater-badge-count{margin-left:auto;font-weight:600}.repeater-badge-loading i{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.repeater-root{box-sizing:border-box}.repeater-wrapper:not(.has-children) .repeater-root{border:1px dashed rgba(203,144,144,.4);border-top:none;border-radius:0 0 4px 4px;min-height:40px}.repeater-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1.5rem 1rem;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none}.repeater-placeholder i{font-size:20px}.repeater-item-template{min-width:0}.repeater-preview-child{opacity:.55;pointer-events:none;min-width:0}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDraggableDirective, selector: "[ioxDraggable]", inputs: ["ioxDragData", "ioxDragSourceId"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
|
|
6795
6945
|
}
|
|
6796
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6946
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderRepeaterComponent, decorators: [{
|
|
6797
6947
|
type: Component,
|
|
6798
6948
|
args: [{ selector: 'app-builder-repeater', template: `
|
|
6799
6949
|
<ng-template #badgeContent>
|
|
@@ -6937,8 +7087,8 @@ class BuilderButtonBlockComponent {
|
|
|
6937
7087
|
onDrop(event) {
|
|
6938
7088
|
this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr);
|
|
6939
7089
|
}
|
|
6940
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6941
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
7090
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderButtonBlockComponent, deps: [{ token: i0.ElementRef }, { token: DragEngineService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7091
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: BuilderButtonBlockComponent, isStandalone: false, selector: "button[iox-button-block],a[iox-button-block]", inputs: { children: "children", style: "style", tag: "tag", href: "href", target: "target", type: "type", nodeId: "nodeId", dropListId: "dropListId" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, host: { properties: { "class": "'button-block-root iox-node-' + nodeId", "attr.href": "tag === 'a' ? (href || null) : null", "attr.target": "tag === 'a' ? (target || null) : null", "attr.type": "tag === 'a' ? null : type" } }, ngImport: i0, template: `
|
|
6942
7092
|
<span *ngIf="!children.length" class="button-block-placeholder">Button</span>
|
|
6943
7093
|
|
|
6944
7094
|
<!-- WRAPPER COLLAPSE (task 9c): render children directly into the host; iox-outer + drag land
|
|
@@ -6952,7 +7102,7 @@ class BuilderButtonBlockComponent {
|
|
|
6952
7102
|
</ng-container>
|
|
6953
7103
|
`, isInline: true, styles: [":host{box-sizing:border-box}.button-block-placeholder{flex:1;display:flex;align-items:center;justify-content:center;color:#64748b66;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none}:host ::ng-deep>[class*=iox-outer-]{min-width:0}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }] }); }
|
|
6954
7104
|
}
|
|
6955
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
7105
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderButtonBlockComponent, decorators: [{
|
|
6956
7106
|
type: Component,
|
|
6957
7107
|
args: [{ selector: 'button[iox-button-block],a[iox-button-block]', template: `
|
|
6958
7108
|
<span *ngIf="!children.length" class="button-block-placeholder">Button</span>
|
|
@@ -7386,8 +7536,8 @@ class SliderContainerComponent {
|
|
|
7386
7536
|
}
|
|
7387
7537
|
}
|
|
7388
7538
|
}
|
|
7389
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
7390
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
7539
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SliderContainerComponent, deps: [{ token: DragEngineService }, { token: i0.ChangeDetectorRef }, { token: IS_PREVIEW, optional: true }, { token: OverlayService, optional: true }, { token: BuilderDataSourceService, optional: true }, { token: DataSourceRegistryService, optional: true }, { token: PanelEventService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7540
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: SliderContainerComponent, isStandalone: false, selector: "app-slider-container", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", dir: "dir", direction: "direction", slidesPerView: "slidesPerView", slidesPerGroup: "slidesPerGroup", loop: "loop", centeredSlides: "centeredSlides", spaceBetween: "spaceBetween", initialSlide: "initialSlide", autoHeight: "autoHeight", grabCursor: "grabCursor", slideToClickedSlide: "slideToClickedSlide", effect: "effect", speed: "speed", enableNavigation: "enableNavigation", navigationColor: "navigationColor", navigationSize: "navigationSize", enablePagination: "enablePagination", paginationColor: "paginationColor", paginationType: "paginationType", paginationClickable: "paginationClickable", paginationDynamicBullets: "paginationDynamicBullets", enableAutoplay: "enableAutoplay", autoplayDelay: "autoplayDelay", autoplayPauseOnMouseEnter: "autoplayPauseOnMouseEnter", autoplayDisableOnInteraction: "autoplayDisableOnInteraction", enableScrollbar: "enableScrollbar", freeMode: "freeMode", enableKeyboard: "enableKeyboard", enableMousewheel: "enableMousewheel", enableZoom: "enableZoom", enableParallax: "enableParallax", enableGrid: "enableGrid", gridRows: "gridRows", breakpoints: "breakpoints", source: "source", limit: "limit" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, viewQueries: [{ propertyName: "swiperEl", first: true, predicate: ["swiperEl"], descendants: true }, { propertyName: "editSwiperEl", first: true, predicate: ["editSwiperEl"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
7391
7541
|
<!-- EDIT MODE: shell wraps swiper + nav buttons so arrows position relative to slide area -->
|
|
7392
7542
|
<div *ngIf="!isPreview"
|
|
7393
7543
|
class="slider-edit-shell"
|
|
@@ -7536,7 +7686,7 @@ class SliderContainerComponent {
|
|
|
7536
7686
|
</div>
|
|
7537
7687
|
`, isInline: true, styles: [":host{display:block}.swiper-wrapper{height:auto}.slider-edit-shell{position:relative;display:block}.swiper-edit{width:100%}.swiper-edit .swiper-slide{position:relative}.slider-edit-nav{position:absolute;top:50%;transform:translateY(-50%);width:32px;height:32px;border-radius:50%;border:1px solid rgba(255,255,255,.5);background:#00000038;color:#fff;font-size:16px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:10;transition:background .15s}.slider-edit-nav:hover{background:#00000073}.slider-edit-nav--prev{left:8px}.slider-edit-nav--next{right:8px}.slider-edit-placeholder{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none}.slider-edit-placeholder i{font-size:22px}.slider-repeat-badge{position:absolute;top:0;left:0;z-index:10;display:flex;align-items:center;gap:.4rem;padding:4px 8px;font-size:11px;color:#cb9090;background:#cb909014;border:1px solid rgba(203,144,144,.5);border-radius:0 0 4px;opacity:0;transition:opacity .15s;-webkit-user-select:none;user-select:none;pointer-events:none}.slider-edit-shell:hover .slider-repeat-badge{opacity:1}.slider-repeat-badge-count{font-weight:600}.slider-badge-spin{animation:slider-badge-spin 1s linear infinite}@keyframes slider-badge-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.slider-preview-slide{opacity:.55;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDraggableDirective, selector: "[ioxDraggable]", inputs: ["ioxDragData", "ioxDragSourceId"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
|
|
7538
7688
|
}
|
|
7539
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
7689
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SliderContainerComponent, decorators: [{
|
|
7540
7690
|
type: Component,
|
|
7541
7691
|
args: [{ selector: 'app-slider-container', template: `
|
|
7542
7692
|
<!-- EDIT MODE: shell wraps swiper + nav buttons so arrows position relative to slide area -->
|
|
@@ -7824,8 +7974,8 @@ class SliderSlideComponent {
|
|
|
7824
7974
|
onDrop(event) {
|
|
7825
7975
|
this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr);
|
|
7826
7976
|
}
|
|
7827
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
7828
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
7977
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SliderSlideComponent, deps: [{ token: DragEngineService }, { token: i0.ChangeDetectorRef }, { token: IS_PREVIEW, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7978
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: SliderSlideComponent, isStandalone: false, selector: "app-slider-slide", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
|
|
7829
7979
|
<!-- The .swiper-slide wrapper (with the iox-outer-* class) is provided by SliderContainer —
|
|
7830
7980
|
Swiper needs it as a direct child of .swiper-wrapper — and the SLIDE'S size lands there
|
|
7831
7981
|
via StyleRegistryService. This is only the styled INNER block, so width/min-width/
|
|
@@ -7862,7 +8012,7 @@ class SliderSlideComponent {
|
|
|
7862
8012
|
</div>
|
|
7863
8013
|
`, isInline: true, styles: [".slide-edit-block{position:relative;box-sizing:border-box;display:flex;align-items:center;justify-content:center;overflow:hidden;background-color:var(--p-surface-300)}.slide-edit-block{width:100%}.slide-placeholder{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px;pointer-events:none;-webkit-user-select:none;user-select:none;opacity:0;transition:opacity .15s}:host:hover .slide-placeholder,:host.iox-drag-over .slide-placeholder{opacity:1}.slide-placeholder i{font-size:22px}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDraggableDirective, selector: "[ioxDraggable]", inputs: ["ioxDragData", "ioxDragSourceId"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
|
|
7864
8014
|
}
|
|
7865
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8015
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: SliderSlideComponent, decorators: [{
|
|
7866
8016
|
type: Component,
|
|
7867
8017
|
args: [{ selector: 'app-slider-slide', template: `
|
|
7868
8018
|
<!-- The .swiper-slide wrapper (with the iox-outer-* class) is provided by SliderContainer —
|
|
@@ -7922,10 +8072,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
7922
8072
|
}] } });
|
|
7923
8073
|
|
|
7924
8074
|
class PanelChildComponent {
|
|
7925
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
7926
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
8075
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PanelChildComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8076
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: PanelChildComponent, isStandalone: false, selector: "panel-child", inputs: { name: "name" }, viewQueries: [{ propertyName: "template", first: true, predicate: ["tpl"], descendants: true, static: true }], ngImport: i0, template: '<ng-template #tpl><ng-content></ng-content></ng-template>', isInline: true }); }
|
|
7927
8077
|
}
|
|
7928
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8078
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PanelChildComponent, decorators: [{
|
|
7929
8079
|
type: Component,
|
|
7930
8080
|
args: [{
|
|
7931
8081
|
selector: 'panel-child',
|
|
@@ -7960,10 +8110,10 @@ class PanelComponent {
|
|
|
7960
8110
|
ngOnDestroy() {
|
|
7961
8111
|
this.sub?.unsubscribe();
|
|
7962
8112
|
}
|
|
7963
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
7964
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
8113
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PanelComponent, deps: [{ token: PanelEventService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8114
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: PanelComponent, isStandalone: false, selector: "app-panel", queries: [{ propertyName: "panelChildren", predicate: PanelChildComponent }], ngImport: i0, template: "<div class=\"panel\">\n <ng-container *ngFor=\"let child of panelChildren\">\n <div class=\"panel-body\" [ngClass]=\"{ active: activePanel === child.name }\">\n <ng-container *ngTemplateOutlet=\"child.template\"></ng-container>\n </div>\n </ng-container>\n</div>", styles: [":host{display:block;width:0;flex-shrink:0;overflow:hidden;transition:width .2s ease-in-out}:host-context(.panel-open){width:260px}.panel{border-left:1px solid #ccc;background:#f7f7f7;width:260px;height:100%;position:relative}.panel .panel-body{position:absolute;inset:0;overflow-y:auto;transform:translate(100%);transition:transform .2s ease-in-out}.panel .panel-body.active{transform:translate(0)}\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.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
|
|
7965
8115
|
}
|
|
7966
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8116
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: PanelComponent, decorators: [{
|
|
7967
8117
|
type: Component,
|
|
7968
8118
|
args: [{ selector: 'app-panel', standalone: false, template: "<div class=\"panel\">\n <ng-container *ngFor=\"let child of panelChildren\">\n <div class=\"panel-body\" [ngClass]=\"{ active: activePanel === child.name }\">\n <ng-container *ngTemplateOutlet=\"child.template\"></ng-container>\n </div>\n </ng-container>\n</div>", styles: [":host{display:block;width:0;flex-shrink:0;overflow:hidden;transition:width .2s ease-in-out}:host-context(.panel-open){width:260px}.panel{border-left:1px solid #ccc;background:#f7f7f7;width:260px;height:100%;position:relative}.panel .panel-body{position:absolute;inset:0;overflow-y:auto;transform:translate(100%);transition:transform .2s ease-in-out}.panel .panel-body.active{transform:translate(0)}\n"] }]
|
|
7969
8119
|
}], ctorParameters: () => [{ type: PanelEventService }], propDecorators: { panelChildren: [{
|
|
@@ -8011,10 +8161,10 @@ class BuilderHistoryService {
|
|
|
8011
8161
|
this._past = [];
|
|
8012
8162
|
this._future = [];
|
|
8013
8163
|
}
|
|
8014
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8015
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
8164
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderHistoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8165
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderHistoryService }); }
|
|
8016
8166
|
}
|
|
8017
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8167
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderHistoryService, decorators: [{
|
|
8018
8168
|
type: Injectable
|
|
8019
8169
|
}] });
|
|
8020
8170
|
|
|
@@ -8043,8 +8193,8 @@ const DECLARATIONS = [
|
|
|
8043
8193
|
BreadcrumbBarComponent,
|
|
8044
8194
|
];
|
|
8045
8195
|
class IoxBuilderModule {
|
|
8046
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8047
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
8196
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxBuilderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
8197
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.31", ngImport: i0, type: IoxBuilderModule, declarations: [BuilderComponent,
|
|
8048
8198
|
RenderDirective,
|
|
8049
8199
|
IoxDraggableDirective,
|
|
8050
8200
|
IoxDropzoneDirective,
|
|
@@ -8101,7 +8251,7 @@ class IoxBuilderModule {
|
|
|
8101
8251
|
PanelChildComponent,
|
|
8102
8252
|
LayerTreeComponent,
|
|
8103
8253
|
BreadcrumbBarComponent] }); }
|
|
8104
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
8254
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxBuilderModule, providers: [
|
|
8105
8255
|
DragEngineService,
|
|
8106
8256
|
OverlayService,
|
|
8107
8257
|
ComponentRegistryService,
|
|
@@ -8140,7 +8290,7 @@ class IoxBuilderModule {
|
|
|
8140
8290
|
DialogModule,
|
|
8141
8291
|
IoxPageModule] }); }
|
|
8142
8292
|
}
|
|
8143
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8293
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: IoxBuilderModule, decorators: [{
|
|
8144
8294
|
type: NgModule,
|
|
8145
8295
|
args: [{
|
|
8146
8296
|
declarations: DECLARATIONS,
|
|
@@ -8772,5 +8922,5 @@ class BuilderSpacerComponentConfig extends ComponentConfig {
|
|
|
8772
8922
|
* Generated bundle index. Do not edit.
|
|
8773
8923
|
*/
|
|
8774
8924
|
|
|
8775
|
-
export { ACTION_TYPE_OPTIONS, BackgroundGroupStyleConfig, BorderGroupStyleConfig, BreadcrumbBarComponent, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderClipboardService, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDataSourceService, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderHistoryService, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ChildLayoutGroupStyleConfig, ComponentConfig, ComponentRegistryService,
|
|
8925
|
+
export { ACTION_TYPE_OPTIONS, BREAKPOINT_PRESENTATION, BUILDER_CANVAS_CONTAINER, BackgroundGroupStyleConfig, BorderGroupStyleConfig, BreadcrumbBarComponent, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderClipboardService, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDataSourceService, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderHistoryService, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ChildLayoutGroupStyleConfig, ComponentConfig, ComponentRegistryService, DRAG_HANDLE_ATTR, DataSourceRegistryService, DataSourceType, DimensionsGroupStyleConfig, DragEngineService, EASING_OPTIONS$1 as EASING_OPTIONS, EffectsGroupStyleConfig, GalleryConfig, GroupStyleConfig, INTERACTION_STATES, INVERSE_ACTION, IOX_DATA_SOURCE_ENDPOINTS, IOX_FONT_MANAGER, InteractionEngineService, InteractionPresetRegistryService, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LayerTreeComponent, LayoutGroupStyleConfig, ListGroupStyleConfig, NodeAction, OverlayComponent, OverlayService, PanelChildComponent, PanelComponent, PanelEventService, PanelEventTypes, PanelTypes, PositionGroupStyleConfig, PresetRegistryService, RELATIONAL_STATES, RELATIONAL_STATE_BASE, ROUTE_ANIMATION_OPTIONS, RenderDirective, RepeaterComponentConfig, SCREEN_WIDTH_OPTIONS, STRUCTURAL_STATES, SUPPORTED_STATES, SectionComponent, SectionComponentConfig, SizeGroupStyleConfig, SliderContainerComponent, SliderContainerConfig, SliderSlideComponent, SliderSlideConfig, SpacingGroupStyleConfig, StyleCategory, StyleRegistryService, TraitConfig as StyleTraitConfig, SymbolRegistryService, TARGETED_STATES, TARGETED_STATE_BASE, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, TypographyGroupStyleConfig, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, ViewportService, ZOOM_OPTIONS, arrayItemSchemaFields, arraySchemaFields, buildFullStyleTraits, buildPresetStyleTraits, defaultPageSettings, findNodeLocation, findParentOf, flattenSchemaFields, generateNodeId, nodeAncestorPath, nodeAncestorPathInEither, resolveTraitControllerType, resolveTraitOptions, wrapNode };
|
|
8776
8926
|
//# sourceMappingURL=vectoriox-iox-builder.mjs.map
|