@vectoriox/iox-builder 1.4.3 → 1.4.4
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.
|
@@ -1294,177 +1294,541 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
1294
1294
|
type: Injectable
|
|
1295
1295
|
}], ctorParameters: () => [{ type: OverlayService }] });
|
|
1296
1296
|
|
|
1297
|
+
var StyleCategory;
|
|
1298
|
+
(function (StyleCategory) {
|
|
1299
|
+
StyleCategory["Layout"] = "Layout";
|
|
1300
|
+
StyleCategory["Size"] = "Size";
|
|
1301
|
+
StyleCategory["Typography"] = "Typography";
|
|
1302
|
+
StyleCategory["Spacing"] = "Spacing";
|
|
1303
|
+
StyleCategory["Border"] = "Border";
|
|
1304
|
+
StyleCategory["Position"] = "Position";
|
|
1305
|
+
StyleCategory["Background"] = "Background";
|
|
1306
|
+
StyleCategory["Effects"] = "Effects";
|
|
1307
|
+
// Legacy — kept for backward compat; prefer Size
|
|
1308
|
+
StyleCategory["Dimensions"] = "Dimensions";
|
|
1309
|
+
})(StyleCategory || (StyleCategory = {}));
|
|
1310
|
+
const TRIGGER_OPTIONS = [
|
|
1311
|
+
{ value: 'pageLoad', label: 'Page load', icon: 'ph-thin ph-play' },
|
|
1312
|
+
{ value: 'viewportEnter', label: 'Enter viewport', icon: 'ph-thin ph-eye' },
|
|
1313
|
+
{ value: 'click', label: 'Click', icon: 'ph-thin ph-cursor-click' },
|
|
1314
|
+
{ value: 'hover', label: 'Hover', icon: 'ph-thin ph-hand-pointing' },
|
|
1315
|
+
{ value: 'scrollProgress', label: 'Scroll progress', icon: 'ph-thin ph-arrow-fat-lines-down' },
|
|
1316
|
+
];
|
|
1317
|
+
const ACTION_TYPE_OPTIONS = [
|
|
1318
|
+
{ value: 'fadeIn', label: 'Fade in' },
|
|
1319
|
+
{ value: 'fadeOut', label: 'Fade out' },
|
|
1320
|
+
{ value: 'moveUp', label: 'Move up' },
|
|
1321
|
+
{ value: 'moveDown', label: 'Move down' },
|
|
1322
|
+
{ value: 'moveLeft', label: 'Move left' },
|
|
1323
|
+
{ value: 'moveRight', label: 'Move right' },
|
|
1324
|
+
{ value: 'scaleIn', label: 'Scale in' },
|
|
1325
|
+
{ value: 'scaleOut', label: 'Scale out' },
|
|
1326
|
+
{ value: 'rotate', label: 'Rotate' },
|
|
1327
|
+
{ value: 'show', label: 'Show' },
|
|
1328
|
+
{ value: 'hide', label: 'Hide' },
|
|
1329
|
+
{ value: 'toggleVisibility', label: 'Toggle visibility' },
|
|
1330
|
+
];
|
|
1331
|
+
const EASING_OPTIONS = ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'];
|
|
1332
|
+
/** Interaction pseudo-classes — compiled to .iox-node-{id}:state */
|
|
1333
|
+
const INTERACTION_STATES = ['hover', 'active', 'focus'];
|
|
1334
|
+
/** Structural pseudo-classes — compiled to .iox-outer-{id}:state */
|
|
1335
|
+
const STRUCTURAL_STATES = ['first-child', 'last-child', 'nth-child(odd)', 'nth-child(even)'];
|
|
1336
|
+
const SUPPORTED_STATES = [...INTERACTION_STATES, ...STRUCTURAL_STATES];
|
|
1297
1337
|
/**
|
|
1298
|
-
*
|
|
1299
|
-
*
|
|
1300
|
-
*
|
|
1301
|
-
* .iox-node-{id} — applied to the inner element; handles layout/visual props
|
|
1302
|
-
* (display, flex, background, border, padding, etc.)
|
|
1303
|
-
* .iox-outer-{id} — applied to the host element by RenderDirective; handles
|
|
1304
|
-
* properties that participate in the PARENT flow (margin,
|
|
1305
|
-
* align-self, flex-grow/shrink/basis, order).
|
|
1306
|
-
*
|
|
1307
|
-
* This split is necessary because margin on an inner wrapper only adds internal
|
|
1308
|
-
* space — it does not push sibling elements. Applying margin to the host element
|
|
1309
|
-
* (which IS the flex/block child in the parent container) makes it work correctly.
|
|
1310
|
-
*
|
|
1311
|
-
* State styles (hover/active/focus) are stored under key `${nodeId}:${state}`
|
|
1312
|
-
* and compiled to `.iox-node-{id}:hover { … }` selectors.
|
|
1313
|
-
*
|
|
1314
|
-
* Design token variables are stored under the reserved key `__tokens__` and
|
|
1315
|
-
* compiled to a `:root { … }` block prepended to all other rules.
|
|
1316
|
-
*
|
|
1317
|
-
* Scoped to PageUiComponent.providers[] — one stylesheet per builder instance.
|
|
1338
|
+
* Build a full StyleTraitGroup[] schema populated with values from a flat
|
|
1339
|
+
* styleProps map. Used when editing a preset in the Style panel — the panel
|
|
1340
|
+
* receives the same `StyleTraitGroup[]` shape regardless of context.
|
|
1318
1341
|
*/
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1342
|
+
function buildPresetStyleTraits(styleProps) {
|
|
1343
|
+
const allGroups = [
|
|
1344
|
+
new LayoutGroupStyleConfig(),
|
|
1345
|
+
new SizeGroupStyleConfig(),
|
|
1346
|
+
new BackgroundGroupStyleConfig(),
|
|
1347
|
+
new SpacingGroupStyleConfig(),
|
|
1348
|
+
new BorderGroupStyleConfig(),
|
|
1349
|
+
new TypographyGroupStyleConfig(),
|
|
1350
|
+
new EffectsGroupStyleConfig(),
|
|
1351
|
+
new PositionGroupStyleConfig(),
|
|
1352
|
+
];
|
|
1353
|
+
return allGroups.map(group => ({
|
|
1354
|
+
...group,
|
|
1355
|
+
traits: group.traits.map(trait => ({
|
|
1356
|
+
...trait,
|
|
1357
|
+
default: styleProps[trait.name] !== undefined ? styleProps[trait.name] : trait.default,
|
|
1358
|
+
})),
|
|
1359
|
+
}));
|
|
1360
|
+
}
|
|
1361
|
+
var TraitInputType;
|
|
1362
|
+
(function (TraitInputType) {
|
|
1363
|
+
TraitInputType["Text"] = "text";
|
|
1364
|
+
TraitInputType["Number"] = "number";
|
|
1365
|
+
TraitInputType["Select"] = "select";
|
|
1366
|
+
TraitInputType["Checkbox"] = "checkbox";
|
|
1367
|
+
TraitInputType["Color"] = "colorPicker";
|
|
1368
|
+
TraitInputType["DirectionalSize"] = "directionalSize";
|
|
1369
|
+
TraitInputType["SelectButton"] = "selectButton";
|
|
1370
|
+
TraitInputType["Scrub"] = "scrub";
|
|
1371
|
+
TraitInputType["Icon"] = "icon";
|
|
1372
|
+
TraitInputType["Media"] = "media";
|
|
1373
|
+
TraitInputType["FontFamily"] = "fontFamily";
|
|
1374
|
+
TraitInputType["GridTemplate"] = "gridTemplate";
|
|
1375
|
+
})(TraitInputType || (TraitInputType = {}));
|
|
1376
|
+
function generateNodeId() {
|
|
1377
|
+
return Math.random().toString(36).substr(2, 9);
|
|
1378
|
+
}
|
|
1379
|
+
class ComponentConfig {
|
|
1380
|
+
constructor(type, selector, icon = 'ph-thin ph-cube', category = 'General') {
|
|
1381
|
+
this.id = generateNodeId();
|
|
1382
|
+
this.type = type;
|
|
1383
|
+
this.selector = selector;
|
|
1384
|
+
this.icon = icon;
|
|
1385
|
+
this.category = category;
|
|
1386
|
+
this.inputs = {};
|
|
1387
|
+
this.traits = [];
|
|
1388
|
+
this.styleTraits = [];
|
|
1335
1389
|
}
|
|
1336
|
-
/**
|
|
1337
|
-
*
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
*/
|
|
1345
|
-
upsert(nodeId, styles, state) {
|
|
1346
|
-
if (!nodeId)
|
|
1347
|
-
return;
|
|
1348
|
-
if (state) {
|
|
1349
|
-
const css = this.compile(`iox-node-${nodeId}:${state}`, styles);
|
|
1350
|
-
const key = `${nodeId}:${state}`;
|
|
1351
|
-
if (css) {
|
|
1352
|
-
this.rules.set(key, css);
|
|
1353
|
-
}
|
|
1354
|
-
else {
|
|
1355
|
-
this.rules.delete(key);
|
|
1356
|
-
}
|
|
1357
|
-
this.flush();
|
|
1358
|
-
return;
|
|
1359
|
-
}
|
|
1360
|
-
const inner = {};
|
|
1361
|
-
const outer = {};
|
|
1362
|
-
for (const [k, v] of Object.entries(styles)) {
|
|
1363
|
-
if (StyleRegistryService.OUTER_PROPS.has(k)) {
|
|
1364
|
-
outer[k] = v;
|
|
1365
|
-
}
|
|
1366
|
-
else {
|
|
1367
|
-
inner[k] = v;
|
|
1390
|
+
/** Override specific trait defaults after styleTraits are set.
|
|
1391
|
+
* Call this at the end of each subclass constructor. */
|
|
1392
|
+
applyStyleDefaults(defaults) {
|
|
1393
|
+
for (const group of this.styleTraits) {
|
|
1394
|
+
for (const trait of group.traits) {
|
|
1395
|
+
if (defaults[trait.name] !== undefined) {
|
|
1396
|
+
trait.default = defaults[trait.name];
|
|
1397
|
+
}
|
|
1368
1398
|
}
|
|
1369
1399
|
}
|
|
1370
|
-
const innerCss = this.compile(`iox-node-${nodeId}`, inner);
|
|
1371
|
-
const outerCss = this.compile(`iox-outer-${nodeId}`, outer);
|
|
1372
|
-
const combined = [innerCss, outerCss].filter(Boolean).join('\n');
|
|
1373
|
-
if (combined) {
|
|
1374
|
-
this.rules.set(nodeId, combined);
|
|
1375
|
-
}
|
|
1376
|
-
else {
|
|
1377
|
-
this.rules.delete(nodeId);
|
|
1378
|
-
}
|
|
1379
|
-
this.flush();
|
|
1380
1400
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
if (entries.length) {
|
|
1392
|
-
this.rules.set('__tokens__', `:root {\n${entries.join('\n')}\n}`);
|
|
1393
|
-
}
|
|
1394
|
-
else {
|
|
1395
|
-
this.rules.delete('__tokens__');
|
|
1396
|
-
}
|
|
1397
|
-
this.flush();
|
|
1401
|
+
}
|
|
1402
|
+
class TraitConfig {
|
|
1403
|
+
constructor(name, label, type, options, defaultValue, inline, showWhen) {
|
|
1404
|
+
this.name = name;
|
|
1405
|
+
this.label = label;
|
|
1406
|
+
this.type = type;
|
|
1407
|
+
this.options = options;
|
|
1408
|
+
this.default = defaultValue;
|
|
1409
|
+
this.inline = inline;
|
|
1410
|
+
this.showWhen = showWhen;
|
|
1398
1411
|
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
this.
|
|
1404
|
-
for (const key of this.rules.keys()) {
|
|
1405
|
-
if (key.startsWith(`${nodeId}:`)) {
|
|
1406
|
-
this.rules.delete(key);
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
this.flush();
|
|
1412
|
+
}
|
|
1413
|
+
class GroupStyleConfig {
|
|
1414
|
+
constructor(category, traits) {
|
|
1415
|
+
this.category = category;
|
|
1416
|
+
this.traits = traits;
|
|
1410
1417
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1418
|
+
}
|
|
1419
|
+
// ─── Unit constants ───────────────────────────────────────────────────────────
|
|
1420
|
+
const UNITS_ALL = ['px', '%', 'rem', 'em', 'vw', 'vh'];
|
|
1421
|
+
const UNITS_NO_VW = ['px', '%', 'rem', 'em', 'vh'];
|
|
1422
|
+
const UNITS_FIXED = ['px', '%', 'rem', 'em'];
|
|
1423
|
+
const UNITS_DEG = ['deg'];
|
|
1424
|
+
// ─── Shared panel utilities ──────────────────────────────────────────────────
|
|
1425
|
+
function resolveTraitControllerType(type) {
|
|
1426
|
+
switch (type) {
|
|
1427
|
+
case TraitInputType.Number: return 'number';
|
|
1428
|
+
case TraitInputType.Select: return 'select';
|
|
1429
|
+
case TraitInputType.Checkbox: return 'switch';
|
|
1430
|
+
case TraitInputType.Color: return 'colorPicker';
|
|
1431
|
+
case TraitInputType.DirectionalSize: return 'directionalSize';
|
|
1432
|
+
case TraitInputType.SelectButton: return 'selectButton';
|
|
1433
|
+
case TraitInputType.Scrub: return 'scrub';
|
|
1434
|
+
case TraitInputType.Icon: return 'icon';
|
|
1435
|
+
case TraitInputType.Media: return 'media';
|
|
1436
|
+
case TraitInputType.FontFamily: return 'select';
|
|
1437
|
+
case TraitInputType.GridTemplate: return 'gridTemplate';
|
|
1438
|
+
default: return 'text';
|
|
1417
1439
|
}
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1440
|
+
}
|
|
1441
|
+
function resolveTraitOptions(trait) {
|
|
1442
|
+
if (trait.type === TraitInputType.Color ||
|
|
1443
|
+
trait.type === TraitInputType.DirectionalSize ||
|
|
1444
|
+
trait.type === TraitInputType.SelectButton ||
|
|
1445
|
+
trait.type === TraitInputType.Scrub ||
|
|
1446
|
+
trait.type === TraitInputType.Media) {
|
|
1447
|
+
return trait.options;
|
|
1425
1448
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1449
|
+
if (trait.type === TraitInputType.FontFamily) {
|
|
1450
|
+
// FontFamily options are injected dynamically by the style panel via FontManagerService.
|
|
1451
|
+
// Return empty array here; the panel overrides this in resolveOptions().
|
|
1452
|
+
return [];
|
|
1428
1453
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
return;
|
|
1432
|
-
// __tokens__ always first so variables are available to all subsequent rules
|
|
1433
|
-
const tokenBlock = this.rules.get('__tokens__');
|
|
1434
|
-
const rest = Array.from(this.rules.entries())
|
|
1435
|
-
.filter(([k]) => k !== '__tokens__')
|
|
1436
|
-
.map(([, v]) => v);
|
|
1437
|
-
this.styleEl.textContent = [tokenBlock, ...rest].filter(Boolean).join('\n');
|
|
1438
|
-
this.changes$.next();
|
|
1454
|
+
if (trait.type !== TraitInputType.Select) {
|
|
1455
|
+
return undefined;
|
|
1439
1456
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1457
|
+
const opts = trait.options ?? [];
|
|
1458
|
+
// Already formatted as {label, value}[]
|
|
1459
|
+
if (opts.length > 0 && typeof opts[0] === 'object' && 'label' in opts[0]) {
|
|
1460
|
+
return opts;
|
|
1461
|
+
}
|
|
1462
|
+
return opts.map((option) => ({ label: option, value: option }));
|
|
1463
|
+
}
|
|
1464
|
+
// ─── Style Groups ─────────────────────────────────────────────────────────────
|
|
1465
|
+
const NON_STATIC_POSITIONS = ['relative', 'absolute', 'fixed', 'sticky'];
|
|
1466
|
+
class PositionGroupStyleConfig extends GroupStyleConfig {
|
|
1467
|
+
constructor() {
|
|
1468
|
+
super(StyleCategory.Position, [
|
|
1469
|
+
new TraitConfig('position', 'Position', TraitInputType.Select, ['static', 'relative', 'absolute', 'fixed', 'sticky'], 'static'),
|
|
1470
|
+
new TraitConfig('top', 'T', TraitInputType.Scrub, { min: -9999, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
1471
|
+
new TraitConfig('right', 'R', TraitInputType.Scrub, { min: -9999, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
1472
|
+
new TraitConfig('bottom', 'B', TraitInputType.Scrub, { min: -9999, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
1473
|
+
new TraitConfig('left', 'L', TraitInputType.Scrub, { min: -9999, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
1474
|
+
new TraitConfig('zIndex', 'Z', TraitInputType.Scrub, { min: -99, max: 9999, step: 1, units: [''] }, '0', false, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
1475
|
+
]);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
// ─── Layout ───────────────────────────────────────────────────────────────────
|
|
1479
|
+
class LayoutGroupStyleConfig extends GroupStyleConfig {
|
|
1480
|
+
constructor() {
|
|
1481
|
+
super(StyleCategory.Layout, [
|
|
1482
|
+
new TraitConfig('display', 'Display', TraitInputType.Select, ['block', 'inline', 'inline-block', 'flex', 'grid'], 'block'),
|
|
1483
|
+
// ── Flex-only ─────────────────────────────────────────────────────
|
|
1484
|
+
new TraitConfig('flexDirection', 'Direction', TraitInputType.SelectButton, [
|
|
1485
|
+
{ value: 'row', label: 'Horizontal', icon: 'ph-thin ph-arrow-right' },
|
|
1486
|
+
{ value: 'row-reverse', label: 'Horizontal Reversed', icon: 'ph-thin ph-arrow-left' },
|
|
1487
|
+
{ value: 'column', label: 'Vertical', icon: 'ph-thin ph-arrow-down' },
|
|
1488
|
+
{ value: 'column-reverse', label: 'Vertical Reversed', icon: 'ph-thin ph-arrow-up' },
|
|
1489
|
+
], 'row', false, { trait: 'display', values: 'flex' }),
|
|
1490
|
+
new TraitConfig('flexWrap', 'Flex Wrap', TraitInputType.SelectButton, [
|
|
1491
|
+
{ value: 'nowrap', label: 'No Wrap', icon: 'ph-thin ph-minus' },
|
|
1492
|
+
{ value: 'wrap', label: 'Wrap', icon: 'ph-thin ph-arrow-elbow-down-right' },
|
|
1493
|
+
{ value: 'wrap-reverse', label: 'Wrap Reversed', icon: 'ph-thin ph-arrow-elbow-up-right' },
|
|
1494
|
+
], 'nowrap', false, { trait: 'display', values: 'flex' }),
|
|
1495
|
+
// ── Shared flex + grid ────────────────────────────────────────────
|
|
1496
|
+
new TraitConfig('justifyContent', 'Justify', TraitInputType.SelectButton, [
|
|
1497
|
+
{ value: 'flex-start', label: 'Start', icon: 'ph-thin ph-align-left' },
|
|
1498
|
+
{ value: 'center', label: 'Center', icon: 'ph-thin ph-align-center-horizontal' },
|
|
1499
|
+
{ value: 'flex-end', label: 'End', icon: 'ph-thin ph-align-right' },
|
|
1500
|
+
{ value: 'space-between', label: 'Space Between', icon: 'ph-thin ph-distribute-horizontal' },
|
|
1501
|
+
{ value: 'space-around', label: 'Space Around', icon: 'ph-thin ph-dots-three' },
|
|
1502
|
+
{ value: 'space-evenly', label: 'Space Evenly', icon: 'ph-thin ph-dots-six' },
|
|
1503
|
+
], 'flex-start', false, { trait: 'display', values: ['flex', 'grid'] }),
|
|
1504
|
+
new TraitConfig('alignItems', 'Align Items', TraitInputType.SelectButton, [
|
|
1505
|
+
{ value: 'stretch', label: 'Stretch', icon: 'ph-thin ph-arrows-vertical' },
|
|
1506
|
+
{ value: 'start', label: 'Start', icon: 'ph-thin ph-align-top' },
|
|
1507
|
+
{ value: 'center', label: 'Center', icon: 'ph-thin ph-align-center-vertical' },
|
|
1508
|
+
{ value: 'end', label: 'End', icon: 'ph-thin ph-align-bottom' },
|
|
1509
|
+
], 'stretch', false, { trait: 'display', values: ['flex', 'grid'] }),
|
|
1510
|
+
new TraitConfig('gap', 'Gap', TraitInputType.Scrub, { min: 0, max: 200, step: 1, units: UNITS_FIXED }, '0px', false, { trait: 'display', values: ['flex', 'grid'] }),
|
|
1511
|
+
// ── Grid-only ─────────────────────────────────────────────────────
|
|
1512
|
+
new TraitConfig('gridTemplateColumns', 'Columns', TraitInputType.GridTemplate, undefined, '1fr', false, { trait: 'display', values: 'grid' }),
|
|
1513
|
+
new TraitConfig('gridTemplateRows', 'Rows', TraitInputType.GridTemplate, undefined, 'auto', false, { trait: 'display', values: 'grid' }),
|
|
1514
|
+
new TraitConfig('justifyItems', 'Justify Items', TraitInputType.SelectButton, [
|
|
1515
|
+
{ value: 'stretch', label: 'Stretch', icon: 'ph-thin ph-arrows-horizontal' },
|
|
1516
|
+
{ value: 'start', label: 'Start', icon: 'ph-thin ph-align-left' },
|
|
1517
|
+
{ value: 'center', label: 'Center', icon: 'ph-thin ph-align-center-horizontal' },
|
|
1518
|
+
{ value: 'end', label: 'End', icon: 'ph-thin ph-align-right' },
|
|
1519
|
+
], 'stretch', false, { trait: 'display', values: 'grid' }),
|
|
1520
|
+
new TraitConfig('alignContent', 'Align Content', TraitInputType.SelectButton, [
|
|
1521
|
+
{ value: 'start', label: 'Start', icon: 'ph-thin ph-align-top' },
|
|
1522
|
+
{ value: 'center', label: 'Center', icon: 'ph-thin ph-align-center-vertical' },
|
|
1523
|
+
{ value: 'end', label: 'End', icon: 'ph-thin ph-align-bottom' },
|
|
1524
|
+
{ value: 'space-between', label: 'Space Between', icon: 'ph-thin ph-distribute-vertical' },
|
|
1525
|
+
{ value: 'space-around', label: 'Space Around', icon: 'ph-thin ph-dots-three' },
|
|
1526
|
+
{ value: 'stretch', label: 'Stretch', icon: 'ph-thin ph-arrows-vertical' },
|
|
1527
|
+
], 'stretch', false, { trait: 'display', values: 'grid' }),
|
|
1528
|
+
// ── Direction (always visible) ────────────────────────────────────
|
|
1529
|
+
new TraitConfig('direction', 'Text Direction', TraitInputType.SelectButton, [
|
|
1530
|
+
{ value: 'ltr', label: 'LTR' },
|
|
1531
|
+
{ value: 'rtl', label: 'RTL' },
|
|
1532
|
+
], 'ltr'),
|
|
1533
|
+
]);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
// ─── Size (replaces Dimensions) ───────────────────────────────────────────────
|
|
1537
|
+
class SizeGroupStyleConfig extends GroupStyleConfig {
|
|
1538
|
+
constructor() {
|
|
1539
|
+
super(StyleCategory.Size, [
|
|
1540
|
+
new TraitConfig('width', 'W', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
1541
|
+
new TraitConfig('height', 'H', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
1542
|
+
new TraitConfig('minWidth', 'Min W', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
1543
|
+
new TraitConfig('minHeight', 'Min H', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
1544
|
+
new TraitConfig('maxWidth', 'Max W', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
1545
|
+
new TraitConfig('maxHeight', 'Max H', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
1546
|
+
new TraitConfig('aspectRatio', 'Aspect Ratio', TraitInputType.Text, undefined, 'auto'),
|
|
1547
|
+
]);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
/** @deprecated Use SizeGroupStyleConfig instead. */
|
|
1551
|
+
class DimensionsGroupStyleConfig extends SizeGroupStyleConfig {
|
|
1552
|
+
}
|
|
1553
|
+
// ─── Background ───────────────────────────────────────────────────────────────
|
|
1554
|
+
class BackgroundGroupStyleConfig extends GroupStyleConfig {
|
|
1555
|
+
constructor() {
|
|
1556
|
+
super(StyleCategory.Background, [
|
|
1557
|
+
new TraitConfig('backgroundColor', 'Background', TraitInputType.Color, { allowGradient: true, allowTransparent: true, formats: ['hex', 'rgb', 'hsl', 'transparent'] }, 'transparent'),
|
|
1558
|
+
]);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
class SpacingGroupStyleConfig extends GroupStyleConfig {
|
|
1562
|
+
constructor() {
|
|
1563
|
+
super(StyleCategory.Spacing, [
|
|
1564
|
+
new TraitConfig('margin', 'Margin', TraitInputType.DirectionalSize, {
|
|
1565
|
+
allowNegative: true,
|
|
1566
|
+
allowLinkedSlider: true,
|
|
1567
|
+
slider: { min: 0, max: 200, step: 1 }
|
|
1568
|
+
}, '0px 0px 0px 0px'),
|
|
1569
|
+
new TraitConfig('padding', 'Padding', TraitInputType.DirectionalSize, {
|
|
1570
|
+
allowNegative: false,
|
|
1571
|
+
allowLinkedSlider: true,
|
|
1572
|
+
slider: { min: 0, max: 200, step: 1 }
|
|
1573
|
+
}, '0px 0px 0px 0px')
|
|
1574
|
+
]);
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
class BorderGroupStyleConfig extends GroupStyleConfig {
|
|
1578
|
+
constructor() {
|
|
1579
|
+
super(StyleCategory.Border, [
|
|
1580
|
+
new TraitConfig('borderWidth', 'Border Width', TraitInputType.DirectionalSize, {
|
|
1581
|
+
units: UNITS_FIXED,
|
|
1582
|
+
allowNegative: false,
|
|
1583
|
+
allowLinkedSlider: true,
|
|
1584
|
+
slider: { min: 0, max: 32, step: 1 }
|
|
1585
|
+
}, '0px'),
|
|
1586
|
+
new TraitConfig('borderStyle', 'Border Style', TraitInputType.SelectButton, [
|
|
1587
|
+
{ value: 'solid', icon: 'ph-thin ph-line-segment' },
|
|
1588
|
+
{ value: 'dashed', icon: 'ph-thin ph-dots-three' },
|
|
1589
|
+
{ value: 'dotted', icon: 'ph-thin ph-dots-six' },
|
|
1590
|
+
], 'solid'),
|
|
1591
|
+
new TraitConfig('borderColor', 'Border Color', TraitInputType.Color, { allowGradient: false, allowTransparent: false, formats: ['hex', 'rgb', 'hsl'] }, '#CCCCCC'),
|
|
1592
|
+
new TraitConfig('borderRadius', 'Border Radius', TraitInputType.DirectionalSize, {
|
|
1593
|
+
units: UNITS_FIXED,
|
|
1594
|
+
allowNegative: false,
|
|
1595
|
+
allowLinkedSlider: true,
|
|
1596
|
+
linkByDefault: true,
|
|
1597
|
+
slider: { min: 0, max: 120, step: 1 },
|
|
1598
|
+
segments: [
|
|
1599
|
+
{ key: 'top-left', icon: 'ph-arrow-bend-up-left', ariaLabel: 'top left radius' },
|
|
1600
|
+
{ key: 'top-right', icon: 'ph-arrow-bend-up-right', ariaLabel: 'top right radius' },
|
|
1601
|
+
{ key: 'bottom-right', icon: 'ph-arrow-bend-down-right', ariaLabel: 'bottom right radius' },
|
|
1602
|
+
{ key: 'bottom-left', icon: 'ph-arrow-bend-down-left', ariaLabel: 'bottom left radius' }
|
|
1603
|
+
]
|
|
1604
|
+
}, '0px')
|
|
1605
|
+
]);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
class TypographyGroupStyleConfig extends GroupStyleConfig {
|
|
1609
|
+
constructor() {
|
|
1610
|
+
super(StyleCategory.Typography, [
|
|
1611
|
+
new TraitConfig('fontFamily', 'Font Family', TraitInputType.FontFamily, [], 'Poppins, sans-serif'),
|
|
1612
|
+
new TraitConfig('fontSize', 'Font Size', TraitInputType.Scrub, { min: 8, max: 200, step: 1, units: UNITS_FIXED }, '16px'),
|
|
1613
|
+
new TraitConfig('fontWeight', 'Font Weight', TraitInputType.Select, ['100', '200', '300', '400', '500', '600', '700', '800', '900'], '400'),
|
|
1614
|
+
new TraitConfig('color', 'Color', TraitInputType.Color, { allowGradient: false, allowTransparent: false, formats: ['hex', 'rgb', 'hsl'] }, '#000000'),
|
|
1615
|
+
new TraitConfig('lineHeight', 'Line Height', TraitInputType.Select, ['1', '1.2', '1.4', '1.5', '1.75', '2', '2.5'], '1.5'),
|
|
1616
|
+
new TraitConfig('letterSpacing', 'Letter Spacing', TraitInputType.Scrub, { min: -5, max: 50, step: 0.5, units: UNITS_FIXED }, '0px'),
|
|
1617
|
+
new TraitConfig('textAlign', 'Alignment', TraitInputType.SelectButton, [
|
|
1618
|
+
{ value: 'left', icon: 'ph-thin ph-text-align-left' },
|
|
1619
|
+
{ value: 'center', icon: 'ph-thin ph-text-align-center' },
|
|
1620
|
+
{ value: 'right', icon: 'ph-thin ph-text-align-right' },
|
|
1621
|
+
{ value: 'justify', icon: 'ph-thin ph-text-align-justify' },
|
|
1622
|
+
], 'left'),
|
|
1623
|
+
new TraitConfig('fontStyle', 'Italic', TraitInputType.SelectButton, { items: [{ value: 'italic', icon: 'ph-thin ph-text-italic', label: 'Italic' }], allowEmpty: true, noneValue: 'normal' }, 'normal', true),
|
|
1624
|
+
new TraitConfig('textDecoration', 'Underline', TraitInputType.SelectButton, { items: [{ value: 'underline', icon: 'ph-thin ph-text-underline', label: 'Underline' }], allowEmpty: true, noneValue: 'none' }, 'none', true),
|
|
1625
|
+
]);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
class EffectsGroupStyleConfig extends GroupStyleConfig {
|
|
1629
|
+
constructor() {
|
|
1630
|
+
super(StyleCategory.Effects, [
|
|
1631
|
+
new TraitConfig('opacity', 'Opacity', TraitInputType.Scrub, { min: 0, max: 1, step: 0.01, units: [''] }, '1'),
|
|
1632
|
+
new TraitConfig('mixBlendMode', 'Blend Mode', TraitInputType.Select, [
|
|
1633
|
+
'normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten',
|
|
1634
|
+
'color-dodge', 'color-burn', 'hard-light', 'soft-light',
|
|
1635
|
+
'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity',
|
|
1636
|
+
], 'normal'),
|
|
1637
|
+
new TraitConfig('cursor', 'Cursor', TraitInputType.Select, [
|
|
1638
|
+
'auto', 'default', 'pointer', 'text', 'move', 'not-allowed',
|
|
1639
|
+
'grab', 'grabbing', 'crosshair', 'zoom-in', 'zoom-out', 'none',
|
|
1640
|
+
], 'auto'),
|
|
1641
|
+
]);
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
function flattenSchemaFields(properties, prefix = '') {
|
|
1645
|
+
const result = [];
|
|
1646
|
+
for (const [key, field] of Object.entries(properties)) {
|
|
1647
|
+
const fullPath = prefix ? `${prefix}.${key}` : key;
|
|
1648
|
+
if (field.type === 'object' && field.properties) {
|
|
1649
|
+
result.push(...flattenSchemaFields(field.properties, fullPath));
|
|
1650
|
+
}
|
|
1651
|
+
else {
|
|
1652
|
+
result.push({ label: fullPath, value: fullPath });
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
return result;
|
|
1442
1656
|
}
|
|
1443
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StyleRegistryService, decorators: [{
|
|
1444
|
-
type: Injectable
|
|
1445
|
-
}] });
|
|
1446
1657
|
|
|
1447
|
-
// Module-level counter — unique drop-list ID per Section instance across the whole app session.
|
|
1448
|
-
let dropListCounter = 0;
|
|
1449
1658
|
/**
|
|
1450
|
-
*
|
|
1451
|
-
* builder component with zero wrapper elements in the DOM.
|
|
1659
|
+
* StyleRegistryService — manages a single <style> tag for the builder canvas.
|
|
1452
1660
|
*
|
|
1453
|
-
*
|
|
1454
|
-
*
|
|
1455
|
-
*
|
|
1661
|
+
* Each builder component gets two CSS classes:
|
|
1662
|
+
* .iox-node-{id} — applied to the inner element; handles layout/visual props
|
|
1663
|
+
* (display, flex, background, border, padding, etc.)
|
|
1664
|
+
* .iox-outer-{id} — applied to the host element by RenderDirective; handles
|
|
1665
|
+
* properties that participate in the PARENT flow (margin,
|
|
1666
|
+
* align-self, flex-grow/shrink/basis, order).
|
|
1456
1667
|
*
|
|
1457
|
-
*
|
|
1458
|
-
*
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
1461
|
-
*
|
|
1462
|
-
*
|
|
1668
|
+
* This split is necessary because margin on an inner wrapper only adds internal
|
|
1669
|
+
* space — it does not push sibling elements. Applying margin to the host element
|
|
1670
|
+
* (which IS the flex/block child in the parent container) makes it work correctly.
|
|
1671
|
+
*
|
|
1672
|
+
* State styles (hover/active/focus) are stored under key `${nodeId}:${state}`
|
|
1673
|
+
* and compiled to `.iox-node-{id}:hover { … }` selectors.
|
|
1674
|
+
*
|
|
1675
|
+
* Design token variables are stored under the reserved key `__tokens__` and
|
|
1676
|
+
* compiled to a `:root { … }` block prepended to all other rules.
|
|
1677
|
+
*
|
|
1678
|
+
* Scoped to PageUiComponent.providers[] — one stylesheet per builder instance.
|
|
1463
1679
|
*/
|
|
1464
|
-
class
|
|
1465
|
-
constructor(
|
|
1466
|
-
this.
|
|
1467
|
-
this.
|
|
1680
|
+
class StyleRegistryService {
|
|
1681
|
+
constructor() {
|
|
1682
|
+
this.changes$ = new Subject();
|
|
1683
|
+
this.rules = new Map();
|
|
1684
|
+
this.styleEl = null;
|
|
1685
|
+
}
|
|
1686
|
+
/** Properties that must live on the wrapper element to affect the parent layout. */
|
|
1687
|
+
static { this.OUTER_PROPS = new Set([
|
|
1688
|
+
'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',
|
|
1689
|
+
'alignSelf', 'flexGrow', 'flexShrink', 'flexBasis', 'order',
|
|
1690
|
+
'width',
|
|
1691
|
+
]); }
|
|
1692
|
+
init() {
|
|
1693
|
+
this.styleEl = document.createElement('style');
|
|
1694
|
+
this.styleEl.id = 'iox-runtime-styles';
|
|
1695
|
+
document.head.appendChild(this.styleEl);
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* Write or update the base styles for a node, or a pseudo-class state override.
|
|
1699
|
+
*
|
|
1700
|
+
* @param nodeId The node's CSS id (used in `.iox-node-{nodeId}`)
|
|
1701
|
+
* @param styles Flat CSS property map (camelCase keys)
|
|
1702
|
+
* @param state Optional pseudo-class state ('hover' | 'active' | 'focus').
|
|
1703
|
+
* When provided, compiles to `.iox-node-{id}:{state} { … }`.
|
|
1704
|
+
* State rules are NOT partitioned into inner/outer.
|
|
1705
|
+
*/
|
|
1706
|
+
upsert(nodeId, styles, state) {
|
|
1707
|
+
if (!nodeId)
|
|
1708
|
+
return;
|
|
1709
|
+
if (state) {
|
|
1710
|
+
// Structural pseudo-classes (first-child, last-child, nth-child) target the
|
|
1711
|
+
// outer wrapper element so they participate correctly in grid/flex layout.
|
|
1712
|
+
const prefix = STRUCTURAL_STATES.includes(state) ? 'iox-outer' : 'iox-node';
|
|
1713
|
+
const css = this.compile(`${prefix}-${nodeId}:${state}`, styles);
|
|
1714
|
+
const key = `${nodeId}:${state}`;
|
|
1715
|
+
if (css) {
|
|
1716
|
+
this.rules.set(key, css);
|
|
1717
|
+
}
|
|
1718
|
+
else {
|
|
1719
|
+
this.rules.delete(key);
|
|
1720
|
+
}
|
|
1721
|
+
this.flush();
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
const inner = {};
|
|
1725
|
+
const outer = {};
|
|
1726
|
+
for (const [k, v] of Object.entries(styles)) {
|
|
1727
|
+
if (StyleRegistryService.OUTER_PROPS.has(k)) {
|
|
1728
|
+
outer[k] = v;
|
|
1729
|
+
}
|
|
1730
|
+
else {
|
|
1731
|
+
inner[k] = v;
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
const innerCss = this.compile(`iox-node-${nodeId}`, inner);
|
|
1735
|
+
const outerCss = this.compile(`iox-outer-${nodeId}`, outer);
|
|
1736
|
+
const combined = [innerCss, outerCss].filter(Boolean).join('\n');
|
|
1737
|
+
if (combined) {
|
|
1738
|
+
this.rules.set(nodeId, combined);
|
|
1739
|
+
}
|
|
1740
|
+
else {
|
|
1741
|
+
this.rules.delete(nodeId);
|
|
1742
|
+
}
|
|
1743
|
+
this.flush();
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* Write the org-level design token variables as a `:root { … }` block.
|
|
1747
|
+
* Token names should be CSS custom property names without the `--` prefix
|
|
1748
|
+
* (e.g., `{ 'iox-primary-color': '#cb9090' }`).
|
|
1749
|
+
* Pass an empty object to clear all tokens.
|
|
1750
|
+
*/
|
|
1751
|
+
upsertTokens(tokens) {
|
|
1752
|
+
const entries = Object.entries(tokens)
|
|
1753
|
+
.filter(([, v]) => v !== undefined && v !== null && v !== '')
|
|
1754
|
+
.map(([k, v]) => ` --${k}: ${v};`);
|
|
1755
|
+
if (entries.length) {
|
|
1756
|
+
this.rules.set('__tokens__', `:root {\n${entries.join('\n')}\n}`);
|
|
1757
|
+
}
|
|
1758
|
+
else {
|
|
1759
|
+
this.rules.delete('__tokens__');
|
|
1760
|
+
}
|
|
1761
|
+
this.flush();
|
|
1762
|
+
}
|
|
1763
|
+
remove(nodeId) {
|
|
1764
|
+
if (!nodeId)
|
|
1765
|
+
return;
|
|
1766
|
+
// Remove base rule and all state rules for this node
|
|
1767
|
+
this.rules.delete(nodeId);
|
|
1768
|
+
for (const key of this.rules.keys()) {
|
|
1769
|
+
if (key.startsWith(`${nodeId}:`)) {
|
|
1770
|
+
this.rules.delete(key);
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
this.flush();
|
|
1774
|
+
}
|
|
1775
|
+
destroy() {
|
|
1776
|
+
this.rules.clear();
|
|
1777
|
+
if (this.styleEl) {
|
|
1778
|
+
this.styleEl.remove();
|
|
1779
|
+
this.styleEl = null;
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
compile(className, styles) {
|
|
1783
|
+
const entries = Object.entries(styles)
|
|
1784
|
+
.filter(([, v]) => v !== undefined && v !== null && v !== '')
|
|
1785
|
+
.map(([k, v]) => ` ${this.toKebabCase(k)}: ${v};`);
|
|
1786
|
+
if (!entries.length)
|
|
1787
|
+
return '';
|
|
1788
|
+
return `.${className} {\n${entries.join('\n')}\n}`;
|
|
1789
|
+
}
|
|
1790
|
+
toKebabCase(str) {
|
|
1791
|
+
return str.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`);
|
|
1792
|
+
}
|
|
1793
|
+
flush() {
|
|
1794
|
+
if (!this.styleEl)
|
|
1795
|
+
return;
|
|
1796
|
+
// __tokens__ always first so variables are available to all subsequent rules
|
|
1797
|
+
const tokenBlock = this.rules.get('__tokens__');
|
|
1798
|
+
const rest = Array.from(this.rules.entries())
|
|
1799
|
+
.filter(([k]) => k !== '__tokens__')
|
|
1800
|
+
.map(([, v]) => v);
|
|
1801
|
+
this.styleEl.textContent = [tokenBlock, ...rest].filter(Boolean).join('\n');
|
|
1802
|
+
this.changes$.next();
|
|
1803
|
+
}
|
|
1804
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StyleRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1805
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StyleRegistryService }); }
|
|
1806
|
+
}
|
|
1807
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StyleRegistryService, decorators: [{
|
|
1808
|
+
type: Injectable
|
|
1809
|
+
}] });
|
|
1810
|
+
|
|
1811
|
+
// Module-level counter — unique drop-list ID per Section instance across the whole app session.
|
|
1812
|
+
let dropListCounter = 0;
|
|
1813
|
+
/**
|
|
1814
|
+
* RenderDirective — applied to <ng-container> to dynamically instantiate a
|
|
1815
|
+
* builder component with zero wrapper elements in the DOM.
|
|
1816
|
+
*
|
|
1817
|
+
* A directive's ViewContainerRef inserts the created component's host element as
|
|
1818
|
+
* a sibling of the ng-container comment node — directly inside the parent element
|
|
1819
|
+
* — so the resulting DOM has no extra <app-renderer> wrapper.
|
|
1820
|
+
*
|
|
1821
|
+
* Usage:
|
|
1822
|
+
* <ng-container [ioxRender]="node"
|
|
1823
|
+
* (onClick)="handleClick($event)"
|
|
1824
|
+
* (onMouseEnter)="handleMouseEnter($event)"
|
|
1825
|
+
* (onMouseLeave)="handleMouseLeave()">
|
|
1826
|
+
* </ng-container>
|
|
1827
|
+
*/
|
|
1828
|
+
class RenderDirective {
|
|
1829
|
+
constructor(vcr, injector, registryService, overlayService, styleRegistry, interactionEngine, cdr, panelEventService) {
|
|
1830
|
+
this.vcr = vcr;
|
|
1831
|
+
this.injector = injector;
|
|
1468
1832
|
this.registryService = registryService;
|
|
1469
1833
|
this.overlayService = overlayService;
|
|
1470
1834
|
this.styleRegistry = styleRegistry;
|
|
@@ -3825,363 +4189,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
3825
4189
|
args: [PanelChildComponent]
|
|
3826
4190
|
}] } });
|
|
3827
4191
|
|
|
3828
|
-
var StyleCategory;
|
|
3829
|
-
(function (StyleCategory) {
|
|
3830
|
-
StyleCategory["Layout"] = "Layout";
|
|
3831
|
-
StyleCategory["Size"] = "Size";
|
|
3832
|
-
StyleCategory["Typography"] = "Typography";
|
|
3833
|
-
StyleCategory["Spacing"] = "Spacing";
|
|
3834
|
-
StyleCategory["Border"] = "Border";
|
|
3835
|
-
StyleCategory["Position"] = "Position";
|
|
3836
|
-
StyleCategory["Background"] = "Background";
|
|
3837
|
-
StyleCategory["Effects"] = "Effects";
|
|
3838
|
-
// Legacy — kept for backward compat; prefer Size
|
|
3839
|
-
StyleCategory["Dimensions"] = "Dimensions";
|
|
3840
|
-
})(StyleCategory || (StyleCategory = {}));
|
|
3841
|
-
const TRIGGER_OPTIONS = [
|
|
3842
|
-
{ value: 'pageLoad', label: 'Page load', icon: 'ph-thin ph-play' },
|
|
3843
|
-
{ value: 'viewportEnter', label: 'Enter viewport', icon: 'ph-thin ph-eye' },
|
|
3844
|
-
{ value: 'click', label: 'Click', icon: 'ph-thin ph-cursor-click' },
|
|
3845
|
-
{ value: 'hover', label: 'Hover', icon: 'ph-thin ph-hand-pointing' },
|
|
3846
|
-
{ value: 'scrollProgress', label: 'Scroll progress', icon: 'ph-thin ph-arrow-fat-lines-down' },
|
|
3847
|
-
];
|
|
3848
|
-
const ACTION_TYPE_OPTIONS = [
|
|
3849
|
-
{ value: 'fadeIn', label: 'Fade in' },
|
|
3850
|
-
{ value: 'fadeOut', label: 'Fade out' },
|
|
3851
|
-
{ value: 'moveUp', label: 'Move up' },
|
|
3852
|
-
{ value: 'moveDown', label: 'Move down' },
|
|
3853
|
-
{ value: 'moveLeft', label: 'Move left' },
|
|
3854
|
-
{ value: 'moveRight', label: 'Move right' },
|
|
3855
|
-
{ value: 'scaleIn', label: 'Scale in' },
|
|
3856
|
-
{ value: 'scaleOut', label: 'Scale out' },
|
|
3857
|
-
{ value: 'rotate', label: 'Rotate' },
|
|
3858
|
-
{ value: 'show', label: 'Show' },
|
|
3859
|
-
{ value: 'hide', label: 'Hide' },
|
|
3860
|
-
{ value: 'toggleVisibility', label: 'Toggle visibility' },
|
|
3861
|
-
];
|
|
3862
|
-
const EASING_OPTIONS = ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'];
|
|
3863
|
-
const SUPPORTED_STATES = ['hover', 'active', 'focus'];
|
|
3864
|
-
/**
|
|
3865
|
-
* Build a full StyleTraitGroup[] schema populated with values from a flat
|
|
3866
|
-
* styleProps map. Used when editing a preset in the Style panel — the panel
|
|
3867
|
-
* receives the same `StyleTraitGroup[]` shape regardless of context.
|
|
3868
|
-
*/
|
|
3869
|
-
function buildPresetStyleTraits(styleProps) {
|
|
3870
|
-
const allGroups = [
|
|
3871
|
-
new LayoutGroupStyleConfig(),
|
|
3872
|
-
new SizeGroupStyleConfig(),
|
|
3873
|
-
new BackgroundGroupStyleConfig(),
|
|
3874
|
-
new SpacingGroupStyleConfig(),
|
|
3875
|
-
new BorderGroupStyleConfig(),
|
|
3876
|
-
new TypographyGroupStyleConfig(),
|
|
3877
|
-
new EffectsGroupStyleConfig(),
|
|
3878
|
-
new PositionGroupStyleConfig(),
|
|
3879
|
-
];
|
|
3880
|
-
return allGroups.map(group => ({
|
|
3881
|
-
...group,
|
|
3882
|
-
traits: group.traits.map(trait => ({
|
|
3883
|
-
...trait,
|
|
3884
|
-
default: styleProps[trait.name] !== undefined ? styleProps[trait.name] : trait.default,
|
|
3885
|
-
})),
|
|
3886
|
-
}));
|
|
3887
|
-
}
|
|
3888
|
-
var TraitInputType;
|
|
3889
|
-
(function (TraitInputType) {
|
|
3890
|
-
TraitInputType["Text"] = "text";
|
|
3891
|
-
TraitInputType["Number"] = "number";
|
|
3892
|
-
TraitInputType["Select"] = "select";
|
|
3893
|
-
TraitInputType["Checkbox"] = "checkbox";
|
|
3894
|
-
TraitInputType["Color"] = "colorPicker";
|
|
3895
|
-
TraitInputType["DirectionalSize"] = "directionalSize";
|
|
3896
|
-
TraitInputType["SelectButton"] = "selectButton";
|
|
3897
|
-
TraitInputType["Scrub"] = "scrub";
|
|
3898
|
-
TraitInputType["Icon"] = "icon";
|
|
3899
|
-
TraitInputType["Media"] = "media";
|
|
3900
|
-
TraitInputType["FontFamily"] = "fontFamily";
|
|
3901
|
-
TraitInputType["GridTemplate"] = "gridTemplate";
|
|
3902
|
-
})(TraitInputType || (TraitInputType = {}));
|
|
3903
|
-
function generateNodeId() {
|
|
3904
|
-
return Math.random().toString(36).substr(2, 9);
|
|
3905
|
-
}
|
|
3906
|
-
class ComponentConfig {
|
|
3907
|
-
constructor(type, selector, icon = 'ph-thin ph-cube', category = 'General') {
|
|
3908
|
-
this.id = generateNodeId();
|
|
3909
|
-
this.type = type;
|
|
3910
|
-
this.selector = selector;
|
|
3911
|
-
this.icon = icon;
|
|
3912
|
-
this.category = category;
|
|
3913
|
-
this.inputs = {};
|
|
3914
|
-
this.traits = [];
|
|
3915
|
-
this.styleTraits = [];
|
|
3916
|
-
}
|
|
3917
|
-
/** Override specific trait defaults after styleTraits are set.
|
|
3918
|
-
* Call this at the end of each subclass constructor. */
|
|
3919
|
-
applyStyleDefaults(defaults) {
|
|
3920
|
-
for (const group of this.styleTraits) {
|
|
3921
|
-
for (const trait of group.traits) {
|
|
3922
|
-
if (defaults[trait.name] !== undefined) {
|
|
3923
|
-
trait.default = defaults[trait.name];
|
|
3924
|
-
}
|
|
3925
|
-
}
|
|
3926
|
-
}
|
|
3927
|
-
}
|
|
3928
|
-
}
|
|
3929
|
-
class TraitConfig {
|
|
3930
|
-
constructor(name, label, type, options, defaultValue, inline, showWhen) {
|
|
3931
|
-
this.name = name;
|
|
3932
|
-
this.label = label;
|
|
3933
|
-
this.type = type;
|
|
3934
|
-
this.options = options;
|
|
3935
|
-
this.default = defaultValue;
|
|
3936
|
-
this.inline = inline;
|
|
3937
|
-
this.showWhen = showWhen;
|
|
3938
|
-
}
|
|
3939
|
-
}
|
|
3940
|
-
class GroupStyleConfig {
|
|
3941
|
-
constructor(category, traits) {
|
|
3942
|
-
this.category = category;
|
|
3943
|
-
this.traits = traits;
|
|
3944
|
-
}
|
|
3945
|
-
}
|
|
3946
|
-
// ─── Unit constants ───────────────────────────────────────────────────────────
|
|
3947
|
-
const UNITS_ALL = ['px', '%', 'rem', 'em', 'vw', 'vh'];
|
|
3948
|
-
const UNITS_NO_VW = ['px', '%', 'rem', 'em', 'vh'];
|
|
3949
|
-
const UNITS_FIXED = ['px', '%', 'rem', 'em'];
|
|
3950
|
-
const UNITS_DEG = ['deg'];
|
|
3951
|
-
// ─── Shared panel utilities ──────────────────────────────────────────────────
|
|
3952
|
-
function resolveTraitControllerType(type) {
|
|
3953
|
-
switch (type) {
|
|
3954
|
-
case TraitInputType.Number: return 'number';
|
|
3955
|
-
case TraitInputType.Select: return 'select';
|
|
3956
|
-
case TraitInputType.Checkbox: return 'switch';
|
|
3957
|
-
case TraitInputType.Color: return 'colorPicker';
|
|
3958
|
-
case TraitInputType.DirectionalSize: return 'directionalSize';
|
|
3959
|
-
case TraitInputType.SelectButton: return 'selectButton';
|
|
3960
|
-
case TraitInputType.Scrub: return 'scrub';
|
|
3961
|
-
case TraitInputType.Icon: return 'icon';
|
|
3962
|
-
case TraitInputType.Media: return 'media';
|
|
3963
|
-
case TraitInputType.FontFamily: return 'select';
|
|
3964
|
-
case TraitInputType.GridTemplate: return 'gridTemplate';
|
|
3965
|
-
default: return 'text';
|
|
3966
|
-
}
|
|
3967
|
-
}
|
|
3968
|
-
function resolveTraitOptions(trait) {
|
|
3969
|
-
if (trait.type === TraitInputType.Color ||
|
|
3970
|
-
trait.type === TraitInputType.DirectionalSize ||
|
|
3971
|
-
trait.type === TraitInputType.SelectButton ||
|
|
3972
|
-
trait.type === TraitInputType.Scrub ||
|
|
3973
|
-
trait.type === TraitInputType.Media) {
|
|
3974
|
-
return trait.options;
|
|
3975
|
-
}
|
|
3976
|
-
if (trait.type === TraitInputType.FontFamily) {
|
|
3977
|
-
// FontFamily options are injected dynamically by the style panel via FontManagerService.
|
|
3978
|
-
// Return empty array here; the panel overrides this in resolveOptions().
|
|
3979
|
-
return [];
|
|
3980
|
-
}
|
|
3981
|
-
if (trait.type !== TraitInputType.Select) {
|
|
3982
|
-
return undefined;
|
|
3983
|
-
}
|
|
3984
|
-
const opts = trait.options ?? [];
|
|
3985
|
-
// Already formatted as {label, value}[]
|
|
3986
|
-
if (opts.length > 0 && typeof opts[0] === 'object' && 'label' in opts[0]) {
|
|
3987
|
-
return opts;
|
|
3988
|
-
}
|
|
3989
|
-
return opts.map((option) => ({ label: option, value: option }));
|
|
3990
|
-
}
|
|
3991
|
-
// ─── Style Groups ─────────────────────────────────────────────────────────────
|
|
3992
|
-
const NON_STATIC_POSITIONS = ['relative', 'absolute', 'fixed', 'sticky'];
|
|
3993
|
-
class PositionGroupStyleConfig extends GroupStyleConfig {
|
|
3994
|
-
constructor() {
|
|
3995
|
-
super(StyleCategory.Position, [
|
|
3996
|
-
new TraitConfig('position', 'Position', TraitInputType.Select, ['static', 'relative', 'absolute', 'fixed', 'sticky'], 'static'),
|
|
3997
|
-
new TraitConfig('top', 'T', TraitInputType.Scrub, { min: -9999, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
3998
|
-
new TraitConfig('right', 'R', TraitInputType.Scrub, { min: -9999, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
3999
|
-
new TraitConfig('bottom', 'B', TraitInputType.Scrub, { min: -9999, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
4000
|
-
new TraitConfig('left', 'L', TraitInputType.Scrub, { min: -9999, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
4001
|
-
new TraitConfig('zIndex', 'Z', TraitInputType.Scrub, { min: -99, max: 9999, step: 1, units: [''] }, '0', false, { trait: 'position', values: NON_STATIC_POSITIONS }),
|
|
4002
|
-
]);
|
|
4003
|
-
}
|
|
4004
|
-
}
|
|
4005
|
-
// ─── Layout ───────────────────────────────────────────────────────────────────
|
|
4006
|
-
class LayoutGroupStyleConfig extends GroupStyleConfig {
|
|
4007
|
-
constructor() {
|
|
4008
|
-
super(StyleCategory.Layout, [
|
|
4009
|
-
new TraitConfig('display', 'Display', TraitInputType.Select, ['block', 'inline', 'inline-block', 'flex', 'grid'], 'block'),
|
|
4010
|
-
// ── Flex-only ─────────────────────────────────────────────────────
|
|
4011
|
-
new TraitConfig('flexDirection', 'Direction', TraitInputType.SelectButton, [
|
|
4012
|
-
{ value: 'row', label: 'Horizontal', icon: 'ph-thin ph-arrow-right' },
|
|
4013
|
-
{ value: 'row-reverse', label: 'Horizontal Reversed', icon: 'ph-thin ph-arrow-left' },
|
|
4014
|
-
{ value: 'column', label: 'Vertical', icon: 'ph-thin ph-arrow-down' },
|
|
4015
|
-
{ value: 'column-reverse', label: 'Vertical Reversed', icon: 'ph-thin ph-arrow-up' },
|
|
4016
|
-
], 'row', false, { trait: 'display', values: 'flex' }),
|
|
4017
|
-
new TraitConfig('flexWrap', 'Flex Wrap', TraitInputType.SelectButton, [
|
|
4018
|
-
{ value: 'nowrap', label: 'No Wrap', icon: 'ph-thin ph-minus' },
|
|
4019
|
-
{ value: 'wrap', label: 'Wrap', icon: 'ph-thin ph-arrow-elbow-down-right' },
|
|
4020
|
-
{ value: 'wrap-reverse', label: 'Wrap Reversed', icon: 'ph-thin ph-arrow-elbow-up-right' },
|
|
4021
|
-
], 'nowrap', false, { trait: 'display', values: 'flex' }),
|
|
4022
|
-
// ── Shared flex + grid ────────────────────────────────────────────
|
|
4023
|
-
new TraitConfig('justifyContent', 'Justify', TraitInputType.SelectButton, [
|
|
4024
|
-
{ value: 'flex-start', label: 'Start', icon: 'ph-thin ph-align-left' },
|
|
4025
|
-
{ value: 'center', label: 'Center', icon: 'ph-thin ph-align-center-horizontal' },
|
|
4026
|
-
{ value: 'flex-end', label: 'End', icon: 'ph-thin ph-align-right' },
|
|
4027
|
-
{ value: 'space-between', label: 'Space Between', icon: 'ph-thin ph-distribute-horizontal' },
|
|
4028
|
-
{ value: 'space-around', label: 'Space Around', icon: 'ph-thin ph-dots-three' },
|
|
4029
|
-
{ value: 'space-evenly', label: 'Space Evenly', icon: 'ph-thin ph-dots-six' },
|
|
4030
|
-
], 'flex-start', false, { trait: 'display', values: ['flex', 'grid'] }),
|
|
4031
|
-
new TraitConfig('alignItems', 'Align Items', TraitInputType.SelectButton, [
|
|
4032
|
-
{ value: 'stretch', label: 'Stretch', icon: 'ph-thin ph-arrows-vertical' },
|
|
4033
|
-
{ value: 'start', label: 'Start', icon: 'ph-thin ph-align-top' },
|
|
4034
|
-
{ value: 'center', label: 'Center', icon: 'ph-thin ph-align-center-vertical' },
|
|
4035
|
-
{ value: 'end', label: 'End', icon: 'ph-thin ph-align-bottom' },
|
|
4036
|
-
], 'stretch', false, { trait: 'display', values: ['flex', 'grid'] }),
|
|
4037
|
-
new TraitConfig('gap', 'Gap', TraitInputType.Scrub, { min: 0, max: 200, step: 1, units: UNITS_FIXED }, '0px', false, { trait: 'display', values: ['flex', 'grid'] }),
|
|
4038
|
-
// ── Grid-only ─────────────────────────────────────────────────────
|
|
4039
|
-
new TraitConfig('gridTemplateColumns', 'Columns', TraitInputType.GridTemplate, undefined, '1fr', false, { trait: 'display', values: 'grid' }),
|
|
4040
|
-
new TraitConfig('gridTemplateRows', 'Rows', TraitInputType.GridTemplate, undefined, 'auto', false, { trait: 'display', values: 'grid' }),
|
|
4041
|
-
new TraitConfig('justifyItems', 'Justify Items', TraitInputType.SelectButton, [
|
|
4042
|
-
{ value: 'stretch', label: 'Stretch', icon: 'ph-thin ph-arrows-horizontal' },
|
|
4043
|
-
{ value: 'start', label: 'Start', icon: 'ph-thin ph-align-left' },
|
|
4044
|
-
{ value: 'center', label: 'Center', icon: 'ph-thin ph-align-center-horizontal' },
|
|
4045
|
-
{ value: 'end', label: 'End', icon: 'ph-thin ph-align-right' },
|
|
4046
|
-
], 'stretch', false, { trait: 'display', values: 'grid' }),
|
|
4047
|
-
new TraitConfig('alignContent', 'Align Content', TraitInputType.SelectButton, [
|
|
4048
|
-
{ value: 'start', label: 'Start', icon: 'ph-thin ph-align-top' },
|
|
4049
|
-
{ value: 'center', label: 'Center', icon: 'ph-thin ph-align-center-vertical' },
|
|
4050
|
-
{ value: 'end', label: 'End', icon: 'ph-thin ph-align-bottom' },
|
|
4051
|
-
{ value: 'space-between', label: 'Space Between', icon: 'ph-thin ph-distribute-vertical' },
|
|
4052
|
-
{ value: 'space-around', label: 'Space Around', icon: 'ph-thin ph-dots-three' },
|
|
4053
|
-
{ value: 'stretch', label: 'Stretch', icon: 'ph-thin ph-arrows-vertical' },
|
|
4054
|
-
], 'stretch', false, { trait: 'display', values: 'grid' }),
|
|
4055
|
-
// ── Direction (always visible) ────────────────────────────────────
|
|
4056
|
-
new TraitConfig('direction', 'Text Direction', TraitInputType.SelectButton, [
|
|
4057
|
-
{ value: 'ltr', label: 'LTR' },
|
|
4058
|
-
{ value: 'rtl', label: 'RTL' },
|
|
4059
|
-
], 'ltr'),
|
|
4060
|
-
]);
|
|
4061
|
-
}
|
|
4062
|
-
}
|
|
4063
|
-
// ─── Size (replaces Dimensions) ───────────────────────────────────────────────
|
|
4064
|
-
class SizeGroupStyleConfig extends GroupStyleConfig {
|
|
4065
|
-
constructor() {
|
|
4066
|
-
super(StyleCategory.Size, [
|
|
4067
|
-
new TraitConfig('width', 'W', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
4068
|
-
new TraitConfig('height', 'H', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
4069
|
-
new TraitConfig('minWidth', 'Min W', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
4070
|
-
new TraitConfig('minHeight', 'Min H', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
4071
|
-
new TraitConfig('maxWidth', 'Max W', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
4072
|
-
new TraitConfig('maxHeight', 'Max H', TraitInputType.Scrub, { min: 0, max: 9999, step: 1, units: UNITS_ALL, allowAuto: true }, 'auto', true),
|
|
4073
|
-
new TraitConfig('aspectRatio', 'Aspect Ratio', TraitInputType.Text, undefined, 'auto'),
|
|
4074
|
-
]);
|
|
4075
|
-
}
|
|
4076
|
-
}
|
|
4077
|
-
/** @deprecated Use SizeGroupStyleConfig instead. */
|
|
4078
|
-
class DimensionsGroupStyleConfig extends SizeGroupStyleConfig {
|
|
4079
|
-
}
|
|
4080
|
-
// ─── Background ───────────────────────────────────────────────────────────────
|
|
4081
|
-
class BackgroundGroupStyleConfig extends GroupStyleConfig {
|
|
4082
|
-
constructor() {
|
|
4083
|
-
super(StyleCategory.Background, [
|
|
4084
|
-
new TraitConfig('backgroundColor', 'Background', TraitInputType.Color, { allowGradient: true, allowTransparent: true, formats: ['hex', 'rgb', 'hsl', 'transparent'] }, 'transparent'),
|
|
4085
|
-
]);
|
|
4086
|
-
}
|
|
4087
|
-
}
|
|
4088
|
-
class SpacingGroupStyleConfig extends GroupStyleConfig {
|
|
4089
|
-
constructor() {
|
|
4090
|
-
super(StyleCategory.Spacing, [
|
|
4091
|
-
new TraitConfig('margin', 'Margin', TraitInputType.DirectionalSize, {
|
|
4092
|
-
allowNegative: true,
|
|
4093
|
-
allowLinkedSlider: true,
|
|
4094
|
-
slider: { min: 0, max: 200, step: 1 }
|
|
4095
|
-
}, '0px 0px 0px 0px'),
|
|
4096
|
-
new TraitConfig('padding', 'Padding', TraitInputType.DirectionalSize, {
|
|
4097
|
-
allowNegative: false,
|
|
4098
|
-
allowLinkedSlider: true,
|
|
4099
|
-
slider: { min: 0, max: 200, step: 1 }
|
|
4100
|
-
}, '0px 0px 0px 0px')
|
|
4101
|
-
]);
|
|
4102
|
-
}
|
|
4103
|
-
}
|
|
4104
|
-
class BorderGroupStyleConfig extends GroupStyleConfig {
|
|
4105
|
-
constructor() {
|
|
4106
|
-
super(StyleCategory.Border, [
|
|
4107
|
-
new TraitConfig('borderWidth', 'Border Width', TraitInputType.DirectionalSize, {
|
|
4108
|
-
units: UNITS_FIXED,
|
|
4109
|
-
allowNegative: false,
|
|
4110
|
-
allowLinkedSlider: true,
|
|
4111
|
-
slider: { min: 0, max: 32, step: 1 }
|
|
4112
|
-
}, '0px'),
|
|
4113
|
-
new TraitConfig('borderStyle', 'Border Style', TraitInputType.SelectButton, [
|
|
4114
|
-
{ value: 'solid', icon: 'ph-thin ph-line-segment' },
|
|
4115
|
-
{ value: 'dashed', icon: 'ph-thin ph-dots-three' },
|
|
4116
|
-
{ value: 'dotted', icon: 'ph-thin ph-dots-six' },
|
|
4117
|
-
], 'solid'),
|
|
4118
|
-
new TraitConfig('borderColor', 'Border Color', TraitInputType.Color, { allowGradient: false, allowTransparent: false, formats: ['hex', 'rgb', 'hsl'] }, '#CCCCCC'),
|
|
4119
|
-
new TraitConfig('borderRadius', 'Border Radius', TraitInputType.DirectionalSize, {
|
|
4120
|
-
units: UNITS_FIXED,
|
|
4121
|
-
allowNegative: false,
|
|
4122
|
-
allowLinkedSlider: true,
|
|
4123
|
-
linkByDefault: true,
|
|
4124
|
-
slider: { min: 0, max: 120, step: 1 },
|
|
4125
|
-
segments: [
|
|
4126
|
-
{ key: 'top-left', icon: 'ph-arrow-bend-up-left', ariaLabel: 'top left radius' },
|
|
4127
|
-
{ key: 'top-right', icon: 'ph-arrow-bend-up-right', ariaLabel: 'top right radius' },
|
|
4128
|
-
{ key: 'bottom-right', icon: 'ph-arrow-bend-down-right', ariaLabel: 'bottom right radius' },
|
|
4129
|
-
{ key: 'bottom-left', icon: 'ph-arrow-bend-down-left', ariaLabel: 'bottom left radius' }
|
|
4130
|
-
]
|
|
4131
|
-
}, '0px')
|
|
4132
|
-
]);
|
|
4133
|
-
}
|
|
4134
|
-
}
|
|
4135
|
-
class TypographyGroupStyleConfig extends GroupStyleConfig {
|
|
4136
|
-
constructor() {
|
|
4137
|
-
super(StyleCategory.Typography, [
|
|
4138
|
-
new TraitConfig('fontFamily', 'Font Family', TraitInputType.FontFamily, [], 'Poppins, sans-serif'),
|
|
4139
|
-
new TraitConfig('fontSize', 'Font Size', TraitInputType.Scrub, { min: 8, max: 200, step: 1, units: UNITS_FIXED }, '16px'),
|
|
4140
|
-
new TraitConfig('fontWeight', 'Font Weight', TraitInputType.Select, ['100', '200', '300', '400', '500', '600', '700', '800', '900'], '400'),
|
|
4141
|
-
new TraitConfig('color', 'Color', TraitInputType.Color, { allowGradient: false, allowTransparent: false, formats: ['hex', 'rgb', 'hsl'] }, '#000000'),
|
|
4142
|
-
new TraitConfig('lineHeight', 'Line Height', TraitInputType.Select, ['1', '1.2', '1.4', '1.5', '1.75', '2', '2.5'], '1.5'),
|
|
4143
|
-
new TraitConfig('letterSpacing', 'Letter Spacing', TraitInputType.Scrub, { min: -5, max: 50, step: 0.5, units: UNITS_FIXED }, '0px'),
|
|
4144
|
-
new TraitConfig('textAlign', 'Alignment', TraitInputType.SelectButton, [
|
|
4145
|
-
{ value: 'left', icon: 'ph-thin ph-text-align-left' },
|
|
4146
|
-
{ value: 'center', icon: 'ph-thin ph-text-align-center' },
|
|
4147
|
-
{ value: 'right', icon: 'ph-thin ph-text-align-right' },
|
|
4148
|
-
{ value: 'justify', icon: 'ph-thin ph-text-align-justify' },
|
|
4149
|
-
], 'left'),
|
|
4150
|
-
new TraitConfig('fontStyle', 'Italic', TraitInputType.SelectButton, { items: [{ value: 'italic', icon: 'ph-thin ph-text-italic', label: 'Italic' }], allowEmpty: true, noneValue: 'normal' }, 'normal', true),
|
|
4151
|
-
new TraitConfig('textDecoration', 'Underline', TraitInputType.SelectButton, { items: [{ value: 'underline', icon: 'ph-thin ph-text-underline', label: 'Underline' }], allowEmpty: true, noneValue: 'none' }, 'none', true),
|
|
4152
|
-
]);
|
|
4153
|
-
}
|
|
4154
|
-
}
|
|
4155
|
-
class EffectsGroupStyleConfig extends GroupStyleConfig {
|
|
4156
|
-
constructor() {
|
|
4157
|
-
super(StyleCategory.Effects, [
|
|
4158
|
-
new TraitConfig('opacity', 'Opacity', TraitInputType.Scrub, { min: 0, max: 1, step: 0.01, units: [''] }, '1'),
|
|
4159
|
-
new TraitConfig('mixBlendMode', 'Blend Mode', TraitInputType.Select, [
|
|
4160
|
-
'normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten',
|
|
4161
|
-
'color-dodge', 'color-burn', 'hard-light', 'soft-light',
|
|
4162
|
-
'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity',
|
|
4163
|
-
], 'normal'),
|
|
4164
|
-
new TraitConfig('cursor', 'Cursor', TraitInputType.Select, [
|
|
4165
|
-
'auto', 'default', 'pointer', 'text', 'move', 'not-allowed',
|
|
4166
|
-
'grab', 'grabbing', 'crosshair', 'zoom-in', 'zoom-out', 'none',
|
|
4167
|
-
], 'auto'),
|
|
4168
|
-
]);
|
|
4169
|
-
}
|
|
4170
|
-
}
|
|
4171
|
-
function flattenSchemaFields(properties, prefix = '') {
|
|
4172
|
-
const result = [];
|
|
4173
|
-
for (const [key, field] of Object.entries(properties)) {
|
|
4174
|
-
const fullPath = prefix ? `${prefix}.${key}` : key;
|
|
4175
|
-
if (field.type === 'object' && field.properties) {
|
|
4176
|
-
result.push(...flattenSchemaFields(field.properties, fullPath));
|
|
4177
|
-
}
|
|
4178
|
-
else {
|
|
4179
|
-
result.push({ label: fullPath, value: fullPath });
|
|
4180
|
-
}
|
|
4181
|
-
}
|
|
4182
|
-
return result;
|
|
4183
|
-
}
|
|
4184
|
-
|
|
4185
4192
|
class InteractionsPanelComponent {
|
|
4186
4193
|
constructor(overlayService) {
|
|
4187
4194
|
this.overlayService = overlayService;
|
|
@@ -4872,5 +4879,5 @@ class TextBlockComponentConfig extends ComponentConfig {
|
|
|
4872
4879
|
* Generated bundle index. Do not edit.
|
|
4873
4880
|
*/
|
|
4874
4881
|
|
|
4875
|
-
export { ACTION_TYPE_OPTIONS, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ComponentConfig, ComponentRegistryService, DEVICE_OPTIONS, DataSourceRegistryService, DeviceMode, DragEngineService, EASING_OPTIONS$1 as EASING_OPTIONS, GroupStyleConfig, IOX_CONTENT_SERVICE, IOX_FONT_MANAGER, InteractionEngineService, InteractionsPanelComponent, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LayerTreeComponent, NodeAction, OverlayComponent, OverlayService, PanelChildComponent, PanelComponent, PanelEventService, PanelEventTypes, PanelTypes, PresetRegistryService, ROUTE_ANIMATION_OPTIONS, RenderDirective, RepeaterComponentConfig, SCREEN_WIDTH_OPTIONS, SUPPORTED_STATES, SectionComponent, SectionComponentConfig, StyleCategory, StyleRegistryService, TraitConfig as StyleTraitConfig, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, ViewportService, ZOOM_OPTIONS, buildPresetStyleTraits, defaultPageSettings, generateNodeId, resolveTraitControllerType, resolveTraitOptions };
|
|
4882
|
+
export { ACTION_TYPE_OPTIONS, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ComponentConfig, ComponentRegistryService, DEVICE_OPTIONS, DataSourceRegistryService, DeviceMode, DragEngineService, EASING_OPTIONS$1 as EASING_OPTIONS, GroupStyleConfig, INTERACTION_STATES, IOX_CONTENT_SERVICE, IOX_FONT_MANAGER, InteractionEngineService, InteractionsPanelComponent, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LayerTreeComponent, NodeAction, OverlayComponent, OverlayService, PanelChildComponent, PanelComponent, PanelEventService, PanelEventTypes, PanelTypes, PresetRegistryService, ROUTE_ANIMATION_OPTIONS, RenderDirective, RepeaterComponentConfig, SCREEN_WIDTH_OPTIONS, STRUCTURAL_STATES, SUPPORTED_STATES, SectionComponent, SectionComponentConfig, StyleCategory, StyleRegistryService, TraitConfig as StyleTraitConfig, TRIGGER_OPTIONS, TextBlockComponentConfig, ToolbarAction, ToolbarComponent, TraitConfig, TraitInputType, UNITS_ALL, UNITS_DEG, UNITS_FIXED, UNITS_NO_VW, ViewportService, ZOOM_OPTIONS, buildPresetStyleTraits, defaultPageSettings, generateNodeId, resolveTraitControllerType, resolveTraitOptions };
|
|
4876
4883
|
//# sourceMappingURL=vectoriox-iox-builder.mjs.map
|