@vectoriox/iox-builder 1.4.30 → 1.4.32

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.
@@ -314,6 +314,8 @@ class DragEngineService {
314
314
  this.ids$ = new BehaviorSubject([]);
315
315
  this.isDragging$ = new BehaviorSubject(false);
316
316
  this.deepTarget$ = new BehaviorSubject(null);
317
+ /** Emits the dropped/inserted ComponentNode after every successful drop. */
318
+ this.dropComplete$ = new Subject();
317
319
  // ── Active drag state ─────────────────────────────────────
318
320
  this._isDragging = false;
319
321
  this._payload = null;
@@ -355,6 +357,7 @@ class DragEngineService {
355
357
  if (config) {
356
358
  children.splice(insertIndex, 0, config);
357
359
  cdr.detectChanges();
360
+ this.dropComplete$.next(config);
358
361
  }
359
362
  afterDrop?.();
360
363
  return;
@@ -369,15 +372,19 @@ class DragEngineService {
369
372
  this.getCdr(payload.sourceId)?.detectChanges();
370
373
  }
371
374
  children.splice(insertIndex, 0, item);
375
+ cdr.detectChanges();
376
+ this.dropComplete$.next(item);
372
377
  }
373
378
  else {
374
379
  // Source not in the drop-zone registry → came from an external panel
375
380
  // (e.g. the built-in blocks panel stores one pre-built node object and
376
381
  // reuses it across drags). Deep-clone with fresh IDs so each drop
377
382
  // produces a fully independent node, preventing shared CSS rules.
378
- children.splice(insertIndex, 0, deepCloneNode(item));
383
+ const cloned = deepCloneNode(item);
384
+ children.splice(insertIndex, 0, cloned);
385
+ cdr.detectChanges();
386
+ this.dropComplete$.next(cloned);
379
387
  }
380
- cdr.detectChanges();
381
388
  afterDrop?.();
382
389
  return;
383
390
  }
@@ -387,6 +394,7 @@ class DragEngineService {
387
394
  children.splice(currentIdx, 1);
388
395
  children.splice(adjustedIdx, 0, item);
389
396
  cdr.detectChanges();
397
+ this.dropComplete$.next(item);
390
398
  }
391
399
  afterDrop?.();
392
400
  }
@@ -1484,12 +1492,18 @@ const TRANSFORM_FUNS = [
1484
1492
  ['skewX', 'skewX', '0deg'],
1485
1493
  ['skewY', 'skewY', '0deg'],
1486
1494
  ];
1495
+ // ─── ::marker pseudo-element ─────────────────────────────────────────────────
1496
+ const MARKER_FUNS = [
1497
+ ['markerColor', 'color'],
1498
+ ['markerFontSize', 'fontSize'],
1499
+ ];
1487
1500
  // ─── All virtual trait names ──────────────────────────────────────────────────
1488
1501
  const VIRTUAL_TRAIT_KEYS = new Set([
1489
1502
  ...FILTER_FUNS.map(([t]) => t),
1490
1503
  ...BACKDROP_FUNS.map(([t]) => t),
1491
1504
  ...TRANSFORM_FUNS.map(([t]) => t),
1492
1505
  'transitionDuration', 'transitionTimingFunction', 'transitionDelay',
1506
+ ...MARKER_FUNS.map(([t]) => t),
1493
1507
  ]);
1494
1508
  // ─── Helpers ─────────────────────────────────────────────────────────────────
1495
1509
  function buildFns(funs, src) {
@@ -1541,6 +1555,17 @@ function composeVirtualTraits(raw, base = raw) {
1541
1555
  const delPart = del && del !== '0ms' && del !== '0s' ? ` ${del}` : '';
1542
1556
  result['transition'] = `all ${dur} ${ease}${delPart}`;
1543
1557
  }
1558
+ // ::marker pseudo-element — collected into __markerStyles so StyleRegistryService
1559
+ // can emit a separate `.iox-node-{id}::marker { … }` rule.
1560
+ const markerStyles = {};
1561
+ for (const [trait, cssProp] of MARKER_FUNS) {
1562
+ const val = raw[trait] ?? base[trait];
1563
+ if (val != null && val !== '')
1564
+ markerStyles[cssProp] = val;
1565
+ }
1566
+ if (Object.keys(markerStyles).length) {
1567
+ result['__markerStyles'] = markerStyles;
1568
+ }
1544
1569
  return result;
1545
1570
  }
1546
1571
 
@@ -1554,6 +1579,7 @@ var StyleCategory;
1554
1579
  StyleCategory["Position"] = "Position";
1555
1580
  StyleCategory["Background"] = "Background";
1556
1581
  StyleCategory["Effects"] = "Effects";
1582
+ StyleCategory["List"] = "List";
1557
1583
  // Legacy — kept for backward compat; prefer Size
1558
1584
  StyleCategory["Dimensions"] = "Dimensions";
1559
1585
  })(StyleCategory || (StyleCategory = {}));
@@ -1952,6 +1978,32 @@ class EffectsGroupStyleConfig extends GroupStyleConfig {
1952
1978
  ]);
1953
1979
  }
1954
1980
  }
1981
+ class ListGroupStyleConfig extends GroupStyleConfig {
1982
+ constructor() {
1983
+ super(StyleCategory.List, [
1984
+ new TraitConfig('listStyleType', 'Marker Style', TraitInputType.Select, [
1985
+ { label: 'None', value: 'none' },
1986
+ { label: 'Disc', value: 'disc' },
1987
+ { label: 'Circle', value: 'circle' },
1988
+ { label: 'Square', value: 'square' },
1989
+ { label: 'Decimal', value: 'decimal' },
1990
+ { label: 'Lower Alpha', value: 'lower-alpha' },
1991
+ { label: 'Upper Alpha', value: 'upper-alpha' },
1992
+ { label: 'Lower Roman', value: 'lower-roman' },
1993
+ { label: 'Upper Roman', value: 'upper-roman' },
1994
+ ], 'disc'),
1995
+ new TraitConfig('listStylePosition', 'Marker Position', TraitInputType.SelectButton, [
1996
+ { value: 'outside', label: 'Outside' },
1997
+ { value: 'inside', label: 'Inside' },
1998
+ ], 'outside'),
1999
+ new TraitConfig('columnCount', 'Columns', TraitInputType.Scrub, { min: 1, max: 6, step: 1, units: [''] }, '1'),
2000
+ new TraitConfig('columnGap', 'Column Gap', TraitInputType.Scrub, { min: 0, max: 200, step: 1, units: UNITS_FIXED }, '0px'),
2001
+ new TraitConfig('_sep_marker', 'Marker', TraitInputType.SectionLabel),
2002
+ new TraitConfig('markerColor', 'Color', TraitInputType.Color, { allowGradient: false, allowTransparent: true, formats: ['hex', 'rgb', 'hsl', 'transparent'] }, ''),
2003
+ new TraitConfig('markerFontSize', 'Size', TraitInputType.Scrub, { min: 4, max: 100, step: 1, units: UNITS_FIXED }, ''),
2004
+ ]);
2005
+ }
2006
+ }
1955
2007
  /**
1956
2008
  * Returns a fresh set of all 8 style-group configs in canonical display order.
1957
2009
  * Every call produces new TraitConfig instances so different component nodes
@@ -2063,11 +2115,25 @@ class StyleRegistryService {
2063
2115
  this.flush();
2064
2116
  return;
2065
2117
  }
2118
+ // ::marker pseudo-element — emitted as a separate rule, not part of inner/outer split.
2119
+ const markerStyles = styles['__markerStyles'];
2120
+ if (markerStyles && Object.keys(markerStyles).length) {
2121
+ const markerCss = this.compile(`iox-node-${nodeId}::marker`, markerStyles);
2122
+ if (markerCss)
2123
+ this.rules.set(`${nodeId}::marker`, markerCss);
2124
+ else
2125
+ this.rules.delete(`${nodeId}::marker`);
2126
+ }
2127
+ else {
2128
+ this.rules.delete(`${nodeId}::marker`);
2129
+ }
2066
2130
  const pos = String(styles['position'] ?? '');
2067
2131
  const isOutOfFlow = pos === 'fixed' || pos === 'absolute';
2068
2132
  const inner = {};
2069
2133
  const outer = {};
2070
2134
  for (const [k, v] of Object.entries(styles)) {
2135
+ if (k === '__markerStyles')
2136
+ continue;
2071
2137
  const wantsOuter = StyleRegistryService.OUTER_PROPS.has(k);
2072
2138
  // width goes to inner for fixed/absolute (the positioned element owns its own width)
2073
2139
  if (wantsOuter && !(isOutOfFlow && k === 'width')) {
@@ -3228,11 +3294,14 @@ class BuilderComponent {
3228
3294
  this.dsRegistry.setDataSources(this.dataSources);
3229
3295
  this.dragEngine.setScale(this.viewportService.getScale());
3230
3296
  this.sub = this.panelEventService.subscribe((panelEvent) => this.handlePanelEvents(panelEvent));
3231
- this.panelEventService.emit(PanelEventTypes.PANEL_OPEN, PanelTypes.STYLES);
3232
- this.dragEngine.isDragging$.subscribe((v) => {
3297
+ this.sub.add(this.dragEngine.isDragging$.subscribe((v) => {
3233
3298
  this.isDragging = v;
3234
3299
  this.cdr.markForCheck();
3235
- });
3300
+ }));
3301
+ this.sub.add(this.dragEngine.dropComplete$.subscribe((node) => {
3302
+ this._selectAfterDrop(node);
3303
+ }));
3304
+ this.panelEventService.emit(PanelEventTypes.PANEL_OPEN, PanelTypes.STYLES);
3236
3305
  this.viewportSub = this.viewportService.state$.subscribe(state => {
3237
3306
  this.activeDevice = state.device;
3238
3307
  this.activeZoom = Math.round(state.scale * 100);
@@ -3382,12 +3451,15 @@ class BuilderComponent {
3382
3451
  if (!config)
3383
3452
  return;
3384
3453
  this.layout.splice(insertIndex, 0, config);
3454
+ this.cdr.markForCheck();
3455
+ this._selectAfterDrop(config);
3385
3456
  }
3386
3457
  else {
3387
3458
  const clone = this.deepCloneWithNewIds(payload.data);
3388
3459
  this.layout.splice(insertIndex, 0, clone);
3460
+ this.cdr.markForCheck();
3461
+ this._selectAfterDrop(clone);
3389
3462
  }
3390
- this.cdr.markForCheck();
3391
3463
  return;
3392
3464
  }
3393
3465
  const item = payload.data;
@@ -3396,6 +3468,7 @@ class BuilderComponent {
3396
3468
  const clone = this.deepCloneWithNewIds(item);
3397
3469
  this.layout.splice(insertIndex, 0, clone);
3398
3470
  this.cdr.markForCheck();
3471
+ this._selectAfterDrop(clone);
3399
3472
  return;
3400
3473
  }
3401
3474
  if (payload.sourceId && payload.sourceId !== 'canvas-preview') {
@@ -3410,6 +3483,7 @@ class BuilderComponent {
3410
3483
  }
3411
3484
  this.layout.splice(insertIndex, 0, item);
3412
3485
  this.cdr.markForCheck();
3486
+ this._selectAfterDrop(item);
3413
3487
  return;
3414
3488
  }
3415
3489
  // Same-container reorder (canvas root).
@@ -3419,6 +3493,7 @@ class BuilderComponent {
3419
3493
  this.layout.splice(currentIdx, 1);
3420
3494
  this.layout.splice(adjustedIdx, 0, item);
3421
3495
  this.cdr.markForCheck();
3496
+ this._selectAfterDrop(item);
3422
3497
  }
3423
3498
  }
3424
3499
  onModeChange(mode) {
@@ -3491,6 +3566,19 @@ class BuilderComponent {
3491
3566
  this.selectPanel(PanelTypes.STYLES);
3492
3567
  this.panelEventService.emit(PanelEventTypes.ELEMENT_SELECT, { node: event.node, componentRef: event.componentRef });
3493
3568
  }
3569
+ _selectAfterDrop(node) {
3570
+ // Wait one tick for Angular to render the new component and register it
3571
+ // in the overlay before attempting to select it.
3572
+ setTimeout(() => {
3573
+ const ref = this.overlayService.getNodeRef(node);
3574
+ if (!ref)
3575
+ return;
3576
+ this.selectedItem = node;
3577
+ this.overlayService.setSelect(ref.element, node.type, this.activeMode, node, ref.componentRef);
3578
+ this.selectPanel(PanelTypes.STYLES);
3579
+ this.panelEventService.emit(PanelEventTypes.ELEMENT_SELECT, { node, componentRef: ref.componentRef });
3580
+ });
3581
+ }
3494
3582
  handleMouseEnter(event) {
3495
3583
  if (this.isDragging || this.activeMode === BuilderMode.Pan)
3496
3584
  return;
@@ -3859,7 +3947,7 @@ class SectionComponent {
3859
3947
  </ng-container>
3860
3948
  </div>
3861
3949
  </div>
3862
- `, isInline: true, styles: [".section-root{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}.section-placeholder i{font-size:22px}.section-child{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: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender"], 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"] }] }); }
3950
+ `, isInline: true, styles: [".section-root{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}.section-root:hover .section-placeholder,.section-root.iox-drag-over .section-placeholder{opacity:1}.section-placeholder i{font-size:22px}.section-child{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: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender"], 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"] }] }); }
3863
3951
  }
3864
3952
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SectionComponent, decorators: [{
3865
3953
  type: Component,
@@ -3889,7 +3977,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
3889
3977
  </ng-container>
3890
3978
  </div>
3891
3979
  </div>
3892
- `, standalone: false, styles: [".section-root{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}.section-placeholder i{font-size:22px}.section-child{min-width:0}\n"] }]
3980
+ `, standalone: false, styles: [".section-root{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}.section-root:hover .section-placeholder,.section-root.iox-drag-over .section-placeholder{opacity:1}.section-placeholder i{font-size:22px}.section-child{min-width:0}\n"] }]
3893
3981
  }], ctorParameters: () => [{ type: DragEngineService }, { type: i0.ChangeDetectorRef }], propDecorators: { children: [{
3894
3982
  type: Input
3895
3983
  }], style: [{
@@ -3915,6 +4003,8 @@ class BuilderContainerComponent {
3915
4003
  this.nodeId = '';
3916
4004
  this.dropListId = '';
3917
4005
  this.htmlTag = 'div';
4006
+ this.start = 1;
4007
+ this.reversed = false;
3918
4008
  this.childClick = new EventEmitter();
3919
4009
  this.childMouseEnter = new EventEmitter();
3920
4010
  this.childMouseLeave = new EventEmitter();
@@ -3934,7 +4024,7 @@ class BuilderContainerComponent {
3934
4024
  this.dragEngine.handleDrop(this.children, event, this.dropListId, this.cdr);
3935
4025
  }
3936
4026
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderContainerComponent, deps: [{ token: DragEngineService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
3937
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: BuilderContainerComponent, isStandalone: false, selector: "app-builder-container", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", htmlTag: "htmlTag" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
4027
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: BuilderContainerComponent, isStandalone: false, selector: "app-builder-container", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", htmlTag: "htmlTag", start: "start", reversed: "reversed" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
3938
4028
  <ng-template #dropContent>
3939
4029
  <div *ngIf="!children.length" class="container-placeholder">
3940
4030
  <i class="ph-thin ph-square"></i>
@@ -3962,11 +4052,11 @@ class BuilderContainerComponent {
3962
4052
  @case ('main') { <main class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></main> }
3963
4053
  @case ('nav') { <nav class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></nav> }
3964
4054
  @case ('ul') { <ul class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></ul> }
3965
- @case ('ol') { <ol class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></ol> }
4055
+ @case ('ol') { <ol class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" [attr.start]="start !== 1 ? start : null" [attr.reversed]="reversed ? '' : null" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></ol> }
3966
4056
  @case ('li') { <li class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></li> }
3967
4057
  @default { <div class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></div> }
3968
4058
  }
3969
- `, isInline: true, styles: [".container-root{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}.container-placeholder i{font-size:18px}.container-child{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"], 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"] }] }); }
4059
+ `, isInline: true, styles: [".container-root{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}.container-root:hover .container-placeholder,.container-root.iox-drag-over .container-placeholder{opacity:1}.container-placeholder i{font-size:18px}.container-child{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"], 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"] }] }); }
3970
4060
  }
3971
4061
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderContainerComponent, decorators: [{
3972
4062
  type: Component,
@@ -3998,11 +4088,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
3998
4088
  @case ('main') { <main class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></main> }
3999
4089
  @case ('nav') { <nav class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></nav> }
4000
4090
  @case ('ul') { <ul class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></ul> }
4001
- @case ('ol') { <ol class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></ol> }
4091
+ @case ('ol') { <ol class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" [attr.start]="start !== 1 ? start : null" [attr.reversed]="reversed ? '' : null" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></ol> }
4002
4092
  @case ('li') { <li class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></li> }
4003
4093
  @default { <div class="container-root" [ngClass]="['iox-node-' + nodeId, listOrientation === 'horizontal' ? 'is-horizontal' : '']" ioxDropzone [ioxDropzoneId]="dropListId" [ioxDropzoneData]="children" (ioxDrop)="onDrop($event)"><ng-container [ngTemplateOutlet]="dropContent"></ng-container></div> }
4004
4094
  }
4005
- `, standalone: false, styles: [".container-root{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}.container-placeholder i{font-size:18px}.container-child{min-width:0}\n"] }]
4095
+ `, standalone: false, styles: [".container-root{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}.container-root:hover .container-placeholder,.container-root.iox-drag-over .container-placeholder{opacity:1}.container-placeholder i{font-size:18px}.container-child{min-width:0}\n"] }]
4006
4096
  }], ctorParameters: () => [{ type: DragEngineService }, { type: i0.ChangeDetectorRef }], propDecorators: { children: [{
4007
4097
  type: Input
4008
4098
  }], style: [{
@@ -4013,6 +4103,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
4013
4103
  type: Input
4014
4104
  }], htmlTag: [{
4015
4105
  type: Input
4106
+ }], start: [{
4107
+ type: Input
4108
+ }], reversed: [{
4109
+ type: Input
4016
4110
  }], childClick: [{
4017
4111
  type: Output
4018
4112
  }], childMouseEnter: [{
@@ -4097,7 +4191,7 @@ class BuilderLinkedContainerComponent {
4097
4191
  </ng-container>
4098
4192
  </div>
4099
4193
  </a>
4100
- `, 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}.linked-container-placeholder i{font-size:18px}.linked-container-child{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"], 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"] }] }); }
4194
+ `, 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}.linked-container-child{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"], 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"] }] }); }
4101
4195
  }
4102
4196
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderLinkedContainerComponent, decorators: [{
4103
4197
  type: Component,
@@ -4130,7 +4224,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
4130
4224
  </ng-container>
4131
4225
  </div>
4132
4226
  </a>
4133
- `, standalone: false, 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}.linked-container-placeholder i{font-size:18px}.linked-container-child{min-width:0}\n"] }]
4227
+ `, standalone: false, 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}.linked-container-child{min-width:0}\n"] }]
4134
4228
  }], ctorParameters: () => [{ type: DragEngineService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: undefined, decorators: [{
4135
4229
  type: Optional
4136
4230
  }, {
@@ -5227,6 +5321,86 @@ class BuilderLinkedContainerConfig extends ComponentConfig {
5227
5321
  }
5228
5322
  }
5229
5323
 
5324
+ class BuilderListItemComponentConfig extends ComponentConfig {
5325
+ constructor() {
5326
+ super('ListItem', 'app-builder-container', 'ph-thin ph-list-dashes', 'Layout');
5327
+ this.traits = [
5328
+ new TraitConfig('htmlTag', 'Tag', TraitInputType.Select, ['li'], 'li'),
5329
+ ];
5330
+ this.styleTraits = buildFullStyleTraits();
5331
+ this.children = [];
5332
+ this.applyStyleDefaults({
5333
+ width: '100%',
5334
+ display: 'block',
5335
+ backgroundColor: 'transparent',
5336
+ });
5337
+ }
5338
+ }
5339
+
5340
+ class TextBlockComponentConfig extends ComponentConfig {
5341
+ constructor() {
5342
+ super('Text', 'app-text-block', 'ph-thin ph-text-aa', 'Basic');
5343
+ this.inputs = {
5344
+ content: 'text',
5345
+ tag: 'select',
5346
+ };
5347
+ this.traits = [
5348
+ new TraitConfig('content', 'Content', TraitInputType.Text, undefined, 'Enter text here'),
5349
+ new TraitConfig('tag', 'Tag', TraitInputType.Select, ['p', 'span'], 'p'),
5350
+ ];
5351
+ this.styleTraits = buildFullStyleTraits();
5352
+ this.applyStyleDefaults({
5353
+ display: 'block',
5354
+ width: '100%',
5355
+ height: 'auto',
5356
+ minHeight: '20px',
5357
+ padding: '10px',
5358
+ });
5359
+ }
5360
+ }
5361
+
5362
+ class BuilderListComponentConfig extends ComponentConfig {
5363
+ constructor() {
5364
+ super('List', 'app-builder-container', 'ph-thin ph-list', 'Layout');
5365
+ this.traits = [
5366
+ new TraitConfig('htmlTag', 'Tag', TraitInputType.Select, ['ul', 'ol'], 'ul'),
5367
+ new TraitConfig('start', 'Start At', TraitInputType.Number, undefined, 1, false, { trait: 'htmlTag', values: 'ol' }),
5368
+ new TraitConfig('reversed', 'Reversed', TraitInputType.Checkbox, undefined, false, false, { trait: 'htmlTag', values: 'ol' }),
5369
+ ];
5370
+ this.styleTraits = [
5371
+ new ListGroupStyleConfig(),
5372
+ new PositionGroupStyleConfig(),
5373
+ new LayoutGroupStyleConfig(),
5374
+ new SizeGroupStyleConfig(),
5375
+ new SpacingGroupStyleConfig(),
5376
+ new BorderGroupStyleConfig(),
5377
+ new BackgroundGroupStyleConfig(),
5378
+ new TypographyGroupStyleConfig(),
5379
+ new EffectsGroupStyleConfig(),
5380
+ ];
5381
+ this.children = [
5382
+ this.makeListItem(),
5383
+ this.makeListItem(),
5384
+ this.makeListItem(),
5385
+ ];
5386
+ this.applyStyleDefaults({
5387
+ width: '100%',
5388
+ display: 'block',
5389
+ backgroundColor: 'transparent',
5390
+ padding: '0px 0px 0px 24px',
5391
+ });
5392
+ }
5393
+ makeListItem() {
5394
+ const item = new BuilderListItemComponentConfig();
5395
+ const textCfg = new TextBlockComponentConfig();
5396
+ const contentTrait = textCfg.traits.find(t => t.name === 'content');
5397
+ if (contentTrait)
5398
+ contentTrait.default = 'List item';
5399
+ item.children = [textCfg];
5400
+ return item;
5401
+ }
5402
+ }
5403
+
5230
5404
  class RepeaterComponentConfig extends ComponentConfig {
5231
5405
  constructor() {
5232
5406
  super('Repeater', 'app-builder-repeater', 'ph-thin ph-repeat', 'Data');
@@ -5282,28 +5456,6 @@ class BuilderSpacerComponentConfig extends ComponentConfig {
5282
5456
  }
5283
5457
  }
5284
5458
 
5285
- class TextBlockComponentConfig extends ComponentConfig {
5286
- constructor() {
5287
- super('Text', 'app-text-block', 'ph-thin ph-text-aa', 'Basic');
5288
- this.inputs = {
5289
- content: 'text',
5290
- tag: 'select',
5291
- };
5292
- this.traits = [
5293
- new TraitConfig('content', 'Content', TraitInputType.Text, undefined, 'Enter text here'),
5294
- new TraitConfig('tag', 'Tag', TraitInputType.Select, ['p', 'span'], 'p'),
5295
- ];
5296
- this.styleTraits = buildFullStyleTraits();
5297
- this.applyStyleDefaults({
5298
- display: 'block',
5299
- width: '100%',
5300
- height: 'auto',
5301
- minHeight: '20px',
5302
- padding: '10px',
5303
- });
5304
- }
5305
- }
5306
-
5307
5459
  /*
5308
5460
  * Public API Surface of @vectoriox/iox-builder
5309
5461
  */
@@ -5312,5 +5464,5 @@ class TextBlockComponentConfig extends ComponentConfig {
5312
5464
  * Generated bundle index. Do not edit.
5313
5465
  */
5314
5466
 
5315
- 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, INVERSE_ACTION, 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, VIRTUAL_TRAIT_KEYS, ViewportService, ZOOM_OPTIONS, buildFullStyleTraits, buildPresetStyleTraits, composeVirtualTraits, defaultPageSettings, generateNodeId, resolveTraitControllerType, resolveTraitOptions };
5467
+ export { ACTION_TYPE_OPTIONS, BuilderButtonBlockComponent, BuilderButtonComponentConfig, BuilderComponent, BuilderContainerComponent, BuilderContainerComponentConfig, BuilderDividerComponentConfig, BuilderHeadingComponentConfig, BuilderIconComponentConfig, BuilderImageComponentConfig, BuilderLinkComponentConfig, BuilderLinkedContainerComponent, BuilderLinkedContainerConfig, BuilderListComponentConfig, BuilderListItemComponentConfig, BuilderMode, BuilderRepeaterComponent, BuilderSpacerComponentConfig, ButtonBlockComponentConfig, CardComponentConfig, ComponentConfig, ComponentRegistryService, DEVICE_OPTIONS, DataSourceRegistryService, DeviceMode, DragEngineService, EASING_OPTIONS$1 as EASING_OPTIONS, GroupStyleConfig, INTERACTION_STATES, INVERSE_ACTION, IOX_CONTENT_SERVICE, IOX_FONT_MANAGER, InteractionEngineService, InteractionsPanelComponent, IoxBuilderModule, IoxDraggableDirective, IoxDropzoneDirective, LayerTreeComponent, ListGroupStyleConfig, 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, VIRTUAL_TRAIT_KEYS, ViewportService, ZOOM_OPTIONS, buildFullStyleTraits, buildPresetStyleTraits, composeVirtualTraits, defaultPageSettings, generateNodeId, resolveTraitControllerType, resolveTraitOptions };
5316
5468
  //# sourceMappingURL=vectoriox-iox-builder.mjs.map