ngx-form-designer 0.0.26 → 0.0.27

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.
@@ -11,6 +11,8 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
11
11
  import * as i3$1 from 'lucide-angular';
12
12
  import { LucideAngularModule } from 'lucide-angular';
13
13
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
14
+ import * as i5 from 'angular-resizable-element';
15
+ import { ResizableModule } from 'angular-resizable-element';
14
16
  import { Router, NavigationEnd } from '@angular/router';
15
17
  import loader from '@monaco-editor/loader';
16
18
  import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
@@ -622,6 +624,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
622
624
  }]
623
625
  }] });
624
626
 
627
+ const WRAPPER_SURFACE_STYLE_KEYS = new Set([
628
+ 'backgroundColor',
629
+ 'borderColor',
630
+ 'borderStyle',
631
+ 'borderWidth',
632
+ 'borderRadius',
633
+ 'borderTopColor',
634
+ 'borderRightColor',
635
+ 'borderBottomColor',
636
+ 'borderLeftColor',
637
+ 'borderTopStyle',
638
+ 'borderRightStyle',
639
+ 'borderBottomStyle',
640
+ 'borderLeftStyle',
641
+ 'borderTopWidth',
642
+ 'borderRightWidth',
643
+ 'borderBottomWidth',
644
+ 'borderLeftWidth',
645
+ 'borderTopLeftRadius',
646
+ 'borderTopRightRadius',
647
+ 'borderBottomRightRadius',
648
+ 'borderBottomLeftRadius'
649
+ ]);
650
+ const CONTROL_SURFACE_STYLE_KEYS = new Set([
651
+ 'color',
652
+ 'fontFamily',
653
+ 'fontSize',
654
+ 'fontStyle',
655
+ 'fontWeight',
656
+ 'lineHeight',
657
+ 'textAlign',
658
+ 'textDecoration'
659
+ ]);
625
660
  function normalizeStyle(style) {
626
661
  if (!style)
627
662
  return {};
@@ -663,6 +698,34 @@ function normalizeStyle(style) {
663
698
  function mergeAndNormalize(base, override) {
664
699
  return normalizeStyle({ ...(base || {}), ...(override || {}) });
665
700
  }
701
+ function splitControlSurfaceStyles(style) {
702
+ if (!style) {
703
+ return { wrapperStyles: {}, controlStyles: {} };
704
+ }
705
+ const wrapperStyles = {};
706
+ const controlStyles = {};
707
+ Object.entries(style).forEach(([key, value]) => {
708
+ if (WRAPPER_SURFACE_STYLE_KEYS.has(key)) {
709
+ wrapperStyles[key] = value;
710
+ return;
711
+ }
712
+ if (CONTROL_SURFACE_STYLE_KEYS.has(key)) {
713
+ controlStyles[key] = value;
714
+ return;
715
+ }
716
+ wrapperStyles[key] = value;
717
+ });
718
+ return {
719
+ wrapperStyles: normalizeStyle(wrapperStyles),
720
+ controlStyles: normalizeStyle(controlStyles)
721
+ };
722
+ }
723
+ function hasWrapperSurfaceStyles(style) {
724
+ if (!style) {
725
+ return false;
726
+ }
727
+ return Object.keys(style).some(key => WRAPPER_SURFACE_STYLE_KEYS.has(key));
728
+ }
666
729
 
667
730
  const WIDGET_EDITOR_CONTEXT = new InjectionToken('WIDGET_EDITOR_CONTEXT');
668
731
 
@@ -2226,9 +2289,15 @@ class LayoutNodeComponent {
2226
2289
  renderEngineProxy;
2227
2290
  renderEngineSource;
2228
2291
  renderEngineMode = 'live';
2229
- resizeStartX = 0;
2230
- resizeStartSpan = 0;
2231
2292
  destroyRef = inject(DestroyRef);
2293
+ bottomResizeEdges = { bottom: true };
2294
+ rightResizeEdges = { right: true };
2295
+ activeResizeNodeId = null;
2296
+ resizeStartSpan = 0;
2297
+ resizeStartWidth = 0;
2298
+ static MIN_RESIZABLE_HEIGHT = 20;
2299
+ static MIN_COLUMN_SPAN = 1;
2300
+ static MAX_COLUMN_SPAN = 12;
2232
2301
  constructor(_widgetDefs, designerState, cdr, el) {
2233
2302
  this._widgetDefs = _widgetDefs;
2234
2303
  this.designerState = designerState;
@@ -2240,6 +2309,9 @@ class LayoutNodeComponent {
2240
2309
  get isSelected() {
2241
2310
  return this.designerState.isNodeSelected(this.getScopedNodeId(this.node.id));
2242
2311
  }
2312
+ get isResizing() {
2313
+ return this.activeResizeNodeId === this.node.id;
2314
+ }
2243
2315
  isNodeSelected(nodeId) {
2244
2316
  return this.designerState.isNodeSelected(this.getScopedNodeId(nodeId));
2245
2317
  }
@@ -2343,16 +2415,6 @@ class LayoutNodeComponent {
2343
2415
  }
2344
2416
  return this.node.type === 'row' ? 'Row' : 'Column';
2345
2417
  }
2346
- // Resize Logic
2347
- resizeStartY = 0;
2348
- resizeStartHeight = 0;
2349
- resizingNode = null;
2350
- resizingCol = null; // New for Col Resize
2351
- resizeMoveListener;
2352
- resizeUpListener;
2353
- get isResizing() {
2354
- return this.resizingNode === this.node;
2355
- }
2356
2418
  ngOnInit() {
2357
2419
  this.updateWidgetDefinitions();
2358
2420
  if (this.node.type === 'widget') {
@@ -2367,89 +2429,48 @@ class LayoutNodeComponent {
2367
2429
  this.cdr.markForCheck();
2368
2430
  });
2369
2431
  }
2370
- // Global listeners (bind once)
2371
- this.resizeMoveListener = this.onResizeMove.bind(this);
2372
- this.resizeUpListener = this.onResizeEnd.bind(this);
2373
2432
  }
2374
2433
  ngOnDestroy() {
2375
- // Cleanup global listeners if any are active (safety)
2376
- document.removeEventListener('mousemove', this.resizeMoveListener);
2377
- document.removeEventListener('mouseup', this.resizeUpListener);
2378
2434
  this.widgetComponentRef?.destroy();
2379
2435
  this.widgetComponentRef = undefined;
2380
2436
  }
2381
- // Height Resize
2382
- onResizeStart(e, node) {
2437
+ onHeightResizeStart(node) {
2383
2438
  if (!this.designMode)
2384
2439
  return;
2385
- e.preventDefault();
2386
- e.stopPropagation();
2387
- this.resizingNode = node;
2388
- this.resizeStartY = e.clientY;
2389
- const currentHeight = parseInt(node.style?.minHeight || '0', 10);
2390
- this.resizeStartHeight = isNaN(currentHeight) ? 50 : currentHeight;
2391
- document.addEventListener('mousemove', this.resizeMoveListener);
2392
- document.addEventListener('mouseup', this.resizeUpListener);
2440
+ this.activeResizeNodeId = node.id;
2393
2441
  this.designerState.selectNode(this.getScopedNodeId(node.id));
2394
2442
  }
2395
- // Column Width Resize
2396
- onColResizeStart(e, node) {
2443
+ onHeightResize(node, event) {
2444
+ if (!this.designMode)
2445
+ return;
2446
+ this.applyVerticalResize(node, event);
2447
+ }
2448
+ onHeightResizeEnd(node, event) {
2449
+ if (!this.designMode)
2450
+ return;
2451
+ this.applyVerticalResize(node, event);
2452
+ this.activeResizeNodeId = null;
2453
+ }
2454
+ onColumnResizeStart(node) {
2397
2455
  if (!this.designMode || node.type !== 'col')
2398
2456
  return;
2399
- e.preventDefault();
2400
- e.stopPropagation();
2401
- this.resizingCol = node;
2402
- this.resizeStartX = e.clientX;
2403
- // Get current span
2404
- // We assume xs for now or active device logic could be added
2405
- // Use effective span for current breakpoint for consistency
2406
- const activeSpan = this.getEffectiveSpan(this.resizingCol.responsive || { xs: 12 });
2407
- this.resizeStartSpan = activeSpan;
2408
- document.addEventListener('mousemove', this.resizeMoveListener);
2409
- document.addEventListener('mouseup', this.resizeUpListener);
2457
+ this.activeResizeNodeId = node.id;
2458
+ this.resizeStartSpan = this.getEffectiveSpan(node.responsive || { xs: LayoutNodeComponent.MAX_COLUMN_SPAN });
2459
+ this.resizeStartWidth = this.getCurrentNodeWidth();
2410
2460
  this.designerState.selectNode(this.getScopedNodeId(node.id));
2411
2461
  }
2412
- onResizeMove(e) {
2413
- // Handle Height Resize
2414
- if (this.resizingNode) {
2415
- const delta = e.clientY - this.resizeStartY;
2416
- const newHeight = Math.max(50, this.resizeStartHeight + delta);
2417
- if (!this.resizingNode.style)
2418
- this.resizingNode.style = {};
2419
- this.resizingNode.style.minHeight = `${newHeight}px`;
2420
- this.cdr.detectChanges();
2421
- return;
2422
- }
2423
- // Handle Column Resize
2424
- if (this.resizingCol) {
2425
- const deltaX = e.clientX - this.resizeStartX;
2426
- // Calculate grid jump
2427
- const currentPixelWidth = this.el.nativeElement.firstElementChild?.getBoundingClientRect().width || 100; // The switch div
2428
- const oneSpanInHighlight = currentPixelWidth / this.resizeStartSpan; // pixels per 1/12
2429
- // Prevent division by zero and weird states
2430
- if (oneSpanInHighlight <= 0)
2431
- return;
2432
- const spanDelta = Math.round(deltaX / oneSpanInHighlight);
2433
- let newSpan = this.resizeStartSpan + spanDelta;
2434
- // Clamp 1-12
2435
- newSpan = Math.max(1, Math.min(12, newSpan));
2436
- if (!this.resizingCol.responsive) {
2437
- this.resizingCol.responsive = { xs: 12 };
2438
- }
2439
- // Update result for CURRENT breakpoint
2440
- // If current breakpoint is not explicitly in responsive object, we should initialize it?
2441
- // Or updating 'xs' as fallback?
2442
- // Strategy: Update the specific breakpoint Key we are viewing.
2443
- const bp = this.breakpoint;
2444
- this.resizingCol.responsive[bp] = newSpan;
2445
- this.cdr.detectChanges();
2446
- }
2447
- }
2448
- onResizeEnd() {
2449
- this.resizingNode = null;
2450
- this.resizingCol = null;
2451
- document.removeEventListener('mousemove', this.resizeMoveListener);
2452
- document.removeEventListener('mouseup', this.resizeUpListener);
2462
+ onColumnResize(node, event) {
2463
+ if (!this.designMode || node.type !== 'col')
2464
+ return;
2465
+ this.applyColumnResize(node, event);
2466
+ }
2467
+ onColumnResizeEnd(node, event) {
2468
+ if (!this.designMode || node.type !== 'col')
2469
+ return;
2470
+ this.applyColumnResize(node, event);
2471
+ this.activeResizeNodeId = null;
2472
+ this.resizeStartSpan = 0;
2473
+ this.resizeStartWidth = 0;
2453
2474
  }
2454
2475
  onNodeDrop(event) {
2455
2476
  this.nodeDrop.emit(event);
@@ -2545,6 +2566,7 @@ class LayoutNodeComponent {
2545
2566
  }
2546
2567
  if (!this.widgetComponentRef)
2547
2568
  return;
2569
+ this.applyWidgetHostLayout();
2548
2570
  this.widgetComponentRef.setInput('config', config);
2549
2571
  this.widgetComponentRef.setInput('engine', this.getEngineForRender());
2550
2572
  if (config.type === 'repeatable-group') {
@@ -2556,6 +2578,15 @@ class LayoutNodeComponent {
2556
2578
  }
2557
2579
  this.widgetComponentRef.changeDetectorRef.markForCheck();
2558
2580
  }
2581
+ applyWidgetHostLayout() {
2582
+ const hostElement = this.widgetComponentRef?.location.nativeElement;
2583
+ if (!hostElement)
2584
+ return;
2585
+ hostElement.style.display = 'block';
2586
+ hostElement.style.width = '100%';
2587
+ hostElement.style.height = '100%';
2588
+ hostElement.style.minHeight = '0';
2589
+ }
2559
2590
  updateWidgetDefinitions() {
2560
2591
  const flavor = this.engine?.getSchema()?.flavor ?? this.designerState.activeFlavor();
2561
2592
  this.widgetDefs = this.allWidgetDefs.filter(def => !def.flavor || def.flavor === flavor);
@@ -2619,6 +2650,36 @@ class LayoutNodeComponent {
2619
2650
  }
2620
2651
  asRow(node) { return node; }
2621
2652
  asCol(node) { return node; }
2653
+ applyVerticalResize(node, event) {
2654
+ const nextHeight = this.getResizeHeight(event);
2655
+ if (!nextHeight)
2656
+ return;
2657
+ const clampedHeight = Math.max(LayoutNodeComponent.MIN_RESIZABLE_HEIGHT, nextHeight);
2658
+ if (!node.style)
2659
+ node.style = {};
2660
+ node.style.height = `${clampedHeight}px`;
2661
+ delete node.style.minHeight;
2662
+ this.cdr.detectChanges();
2663
+ }
2664
+ applyColumnResize(node, event) {
2665
+ const nextWidth = event.rectangle.width;
2666
+ if (!nextWidth || nextWidth <= 0)
2667
+ return;
2668
+ const startSpan = this.resizeStartSpan || this.getEffectiveSpan(node.responsive || { xs: LayoutNodeComponent.MAX_COLUMN_SPAN });
2669
+ const startWidth = this.resizeStartWidth || this.getCurrentNodeWidth();
2670
+ if (!startWidth || startWidth <= 0 || startSpan <= 0)
2671
+ return;
2672
+ const oneSpanWidth = startWidth / startSpan;
2673
+ if (oneSpanWidth <= 0)
2674
+ return;
2675
+ const spanDelta = Math.round((nextWidth - startWidth) / oneSpanWidth);
2676
+ const nextSpan = Math.max(LayoutNodeComponent.MIN_COLUMN_SPAN, Math.min(LayoutNodeComponent.MAX_COLUMN_SPAN, startSpan + spanDelta));
2677
+ if (!node.responsive) {
2678
+ node.responsive = { xs: LayoutNodeComponent.MAX_COLUMN_SPAN };
2679
+ }
2680
+ node.responsive[this.breakpoint] = nextSpan;
2681
+ this.cdr.detectChanges();
2682
+ }
2622
2683
  getColClasses(node) {
2623
2684
  if (node.type !== 'col')
2624
2685
  return '';
@@ -2672,6 +2733,20 @@ class LayoutNodeComponent {
2672
2733
  };
2673
2734
  return map[span] || 'w-full';
2674
2735
  }
2736
+ getResizeHeight(event) {
2737
+ if (event.rectangle.height !== undefined) {
2738
+ return Math.round(event.rectangle.height);
2739
+ }
2740
+ const { top, bottom } = event.rectangle;
2741
+ if (top === undefined || bottom === undefined) {
2742
+ return undefined;
2743
+ }
2744
+ return Math.round(bottom - top);
2745
+ }
2746
+ getCurrentNodeWidth() {
2747
+ const hostElement = this.el.nativeElement.firstElementChild;
2748
+ return hostElement?.getBoundingClientRect().width ?? 0;
2749
+ }
2675
2750
  getStyle(node) {
2676
2751
  if (!('style' in node) || !node.style)
2677
2752
  return {};
@@ -2769,6 +2844,10 @@ class LayoutNodeComponent {
2769
2844
  <div *ngIf="isNodeVisible(node)"
2770
2845
  class="flex flex-wrap transition-all relative group"
2771
2846
  [style]="getStyle(node)"
2847
+ mwlResizable
2848
+ (resizeStart)="onHeightResizeStart(node)"
2849
+ (resizing)="onHeightResize(node, $event)"
2850
+ (resizeEnd)="onHeightResizeEnd(node, $event)"
2772
2851
  (click)="onRowClick($event)"
2773
2852
  (contextmenu)="onRowContextMenu($event)"
2774
2853
  [class.outline-dashed]="designMode"
@@ -2820,7 +2899,9 @@ class LayoutNodeComponent {
2820
2899
  </app-layout-node>
2821
2900
  <div *ngIf="designMode && isSelected"
2822
2901
  class="absolute bottom-0 left-0 right-0 h-3 cursor-row-resize bg-transparent hover:bg-blue-400/20 transition-colors z-50 group-hover:bg-blue-100/30"
2823
- (mousedown)="onResizeStart($event, node)"
2902
+ mwlResizeHandle
2903
+ [resizeEdges]="bottomResizeEdges"
2904
+ (mousedown)="$event.stopPropagation()"
2824
2905
  (click)="$event.stopPropagation()">
2825
2906
  </div>
2826
2907
  </div>
@@ -2832,6 +2913,10 @@ class LayoutNodeComponent {
2832
2913
  [class]="getColContainerClasses(node)"
2833
2914
  [class.bg-blue-50]="isResizing"
2834
2915
  [style]="getStyle(node)"
2916
+ mwlResizable
2917
+ (resizeStart)="onColumnResizeStart(node)"
2918
+ (resizing)="onColumnResize(node, $event)"
2919
+ (resizeEnd)="onColumnResizeEnd(node, $event)"
2835
2920
  (click)="onColumnClick($event)"
2836
2921
  (contextmenu)="onColumnContextMenu($event)"
2837
2922
  cdkDropList
@@ -2914,7 +2999,9 @@ class LayoutNodeComponent {
2914
2999
  <!-- Width Resize (Right) - Only if not last column in row -->
2915
3000
  <div *ngIf="designMode && isSelected"
2916
3001
  class="absolute top-0 bottom-2 right-0 w-3 cursor-col-resize bg-transparent hover:bg-blue-400/20 transition-colors z-50 group-hover:bg-blue-100/30"
2917
- (mousedown)="onColResizeStart($event, node)"
3002
+ mwlResizeHandle
3003
+ [resizeEdges]="rightResizeEdges"
3004
+ (mousedown)="$event.stopPropagation()"
2918
3005
  (click)="$event.stopPropagation()">
2919
3006
  </div>
2920
3007
  </div>
@@ -2925,6 +3012,10 @@ class LayoutNodeComponent {
2925
3012
  <div *ngIf="isNodeVisible(node)"
2926
3013
  class="relative group w-full"
2927
3014
  [style]="getStyle(node)"
3015
+ mwlResizable
3016
+ (resizeStart)="onHeightResizeStart(node)"
3017
+ (resizing)="onHeightResize(node, $event)"
3018
+ (resizeEnd)="onHeightResizeEnd(node, $event)"
2928
3019
  (click)="onWidgetClick($event)"
2929
3020
  (contextmenu)="onWidgetContextMenu($event)"
2930
3021
  [class.ring-2]="designMode && isSelected"
@@ -2975,21 +3066,23 @@ class LayoutNodeComponent {
2975
3066
  <div *ngIf="designMode && !isSelected && !hasActiveNestedSelection()" class="absolute inset-0 cursor-pointer z-10 hover:bg-blue-500/5" (click)="onWidgetClick($event)"></div>
2976
3067
  <div *ngIf="designMode && isSelected"
2977
3068
  class="absolute bottom-0 left-0 right-0 h-3 cursor-row-resize bg-transparent hover:bg-blue-400/20 transition-colors z-50 group-hover:bg-blue-100/30"
2978
- (mousedown)="onResizeStart($event, node)"
3069
+ mwlResizeHandle
3070
+ [resizeEdges]="bottomResizeEdges"
3071
+ (mousedown)="$event.stopPropagation()"
2979
3072
  (click)="$event.stopPropagation()">
2980
3073
  </div>
2981
3074
  </div>
2982
3075
  </ng-container>
2983
3076
 
2984
3077
  </ng-container>
2985
- `, isInline: true, dependencies: [{ kind: "component", type: LayoutNodeComponent, selector: "app-layout-node", inputs: ["node", "engine", "fields", "designMode", "readOnlyMode", "scopePath", "device", "breakpoint", "connectedDropLists"], outputs: ["nodeDrop", "nodeSelect"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i3.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i3.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: i3.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3078
+ `, isInline: true, dependencies: [{ kind: "component", type: LayoutNodeComponent, selector: "app-layout-node", inputs: ["node", "engine", "fields", "designMode", "readOnlyMode", "scopePath", "device", "breakpoint", "connectedDropLists"], outputs: ["nodeDrop", "nodeSelect"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i3.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i3.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: i3.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "ngmodule", type: ResizableModule }, { kind: "directive", type: i5.ResizableDirective, selector: "[mwlResizable]", inputs: ["validateResize", "enableGhostResize", "resizeSnapGrid", "resizeCursors", "ghostElementPositioning", "allowNegativeResizes", "mouseMoveThrottleMS"], outputs: ["resizeStart", "resizing", "resizeEnd"], exportAs: ["mwlResizable"] }, { kind: "directive", type: i5.ResizeHandleDirective, selector: "[mwlResizeHandle]", inputs: ["resizeEdges", "resizableContainer"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2986
3079
  }
2987
3080
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: LayoutNodeComponent, decorators: [{
2988
3081
  type: Component,
2989
3082
  args: [{
2990
3083
  selector: 'app-layout-node',
2991
3084
  standalone: true,
2992
- imports: [CommonModule, DragDropModule, UiIconModule],
3085
+ imports: [CommonModule, DragDropModule, UiIconModule, ResizableModule],
2993
3086
  changeDetection: ChangeDetectionStrategy.OnPush,
2994
3087
  template: `
2995
3088
  <ng-container [ngSwitch]="node.type">
@@ -2999,6 +3092,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
2999
3092
  <div *ngIf="isNodeVisible(node)"
3000
3093
  class="flex flex-wrap transition-all relative group"
3001
3094
  [style]="getStyle(node)"
3095
+ mwlResizable
3096
+ (resizeStart)="onHeightResizeStart(node)"
3097
+ (resizing)="onHeightResize(node, $event)"
3098
+ (resizeEnd)="onHeightResizeEnd(node, $event)"
3002
3099
  (click)="onRowClick($event)"
3003
3100
  (contextmenu)="onRowContextMenu($event)"
3004
3101
  [class.outline-dashed]="designMode"
@@ -3050,7 +3147,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
3050
3147
  </app-layout-node>
3051
3148
  <div *ngIf="designMode && isSelected"
3052
3149
  class="absolute bottom-0 left-0 right-0 h-3 cursor-row-resize bg-transparent hover:bg-blue-400/20 transition-colors z-50 group-hover:bg-blue-100/30"
3053
- (mousedown)="onResizeStart($event, node)"
3150
+ mwlResizeHandle
3151
+ [resizeEdges]="bottomResizeEdges"
3152
+ (mousedown)="$event.stopPropagation()"
3054
3153
  (click)="$event.stopPropagation()">
3055
3154
  </div>
3056
3155
  </div>
@@ -3062,6 +3161,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
3062
3161
  [class]="getColContainerClasses(node)"
3063
3162
  [class.bg-blue-50]="isResizing"
3064
3163
  [style]="getStyle(node)"
3164
+ mwlResizable
3165
+ (resizeStart)="onColumnResizeStart(node)"
3166
+ (resizing)="onColumnResize(node, $event)"
3167
+ (resizeEnd)="onColumnResizeEnd(node, $event)"
3065
3168
  (click)="onColumnClick($event)"
3066
3169
  (contextmenu)="onColumnContextMenu($event)"
3067
3170
  cdkDropList
@@ -3144,7 +3247,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
3144
3247
  <!-- Width Resize (Right) - Only if not last column in row -->
3145
3248
  <div *ngIf="designMode && isSelected"
3146
3249
  class="absolute top-0 bottom-2 right-0 w-3 cursor-col-resize bg-transparent hover:bg-blue-400/20 transition-colors z-50 group-hover:bg-blue-100/30"
3147
- (mousedown)="onColResizeStart($event, node)"
3250
+ mwlResizeHandle
3251
+ [resizeEdges]="rightResizeEdges"
3252
+ (mousedown)="$event.stopPropagation()"
3148
3253
  (click)="$event.stopPropagation()">
3149
3254
  </div>
3150
3255
  </div>
@@ -3155,6 +3260,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
3155
3260
  <div *ngIf="isNodeVisible(node)"
3156
3261
  class="relative group w-full"
3157
3262
  [style]="getStyle(node)"
3263
+ mwlResizable
3264
+ (resizeStart)="onHeightResizeStart(node)"
3265
+ (resizing)="onHeightResize(node, $event)"
3266
+ (resizeEnd)="onHeightResizeEnd(node, $event)"
3158
3267
  (click)="onWidgetClick($event)"
3159
3268
  (contextmenu)="onWidgetContextMenu($event)"
3160
3269
  [class.ring-2]="designMode && isSelected"
@@ -3205,7 +3314,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
3205
3314
  <div *ngIf="designMode && !isSelected && !hasActiveNestedSelection()" class="absolute inset-0 cursor-pointer z-10 hover:bg-blue-500/5" (click)="onWidgetClick($event)"></div>
3206
3315
  <div *ngIf="designMode && isSelected"
3207
3316
  class="absolute bottom-0 left-0 right-0 h-3 cursor-row-resize bg-transparent hover:bg-blue-400/20 transition-colors z-50 group-hover:bg-blue-100/30"
3208
- (mousedown)="onResizeStart($event, node)"
3317
+ mwlResizeHandle
3318
+ [resizeEdges]="bottomResizeEdges"
3319
+ (mousedown)="$event.stopPropagation()"
3209
3320
  (click)="$event.stopPropagation()">
3210
3321
  </div>
3211
3322
  </div>
@@ -10648,26 +10759,65 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
10648
10759
  `, styles: [".inspector-select{height:2rem;padding-left:.5rem;padding-right:.5rem;font-size:.875rem;line-height:1.25rem;background-color:var(--color-input-dark);border:1px solid var(--color-border-dark);border-radius:var(--radius-md);color:var(--color-ink-700);appearance:none;cursor:pointer}.inspector-select:focus{outline:none;border-color:var(--color-primary-blue)}.inspector-input-with-unit{display:flex;align-items:center;background-color:var(--color-input-dark);border:1px solid var(--color-border-dark);border-radius:var(--radius-md);overflow:hidden}.inspector-number-input{height:2rem;padding-left:.5rem;padding-right:.5rem;background-color:transparent;border:none;font-size:.875rem;line-height:1.25rem;color:var(--color-ink-700)}.inspector-number-input:focus{outline:none}.inspector-unit{font-size:11px;color:var(--color-ink-400);padding-left:.25rem;padding-right:.25rem;background-color:var(--color-input-dark);height:2rem;display:flex;align-items:center;border-left:1px solid var(--color-border-dark)}\n"] }]
10649
10760
  }] });
10650
10761
 
10762
+ const BORDER_SIDE_KEYS = {
10763
+ top: {
10764
+ borderStyle: 'borderTopStyle',
10765
+ borderWidth: 'borderTopWidth',
10766
+ borderColor: 'borderTopColor'
10767
+ },
10768
+ right: {
10769
+ borderStyle: 'borderRightStyle',
10770
+ borderWidth: 'borderRightWidth',
10771
+ borderColor: 'borderRightColor'
10772
+ },
10773
+ bottom: {
10774
+ borderStyle: 'borderBottomStyle',
10775
+ borderWidth: 'borderBottomWidth',
10776
+ borderColor: 'borderBottomColor'
10777
+ },
10778
+ left: {
10779
+ borderStyle: 'borderLeftStyle',
10780
+ borderWidth: 'borderLeftWidth',
10781
+ borderColor: 'borderLeftColor'
10782
+ }
10783
+ };
10784
+ const RADIUS_CORNER_KEYS = {
10785
+ tl: 'borderTopLeftRadius',
10786
+ tr: 'borderTopRightRadius',
10787
+ br: 'borderBottomRightRadius',
10788
+ bl: 'borderBottomLeftRadius'
10789
+ };
10651
10790
  /**
10652
- * Light theme Borders section.
10791
+ * Borders inspector with side-aware editing.
10653
10792
  */
10654
10793
  class InspectorBordersSectionComponent {
10655
10794
  style = input({});
10656
10795
  styleChange = output();
10657
10796
  selectedCorner = signal('all');
10658
10797
  selectedSide = signal('all');
10798
+ selectedSideLabel = computed(() => {
10799
+ const option = this.borderSides.find(candidate => candidate.side === this.selectedSide());
10800
+ return option?.label.toLowerCase() ?? 'all';
10801
+ });
10659
10802
  radiusCorners = [
10660
- { corner: 'all', label: 'All Corners', icon: 'square' },
10661
- { corner: 'tl', label: 'Top Left', icon: 'corner-up-left' },
10662
- { corner: 'tr', label: 'Top Right', icon: 'corner-up-right' },
10663
- { corner: 'bl', label: 'Bottom Left', icon: 'corner-down-left' },
10664
- { corner: 'br', label: 'Bottom Right', icon: 'corner-down-right' }
10803
+ { corner: 'all', label: 'All' },
10804
+ { corner: 'tl', label: 'TL' },
10805
+ { corner: 'tr', label: 'TR' },
10806
+ { corner: 'bl', label: 'BL' },
10807
+ { corner: 'br', label: 'BR' }
10808
+ ];
10809
+ borderSides = [
10810
+ { side: 'all', label: 'All' },
10811
+ { side: 'top', label: 'Top' },
10812
+ { side: 'right', label: 'Right' },
10813
+ { side: 'bottom', label: 'Bottom' },
10814
+ { side: 'left', label: 'Left' }
10665
10815
  ];
10666
10816
  borderStyles = [
10667
- { value: 'none', icon: 'x' },
10668
- { value: 'solid', icon: 'minus' },
10669
- { value: 'dashed', icon: 'more-horizontal' },
10670
- { value: 'dotted', icon: 'grip-horizontal' }
10817
+ { value: 'none', label: 'None' },
10818
+ { value: 'solid', label: 'Solid' },
10819
+ { value: 'dashed', label: 'Dashed' },
10820
+ { value: 'dotted', label: 'Dotted' }
10671
10821
  ];
10672
10822
  selectCorner(corner) {
10673
10823
  this.selectedCorner.set(corner);
@@ -10675,315 +10825,352 @@ class InspectorBordersSectionComponent {
10675
10825
  selectSide(side) {
10676
10826
  this.selectedSide.set(side);
10677
10827
  }
10828
+ getSelectorClass(isActive) {
10829
+ return isActive
10830
+ ? 'h-8 rounded-md border border-gray-400 bg-gray-200 px-3 text-[12px] font-medium text-gray-800'
10831
+ : 'h-8 rounded-md border border-border-dark bg-input-dark px-3 text-[12px] text-gray-600 hover:border-gray-400 hover:text-gray-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-blue';
10832
+ }
10833
+ getSegmentClass(isActive) {
10834
+ return isActive
10835
+ ? 'rounded-sm bg-gray-200 px-2 py-1.5 text-[12px] font-medium text-gray-800'
10836
+ : 'rounded-sm px-2 py-1.5 text-[12px] text-gray-600 hover:bg-gray-100';
10837
+ }
10678
10838
  getRadiusValue() {
10679
10839
  const corner = this.selectedCorner();
10680
- if (corner === 'all')
10681
- return String(this.style()['borderRadius'] || '0');
10682
- const map = {
10683
- tl: 'borderTopLeftRadius',
10684
- tr: 'borderTopRightRadius',
10685
- br: 'borderBottomRightRadius',
10686
- bl: 'borderBottomLeftRadius'
10687
- };
10688
- return String(this.style()[map[corner]] || '0');
10840
+ if (corner === 'all') {
10841
+ return String(this.style()['borderRadius'] ?? '0');
10842
+ }
10843
+ const cornerKey = RADIUS_CORNER_KEYS[corner];
10844
+ return String(this.style()[cornerKey] ?? this.style()['borderRadius'] ?? '0');
10689
10845
  }
10690
10846
  setRadiusValue(value) {
10847
+ const nextStyle = this.createStyleDraft();
10691
10848
  const corner = this.selectedCorner();
10692
10849
  if (corner === 'all') {
10693
- this.updateStyle('borderRadius', value);
10850
+ this.clearRadiusOverrides(nextStyle);
10851
+ this.assignStyleValue(nextStyle, 'borderRadius', value);
10694
10852
  }
10695
10853
  else {
10696
- const map = {
10697
- tl: 'borderTopLeftRadius',
10698
- tr: 'borderTopRightRadius',
10699
- br: 'borderBottomRightRadius',
10700
- bl: 'borderBottomLeftRadius'
10701
- };
10702
- this.updateStyle(map[corner], value);
10854
+ this.assignStyleValue(nextStyle, RADIUS_CORNER_KEYS[corner], value);
10855
+ }
10856
+ this.emitStyle(nextStyle);
10857
+ }
10858
+ getBorderValue(property) {
10859
+ const side = this.selectedSide();
10860
+ if (side === 'all') {
10861
+ return String(this.style()[property] ?? this.getDefaultBorderValue(property));
10862
+ }
10863
+ const sideKey = BORDER_SIDE_KEYS[side][property];
10864
+ return String(this.style()[sideKey] ?? this.style()[property] ?? this.getDefaultBorderValue(property));
10865
+ }
10866
+ getColorInputValue() {
10867
+ const value = String(this.getBorderValue('borderColor') || '').trim().toLowerCase();
10868
+ if (/^#[0-9a-f]{6}$/i.test(value)) {
10869
+ return value;
10703
10870
  }
10871
+ if (/^#[0-9a-f]{3}$/i.test(value)) {
10872
+ const [, r, g, b] = value;
10873
+ return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();
10874
+ }
10875
+ if (value === 'white') {
10876
+ return '#ffffff';
10877
+ }
10878
+ return '#000000';
10704
10879
  }
10705
10880
  parseValue(val) {
10706
10881
  if (val === undefined || val === null)
10707
10882
  return 0;
10708
10883
  const num = parseFloat(String(val));
10709
- return isNaN(num) ? 0 : num;
10710
- }
10711
- getColorName(color) {
10712
- if (!color)
10713
- return 'black';
10714
- if (color === '#000000' || color === 'black')
10715
- return 'black';
10716
- if (color === '#ffffff' || color === 'white')
10717
- return 'white';
10718
- return color;
10884
+ return Number.isNaN(num) ? 0 : num;
10719
10885
  }
10720
10886
  updateStyle(key, value) {
10721
- this.styleChange.emit({ ...this.style(), [key]: value });
10887
+ if (this.isBorderProperty(key)) {
10888
+ this.emitStyle(this.buildBorderStyleDraft(key, value));
10889
+ return;
10890
+ }
10891
+ const nextStyle = this.createStyleDraft();
10892
+ this.assignStyleValue(nextStyle, key, value);
10893
+ this.emitStyle(nextStyle);
10894
+ }
10895
+ buildBorderStyleDraft(property, value) {
10896
+ const nextStyle = this.createStyleDraft();
10897
+ const side = this.selectedSide();
10898
+ if (side === 'all') {
10899
+ this.clearBorderOverrides(nextStyle, property);
10900
+ this.assignStyleValue(nextStyle, property, value);
10901
+ return nextStyle;
10902
+ }
10903
+ this.assignStyleValue(nextStyle, BORDER_SIDE_KEYS[side][property], value);
10904
+ return nextStyle;
10905
+ }
10906
+ isBorderProperty(key) {
10907
+ return key === 'borderStyle' || key === 'borderWidth' || key === 'borderColor';
10908
+ }
10909
+ getDefaultBorderValue(property) {
10910
+ switch (property) {
10911
+ case 'borderStyle':
10912
+ return 'none';
10913
+ case 'borderColor':
10914
+ return '#000000';
10915
+ default:
10916
+ return '0';
10917
+ }
10918
+ }
10919
+ createStyleDraft() {
10920
+ return { ...this.style() };
10921
+ }
10922
+ clearBorderOverrides(style, property) {
10923
+ for (const side of Object.keys(BORDER_SIDE_KEYS)) {
10924
+ delete style[BORDER_SIDE_KEYS[side][property]];
10925
+ }
10926
+ }
10927
+ clearRadiusOverrides(style) {
10928
+ for (const corner of Object.keys(RADIUS_CORNER_KEYS)) {
10929
+ delete style[RADIUS_CORNER_KEYS[corner]];
10930
+ }
10931
+ }
10932
+ assignStyleValue(style, key, value) {
10933
+ if (value === undefined || value === null || value === '') {
10934
+ delete style[key];
10935
+ return;
10936
+ }
10937
+ style[key] = value;
10938
+ }
10939
+ emitStyle(style) {
10940
+ this.styleChange.emit(style);
10722
10941
  }
10723
10942
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: InspectorBordersSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10724
10943
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: InspectorBordersSectionComponent, isStandalone: true, selector: "inspector-borders-section", inputs: { style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { styleChange: "styleChange" }, ngImport: i0, template: `
10725
- <div class="flex flex-col gap-3">
10726
- <!-- Radius Row -->
10727
- <div class="flex items-center gap-2">
10728
- <span class="text-[12px] text-gray-500 w-14">Radius</span>
10729
- <div class="flex-1 flex items-center gap-2">
10730
- <!-- Corner selector -->
10731
- <div class="flex gap-1">
10732
- @for (opt of radiusCorners; track opt.corner) {
10944
+ <div class="flex flex-col gap-4">
10945
+ <div class="grid grid-cols-[56px_1fr] gap-3 items-start">
10946
+ <span class="section-label text-[12px] pt-2">Radius</span>
10947
+ <div class="flex flex-col gap-2">
10948
+ <div class="flex flex-wrap gap-1">
10949
+ @for (option of radiusCorners; track option.corner) {
10733
10950
  <button
10734
10951
  type="button"
10735
- (click)="selectCorner(opt.corner)"
10736
- [class]="selectedCorner() === opt.corner
10737
- ? 'w-6 h-6 flex items-center justify-center bg-gray-200 rounded text-gray-700 border border-gray-400'
10738
- : 'w-6 h-6 flex items-center justify-center bg-input-dark rounded text-gray-500 border border-transparent hover:border-gray-300'"
10739
- [title]="opt.label">
10740
- <lucide-icon [name]="opt.icon" class="w-3 h-3"></lucide-icon>
10952
+ (click)="selectCorner(option.corner)"
10953
+ [class]="getSelectorClass(selectedCorner() === option.corner)"
10954
+ [attr.aria-pressed]="selectedCorner() === option.corner">
10955
+ {{ option.label }}
10741
10956
  </button>
10742
10957
  }
10743
10958
  </div>
10744
-
10745
- <!-- Slider -->
10746
- <input
10747
- type="range"
10748
- [ngModel]="parseValue(getRadiusValue())"
10749
- (ngModelChange)="setRadiusValue($event + 'px')"
10750
- min="0"
10751
- max="50"
10752
- class="flex-1 h-0.5 bg-gray-300 rounded appearance-none cursor-pointer accent-primary-blue">
10753
-
10754
- <!-- Value -->
10755
- <div class="inspector-input-with-unit w-14">
10959
+
10960
+ <div class="flex items-center gap-2">
10756
10961
  <input
10757
- type="text"
10758
- [ngModel]="getRadiusValue()"
10759
- (ngModelChange)="setRadiusValue($event)"
10760
- class="inspector-number-input">
10761
- <span class="inspector-unit">PX</span>
10962
+ type="range"
10963
+ [ngModel]="parseValue(getRadiusValue())"
10964
+ (ngModelChange)="setRadiusValue($event + 'px')"
10965
+ min="0"
10966
+ max="50"
10967
+ class="flex-1 h-1 cursor-pointer accent-primary-blue">
10968
+
10969
+ <div class="inspector-input-with-unit w-[88px]">
10970
+ <input
10971
+ type="text"
10972
+ [ngModel]="getRadiusValue()"
10973
+ (ngModelChange)="setRadiusValue($event)"
10974
+ class="inspector-number-input"
10975
+ aria-label="Border radius">
10976
+ <span class="inspector-unit">PX</span>
10977
+ </div>
10762
10978
  </div>
10763
10979
  </div>
10764
10980
  </div>
10765
-
10766
- <!-- Borders Section -->
10767
- <div class="text-[12px] text-gray-500 mb-1">Borders</div>
10768
-
10769
- <div class="grid grid-cols-[auto_1fr] gap-4">
10770
- <!-- Side Selector Grid -->
10771
- <div class="grid grid-cols-3 gap-1 w-fit place-items-center">
10772
- <!-- Top -->
10773
- <div class="col-start-2 w-5 h-5 flex items-center justify-center border border-border-dark rounded hover:bg-gray-100 cursor-pointer"
10774
- (click)="selectSide('top')"
10775
- [class.bg-gray-200]="selectedSide() === 'top'">
10776
- <div class="w-3 h-[1px] bg-gray-500"></div>
10777
- </div>
10778
- <!-- Left -->
10779
- <div class="col-start-1 row-start-2 w-5 h-5 flex items-center justify-center border border-border-dark rounded hover:bg-gray-100 cursor-pointer"
10780
- (click)="selectSide('left')"
10781
- [class.bg-gray-200]="selectedSide() === 'left'">
10782
- <div class="w-[1px] h-3 bg-gray-500"></div>
10783
- </div>
10784
- <!-- All -->
10785
- <div class="col-start-2 row-start-2 w-6 h-6 flex items-center justify-center bg-gray-200 border border-gray-400 rounded cursor-pointer"
10786
- (click)="selectSide('all')"
10787
- [class.border-gray-600]="selectedSide() === 'all'">
10788
- <div class="w-3 h-3 border border-gray-600"></div>
10789
- </div>
10790
- <!-- Right -->
10791
- <div class="col-start-3 row-start-2 w-5 h-5 flex items-center justify-center border border-border-dark rounded hover:bg-gray-100 cursor-pointer"
10792
- (click)="selectSide('right')"
10793
- [class.bg-gray-200]="selectedSide() === 'right'">
10794
- <div class="w-[1px] h-3 bg-gray-500"></div>
10795
- </div>
10796
- <!-- Bottom -->
10797
- <div class="col-start-2 row-start-3 w-5 h-5 flex items-center justify-center border border-border-dark rounded hover:bg-gray-100 cursor-pointer"
10798
- (click)="selectSide('bottom')"
10799
- [class.bg-gray-200]="selectedSide() === 'bottom'">
10800
- <div class="w-3 h-[1px] bg-gray-500"></div>
10801
- </div>
10802
- </div>
10803
-
10804
- <!-- Border Controls -->
10805
- <div class="flex flex-col gap-2 w-full">
10806
- <!-- Style -->
10807
- <div class="flex items-center justify-between">
10808
- <span class="text-[12px] text-gray-500 w-10">Style</span>
10809
- <div class="flex bg-input-dark rounded border border-border-dark p-[1px]">
10810
- @for (st of borderStyles; track st.value) {
10981
+
10982
+ <div class="overflow-hidden rounded-lg border border-border-dark bg-white p-3">
10983
+ <div class="grid min-w-0 grid-cols-[56px_1fr] gap-3 items-start">
10984
+ <span class="section-label text-[12px] pt-2">Borders</span>
10985
+ <div class="flex min-w-0 flex-col gap-3">
10986
+ <div class="flex flex-wrap gap-1">
10987
+ @for (option of borderSides; track option.side) {
10811
10988
  <button
10812
10989
  type="button"
10813
- (click)="updateStyle('borderStyle', st.value)"
10814
- [class]="style()['borderStyle'] === st.value
10815
- ? 'p-1 px-2 bg-gray-200 rounded'
10816
- : 'p-1 px-2 hover:bg-gray-100 rounded'">
10817
- <lucide-icon [name]="st.icon"
10818
- [class]="style()['borderStyle'] === st.value ? 'w-3 h-3 text-gray-700' : 'w-3 h-3 text-gray-400'">
10819
- </lucide-icon>
10990
+ (click)="selectSide(option.side)"
10991
+ [class]="getSelectorClass(selectedSide() === option.side)"
10992
+ [attr.aria-pressed]="selectedSide() === option.side">
10993
+ {{ option.label }}
10820
10994
  </button>
10821
10995
  }
10822
10996
  </div>
10823
- </div>
10824
-
10825
- <!-- Width -->
10826
- <div class="flex items-center justify-between">
10827
- <span class="text-[12px] text-gray-500 w-10">Width</span>
10828
- <div class="inspector-input-with-unit w-24">
10829
- <input
10830
- type="text"
10831
- [ngModel]="style()['borderWidth'] || '0'"
10832
- (ngModelChange)="updateStyle('borderWidth', $event)"
10833
- class="inspector-number-input flex-1 text-left">
10834
- <span class="inspector-unit">PX</span>
10997
+
10998
+ <p class="text-[11px] text-gray-500">
10999
+ Editing {{ selectedSideLabel() }} border
11000
+ </p>
11001
+
11002
+ <div class="grid grid-cols-[52px_1fr] gap-2 items-center">
11003
+ <label class="section-label text-[12px]" for="inspector-border-style">Style</label>
11004
+ <div
11005
+ id="inspector-border-style"
11006
+ class="grid grid-cols-4 rounded-md border border-border-dark bg-input-dark p-1">
11007
+ @for (styleOption of borderStyles; track styleOption.value) {
11008
+ <button
11009
+ type="button"
11010
+ (click)="updateStyle('borderStyle', styleOption.value)"
11011
+ [class]="getSegmentClass(getBorderValue('borderStyle') === styleOption.value)">
11012
+ {{ styleOption.label }}
11013
+ </button>
11014
+ }
11015
+ </div>
10835
11016
  </div>
10836
- </div>
10837
-
10838
- <!-- Color -->
10839
- <div class="flex items-center justify-between">
10840
- <span class="text-[12px] text-gray-500 w-10">Color</span>
10841
- <div class="flex items-center w-24 bg-input-dark border border-border-dark rounded px-1 py-0.5 cursor-pointer">
10842
- <input
10843
- type="color"
10844
- [ngModel]="style()['borderColor'] || '#000000'"
10845
- (ngModelChange)="updateStyle('borderColor', $event)"
10846
- class="w-3 h-3 border border-gray-300 mr-2 cursor-pointer">
10847
- <span class="text-sm text-gray-700">{{ getColorName(style()['borderColor']) }}</span>
11017
+
11018
+ <div class="grid grid-cols-[52px_1fr] gap-2 items-center">
11019
+ <label class="section-label text-[12px]" for="inspector-border-width">Width</label>
11020
+ <div class="inspector-input-with-unit min-w-0">
11021
+ <input
11022
+ id="inspector-border-width"
11023
+ data-testid="border-width-input"
11024
+ type="text"
11025
+ [ngModel]="getBorderValue('borderWidth')"
11026
+ (ngModelChange)="updateStyle('borderWidth', $event)"
11027
+ class="inspector-number-input"
11028
+ aria-label="Border width">
11029
+ <span class="inspector-unit">PX</span>
11030
+ </div>
11031
+ </div>
11032
+
11033
+ <div class="grid grid-cols-[52px_1fr] gap-2 items-center">
11034
+ <label class="section-label text-[12px]" for="inspector-border-color">Color</label>
11035
+ <div class="flex min-w-0 items-center gap-2 rounded-md border border-border-dark bg-input-dark px-2 py-1">
11036
+ <input
11037
+ id="inspector-border-color"
11038
+ type="color"
11039
+ [ngModel]="getColorInputValue()"
11040
+ (ngModelChange)="updateStyle('borderColor', $event)"
11041
+ class="h-7 w-7 shrink-0 cursor-pointer rounded border border-border-dark bg-white">
11042
+
11043
+ <input
11044
+ data-testid="border-color-input"
11045
+ type="text"
11046
+ [ngModel]="getBorderValue('borderColor')"
11047
+ (ngModelChange)="updateStyle('borderColor', $event)"
11048
+ class="h-8 min-w-0 flex-1 bg-transparent text-sm text-gray-700 focus:outline-none"
11049
+ aria-label="Border color">
11050
+ </div>
10848
11051
  </div>
10849
11052
  </div>
10850
11053
  </div>
10851
11054
  </div>
10852
11055
  </div>
10853
- `, isInline: true, styles: [".inspector-input-with-unit{display:flex;align-items:center;background-color:var(--color-input-dark);border:1px solid var(--color-border-dark);border-radius:var(--radius-md);padding-left:.25rem;padding-right:.25rem;overflow:hidden}.inspector-number-input{height:2rem;padding-left:.25rem;padding-right:.25rem;background-color:transparent;border:none;text-align:right;font-size:.875rem;line-height:1.25rem;color:var(--color-ink-700);width:100%}.inspector-number-input:focus{outline:none;--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000}.inspector-unit{font-size:11px;color:var(--color-ink-400);margin-left:.25rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: UiIconModule }, { kind: "component", type: i3$1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] });
11056
+ `, isInline: true, styles: [".section-label{font-size:12px;color:var(--color-ink-400)}.inspector-input-with-unit{display:flex;align-items:center;min-width:0;background-color:var(--color-input-dark);border:1px solid var(--color-border-dark);border-radius:var(--radius-md);overflow:hidden}.inspector-number-input{width:100%;min-width:0;height:2rem;padding-left:.5rem;padding-right:.5rem;background-color:transparent;border:none;color:var(--color-ink-700);font-size:.875rem;line-height:1.25rem}.inspector-number-input:focus{outline:none}.inspector-unit{display:flex;align-items:center;height:2rem;padding-left:.5rem;padding-right:.5rem;border-left:1px solid var(--color-border-dark);font-size:11px;color:var(--color-ink-400);background-color:var(--color-input-dark)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
10854
11057
  }
10855
11058
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: InspectorBordersSectionComponent, decorators: [{
10856
11059
  type: Component,
10857
- args: [{ selector: 'inspector-borders-section', standalone: true, imports: [CommonModule, FormsModule, UiIconModule], template: `
10858
- <div class="flex flex-col gap-3">
10859
- <!-- Radius Row -->
10860
- <div class="flex items-center gap-2">
10861
- <span class="text-[12px] text-gray-500 w-14">Radius</span>
10862
- <div class="flex-1 flex items-center gap-2">
10863
- <!-- Corner selector -->
10864
- <div class="flex gap-1">
10865
- @for (opt of radiusCorners; track opt.corner) {
11060
+ args: [{ selector: 'inspector-borders-section', standalone: true, imports: [CommonModule, FormsModule], template: `
11061
+ <div class="flex flex-col gap-4">
11062
+ <div class="grid grid-cols-[56px_1fr] gap-3 items-start">
11063
+ <span class="section-label text-[12px] pt-2">Radius</span>
11064
+ <div class="flex flex-col gap-2">
11065
+ <div class="flex flex-wrap gap-1">
11066
+ @for (option of radiusCorners; track option.corner) {
10866
11067
  <button
10867
11068
  type="button"
10868
- (click)="selectCorner(opt.corner)"
10869
- [class]="selectedCorner() === opt.corner
10870
- ? 'w-6 h-6 flex items-center justify-center bg-gray-200 rounded text-gray-700 border border-gray-400'
10871
- : 'w-6 h-6 flex items-center justify-center bg-input-dark rounded text-gray-500 border border-transparent hover:border-gray-300'"
10872
- [title]="opt.label">
10873
- <lucide-icon [name]="opt.icon" class="w-3 h-3"></lucide-icon>
11069
+ (click)="selectCorner(option.corner)"
11070
+ [class]="getSelectorClass(selectedCorner() === option.corner)"
11071
+ [attr.aria-pressed]="selectedCorner() === option.corner">
11072
+ {{ option.label }}
10874
11073
  </button>
10875
11074
  }
10876
11075
  </div>
10877
-
10878
- <!-- Slider -->
10879
- <input
10880
- type="range"
10881
- [ngModel]="parseValue(getRadiusValue())"
10882
- (ngModelChange)="setRadiusValue($event + 'px')"
10883
- min="0"
10884
- max="50"
10885
- class="flex-1 h-0.5 bg-gray-300 rounded appearance-none cursor-pointer accent-primary-blue">
10886
-
10887
- <!-- Value -->
10888
- <div class="inspector-input-with-unit w-14">
11076
+
11077
+ <div class="flex items-center gap-2">
10889
11078
  <input
10890
- type="text"
10891
- [ngModel]="getRadiusValue()"
10892
- (ngModelChange)="setRadiusValue($event)"
10893
- class="inspector-number-input">
10894
- <span class="inspector-unit">PX</span>
11079
+ type="range"
11080
+ [ngModel]="parseValue(getRadiusValue())"
11081
+ (ngModelChange)="setRadiusValue($event + 'px')"
11082
+ min="0"
11083
+ max="50"
11084
+ class="flex-1 h-1 cursor-pointer accent-primary-blue">
11085
+
11086
+ <div class="inspector-input-with-unit w-[88px]">
11087
+ <input
11088
+ type="text"
11089
+ [ngModel]="getRadiusValue()"
11090
+ (ngModelChange)="setRadiusValue($event)"
11091
+ class="inspector-number-input"
11092
+ aria-label="Border radius">
11093
+ <span class="inspector-unit">PX</span>
11094
+ </div>
10895
11095
  </div>
10896
11096
  </div>
10897
11097
  </div>
10898
-
10899
- <!-- Borders Section -->
10900
- <div class="text-[12px] text-gray-500 mb-1">Borders</div>
10901
-
10902
- <div class="grid grid-cols-[auto_1fr] gap-4">
10903
- <!-- Side Selector Grid -->
10904
- <div class="grid grid-cols-3 gap-1 w-fit place-items-center">
10905
- <!-- Top -->
10906
- <div class="col-start-2 w-5 h-5 flex items-center justify-center border border-border-dark rounded hover:bg-gray-100 cursor-pointer"
10907
- (click)="selectSide('top')"
10908
- [class.bg-gray-200]="selectedSide() === 'top'">
10909
- <div class="w-3 h-[1px] bg-gray-500"></div>
10910
- </div>
10911
- <!-- Left -->
10912
- <div class="col-start-1 row-start-2 w-5 h-5 flex items-center justify-center border border-border-dark rounded hover:bg-gray-100 cursor-pointer"
10913
- (click)="selectSide('left')"
10914
- [class.bg-gray-200]="selectedSide() === 'left'">
10915
- <div class="w-[1px] h-3 bg-gray-500"></div>
10916
- </div>
10917
- <!-- All -->
10918
- <div class="col-start-2 row-start-2 w-6 h-6 flex items-center justify-center bg-gray-200 border border-gray-400 rounded cursor-pointer"
10919
- (click)="selectSide('all')"
10920
- [class.border-gray-600]="selectedSide() === 'all'">
10921
- <div class="w-3 h-3 border border-gray-600"></div>
10922
- </div>
10923
- <!-- Right -->
10924
- <div class="col-start-3 row-start-2 w-5 h-5 flex items-center justify-center border border-border-dark rounded hover:bg-gray-100 cursor-pointer"
10925
- (click)="selectSide('right')"
10926
- [class.bg-gray-200]="selectedSide() === 'right'">
10927
- <div class="w-[1px] h-3 bg-gray-500"></div>
10928
- </div>
10929
- <!-- Bottom -->
10930
- <div class="col-start-2 row-start-3 w-5 h-5 flex items-center justify-center border border-border-dark rounded hover:bg-gray-100 cursor-pointer"
10931
- (click)="selectSide('bottom')"
10932
- [class.bg-gray-200]="selectedSide() === 'bottom'">
10933
- <div class="w-3 h-[1px] bg-gray-500"></div>
10934
- </div>
10935
- </div>
10936
-
10937
- <!-- Border Controls -->
10938
- <div class="flex flex-col gap-2 w-full">
10939
- <!-- Style -->
10940
- <div class="flex items-center justify-between">
10941
- <span class="text-[12px] text-gray-500 w-10">Style</span>
10942
- <div class="flex bg-input-dark rounded border border-border-dark p-[1px]">
10943
- @for (st of borderStyles; track st.value) {
11098
+
11099
+ <div class="overflow-hidden rounded-lg border border-border-dark bg-white p-3">
11100
+ <div class="grid min-w-0 grid-cols-[56px_1fr] gap-3 items-start">
11101
+ <span class="section-label text-[12px] pt-2">Borders</span>
11102
+ <div class="flex min-w-0 flex-col gap-3">
11103
+ <div class="flex flex-wrap gap-1">
11104
+ @for (option of borderSides; track option.side) {
10944
11105
  <button
10945
11106
  type="button"
10946
- (click)="updateStyle('borderStyle', st.value)"
10947
- [class]="style()['borderStyle'] === st.value
10948
- ? 'p-1 px-2 bg-gray-200 rounded'
10949
- : 'p-1 px-2 hover:bg-gray-100 rounded'">
10950
- <lucide-icon [name]="st.icon"
10951
- [class]="style()['borderStyle'] === st.value ? 'w-3 h-3 text-gray-700' : 'w-3 h-3 text-gray-400'">
10952
- </lucide-icon>
11107
+ (click)="selectSide(option.side)"
11108
+ [class]="getSelectorClass(selectedSide() === option.side)"
11109
+ [attr.aria-pressed]="selectedSide() === option.side">
11110
+ {{ option.label }}
10953
11111
  </button>
10954
11112
  }
10955
11113
  </div>
10956
- </div>
10957
-
10958
- <!-- Width -->
10959
- <div class="flex items-center justify-between">
10960
- <span class="text-[12px] text-gray-500 w-10">Width</span>
10961
- <div class="inspector-input-with-unit w-24">
10962
- <input
10963
- type="text"
10964
- [ngModel]="style()['borderWidth'] || '0'"
10965
- (ngModelChange)="updateStyle('borderWidth', $event)"
10966
- class="inspector-number-input flex-1 text-left">
10967
- <span class="inspector-unit">PX</span>
11114
+
11115
+ <p class="text-[11px] text-gray-500">
11116
+ Editing {{ selectedSideLabel() }} border
11117
+ </p>
11118
+
11119
+ <div class="grid grid-cols-[52px_1fr] gap-2 items-center">
11120
+ <label class="section-label text-[12px]" for="inspector-border-style">Style</label>
11121
+ <div
11122
+ id="inspector-border-style"
11123
+ class="grid grid-cols-4 rounded-md border border-border-dark bg-input-dark p-1">
11124
+ @for (styleOption of borderStyles; track styleOption.value) {
11125
+ <button
11126
+ type="button"
11127
+ (click)="updateStyle('borderStyle', styleOption.value)"
11128
+ [class]="getSegmentClass(getBorderValue('borderStyle') === styleOption.value)">
11129
+ {{ styleOption.label }}
11130
+ </button>
11131
+ }
11132
+ </div>
10968
11133
  </div>
10969
- </div>
10970
-
10971
- <!-- Color -->
10972
- <div class="flex items-center justify-between">
10973
- <span class="text-[12px] text-gray-500 w-10">Color</span>
10974
- <div class="flex items-center w-24 bg-input-dark border border-border-dark rounded px-1 py-0.5 cursor-pointer">
10975
- <input
10976
- type="color"
10977
- [ngModel]="style()['borderColor'] || '#000000'"
10978
- (ngModelChange)="updateStyle('borderColor', $event)"
10979
- class="w-3 h-3 border border-gray-300 mr-2 cursor-pointer">
10980
- <span class="text-sm text-gray-700">{{ getColorName(style()['borderColor']) }}</span>
11134
+
11135
+ <div class="grid grid-cols-[52px_1fr] gap-2 items-center">
11136
+ <label class="section-label text-[12px]" for="inspector-border-width">Width</label>
11137
+ <div class="inspector-input-with-unit min-w-0">
11138
+ <input
11139
+ id="inspector-border-width"
11140
+ data-testid="border-width-input"
11141
+ type="text"
11142
+ [ngModel]="getBorderValue('borderWidth')"
11143
+ (ngModelChange)="updateStyle('borderWidth', $event)"
11144
+ class="inspector-number-input"
11145
+ aria-label="Border width">
11146
+ <span class="inspector-unit">PX</span>
11147
+ </div>
11148
+ </div>
11149
+
11150
+ <div class="grid grid-cols-[52px_1fr] gap-2 items-center">
11151
+ <label class="section-label text-[12px]" for="inspector-border-color">Color</label>
11152
+ <div class="flex min-w-0 items-center gap-2 rounded-md border border-border-dark bg-input-dark px-2 py-1">
11153
+ <input
11154
+ id="inspector-border-color"
11155
+ type="color"
11156
+ [ngModel]="getColorInputValue()"
11157
+ (ngModelChange)="updateStyle('borderColor', $event)"
11158
+ class="h-7 w-7 shrink-0 cursor-pointer rounded border border-border-dark bg-white">
11159
+
11160
+ <input
11161
+ data-testid="border-color-input"
11162
+ type="text"
11163
+ [ngModel]="getBorderValue('borderColor')"
11164
+ (ngModelChange)="updateStyle('borderColor', $event)"
11165
+ class="h-8 min-w-0 flex-1 bg-transparent text-sm text-gray-700 focus:outline-none"
11166
+ aria-label="Border color">
11167
+ </div>
10981
11168
  </div>
10982
11169
  </div>
10983
11170
  </div>
10984
11171
  </div>
10985
11172
  </div>
10986
- `, styles: [".inspector-input-with-unit{display:flex;align-items:center;background-color:var(--color-input-dark);border:1px solid var(--color-border-dark);border-radius:var(--radius-md);padding-left:.25rem;padding-right:.25rem;overflow:hidden}.inspector-number-input{height:2rem;padding-left:.25rem;padding-right:.25rem;background-color:transparent;border:none;text-align:right;font-size:.875rem;line-height:1.25rem;color:var(--color-ink-700);width:100%}.inspector-number-input:focus{outline:none;--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000}.inspector-unit{font-size:11px;color:var(--color-ink-400);margin-left:.25rem}\n"] }]
11173
+ `, styles: [".section-label{font-size:12px;color:var(--color-ink-400)}.inspector-input-with-unit{display:flex;align-items:center;min-width:0;background-color:var(--color-input-dark);border:1px solid var(--color-border-dark);border-radius:var(--radius-md);overflow:hidden}.inspector-number-input{width:100%;min-width:0;height:2rem;padding-left:.5rem;padding-right:.5rem;background-color:transparent;border:none;color:var(--color-ink-700);font-size:.875rem;line-height:1.25rem}.inspector-number-input:focus{outline:none}.inspector-unit{display:flex;align-items:center;height:2rem;padding-left:.5rem;padding-right:.5rem;border-left:1px solid var(--color-border-dark);font-size:11px;color:var(--color-ink-400);background-color:var(--color-input-dark)}\n"] }]
10987
11174
  }] });
10988
11175
 
10989
11176
  const DATA_SOURCE_CLIENT = new InjectionToken('DATA_SOURCE_CLIENT');
@@ -26158,7 +26345,7 @@ function joinClasses(...classNames) {
26158
26345
  const TEXT_CONTROL_BASE_CLASS = 'block w-full rounded-[4px] border bg-transparent px-3 text-sm text-[#1C2431] transition-all placeholder:text-transparent hover:border-[#1C2431]/40 focus:outline-none disabled:cursor-not-allowed disabled:border-[#E6EAF0] disabled:bg-[#E6EAF0]/40 disabled:text-[#1C2431]/40';
26159
26346
  const TEXT_CONTROL_VALID_CLASS = 'border-[#E6EAF0] focus:border-[#7FB2FF] focus:border-2 focus:ring-0';
26160
26347
  const TEXT_CONTROL_INVALID_CLASS = 'border-red-500 border-2 text-red-700 placeholder:text-red-300 focus:border-red-500 focus:ring-0';
26161
- const FIELD_CONTAINER_CLASS = 'relative w-full font-sans';
26348
+ const FIELD_CONTAINER_CLASS = 'relative flex h-full min-h-0 w-full flex-col font-sans';
26162
26349
  const FIELD_LABEL_CLASS = 'mb-[0.25em] block font-sans text-xs font-normal tracking-[0.00937em] text-[#1C2431]/70';
26163
26350
  const FIELD_REQUIRED_CLASS = 'text-red-500';
26164
26351
  const FIELD_HELP_CLASS = 'mt-1 text-xs leading-5 tracking-[0.03333em] text-[#1C2431]/50';
@@ -26167,7 +26354,7 @@ const FIELD_CHOICE_SURFACE_CLASS = 'flex items-start gap-3 rounded-[4px] border
26167
26354
  const FIELD_CHOICE_LABEL_CLASS = 'text-sm leading-6 tracking-[0.01786em] text-[#1C2431]';
26168
26355
  const FIELD_RESULTS_PANEL_CLASS = 'absolute z-30 mt-1 max-h-64 w-full overflow-auto rounded-[4px] border-0 bg-[#FFFFFF] py-2 shadow-[0_5px_5px_-3px_rgba(0,0,0,.2),0_8px_10px_1px_rgba(0,0,0,.14),0_3px_14px_2px_rgba(0,0,0,.12)]';
26169
26356
  const FIELD_OPTION_CLASS = 'block w-full px-4 py-3 text-left text-sm tracking-[0.01786em] text-[#1C2431] transition hover:bg-[#7FB2FF]/[0.08] active:bg-[#7FB2FF]/[0.14]';
26170
- const FILE_UPLOAD_SHELL_CLASS = 'rounded-[4px] border border-dashed border-[#E6EAF0] bg-transparent';
26357
+ const FILE_UPLOAD_SHELL_CLASS = 'flex flex-1 min-h-0 items-stretch rounded-[4px] border border-dashed border-[#E6EAF0] bg-transparent';
26171
26358
  const FILE_UPLOAD_CARD_CLASS = 'flex flex-col gap-0.5 rounded-[4px] border border-[#E6EAF0] bg-[#FFFFFF] px-3 py-2 text-xs text-[#1C2431] shadow-[0_1px_2px_0_rgba(0,0,0,.08)]';
26172
26359
  const CONTENT_TEXT_CLASS = 'mb-4 leading-6 tracking-[0.03125em] text-[#1C2431] text-[0.875rem]';
26173
26360
  const CONTENT_TEXT_MUTED_CLASS = 'text-[0.75rem] tracking-[0.03333em] text-[#1C2431]/50';
@@ -26208,13 +26395,20 @@ const TABLE_ICON_BUTTON_CLASS = 'inline-flex h-10 w-10 items-center justify-cent
26208
26395
  function getTextControlClass(options) {
26209
26396
  const multiline = options?.multiline === true;
26210
26397
  const compact = options?.compact === true;
26211
- return joinClasses(TEXT_CONTROL_BASE_CLASS, options?.invalid ? TEXT_CONTROL_INVALID_CLASS : TEXT_CONTROL_VALID_CLASS, multiline ? 'min-h-[96px] py-2 leading-6 resize-y' : compact ? 'min-h-[20px] py-0.5' : 'min-h-[20px] py-0.5', options?.leadingInset && 'pl-10', options?.trailingInset && 'pr-10');
26398
+ const framed = options?.framed === true;
26399
+ return joinClasses(TEXT_CONTROL_BASE_CLASS, framed
26400
+ ? options?.invalid
26401
+ ? 'border-transparent text-red-700 placeholder:text-red-300 focus:border-transparent focus:ring-0'
26402
+ : 'border-transparent focus:border-transparent focus:ring-0'
26403
+ : options?.invalid
26404
+ ? TEXT_CONTROL_INVALID_CLASS
26405
+ : TEXT_CONTROL_VALID_CLASS, 'h-full min-h-0', multiline ? 'min-h-[96px] py-2 leading-6 resize-y' : compact ? 'min-h-[20px] py-0.5' : 'min-h-[20px] py-0.5', options?.leadingInset && 'pl-10', options?.trailingInset && 'pr-10');
26212
26406
  }
26213
26407
  function getChoiceControlClass(options) {
26214
26408
  return joinClasses('mt-0.5 h-[18px] w-[18px] border-2 bg-[#FFFFFF] text-[#7FB2FF] transition focus:ring-2 focus:ring-[#7FB2FF] focus:ring-offset-0', options?.radio ? 'rounded-full' : 'rounded-[2px]', options?.invalid ? 'border-red-500 focus:ring-red-200' : 'border-[#1C2431]/40 checked:border-[#7FB2FF]');
26215
26409
  }
26216
26410
  function getFileInputClass(options) {
26217
- return joinClasses('block w-full cursor-pointer rounded-[4px] border bg-transparent px-3 py-3 text-sm tracking-[0.01786em] text-[#1C2431] transition hover:border-[#1C2431]/40 focus-visible:outline-none focus-visible:border-2 disabled:cursor-not-allowed disabled:border-[#E6EAF0] disabled:bg-[#E6EAF0]/40', 'file:mr-3 file:rounded-[2px] file:border file:px-3 file:py-1.5 file:text-xs file:font-medium file:tracking-[0.08929em] file:uppercase', 'file:border-[#7FB2FF] file:bg-transparent file:text-[#1C2431] hover:file:bg-[#7FB2FF]/[0.08]', options?.invalid
26411
+ return joinClasses('block h-full min-h-0 w-full cursor-pointer rounded-[4px] border bg-transparent px-3 py-3 text-sm tracking-[0.01786em] text-[#1C2431] transition hover:border-[#1C2431]/40 focus-visible:outline-none focus-visible:border-2 disabled:cursor-not-allowed disabled:border-[#E6EAF0] disabled:bg-[#E6EAF0]/40', 'file:mr-3 file:rounded-[2px] file:border file:px-3 file:py-1.5 file:text-xs file:font-medium file:tracking-[0.08929em] file:uppercase', 'file:border-[#7FB2FF] file:bg-transparent file:text-[#1C2431] hover:file:bg-[#7FB2FF]/[0.08]', options?.invalid
26218
26412
  ? 'border-red-500 border-2 text-red-700 focus-visible:border-red-500'
26219
26413
  : 'border-[#E6EAF0] focus-visible:border-[#7FB2FF]');
26220
26414
  }
@@ -26285,7 +26479,8 @@ class TextFieldWidgetComponent {
26285
26479
  getControlClass(multiline = false) {
26286
26480
  return getTextControlClass({
26287
26481
  invalid: !!this.error,
26288
- multiline
26482
+ multiline,
26483
+ framed: this.hasWrapperFrame()
26289
26484
  });
26290
26485
  }
26291
26486
  getAccessibleLabel() {
@@ -26376,11 +26571,17 @@ class TextFieldWidgetComponent {
26376
26571
  // Cleanup handled by takeUntilDestroyed
26377
26572
  }
26378
26573
  getWrapperStyles() {
26379
- if (!this.config?.style)
26380
- return {};
26574
+ const { wrapperStyles } = splitControlSurfaceStyles(this.config.style);
26381
26575
  return mergeAndNormalize({
26382
- width: '100%'
26383
- }, this.config.style);
26576
+ width: '100%',
26577
+ height: '100%'
26578
+ }, wrapperStyles);
26579
+ }
26580
+ getControlStyles() {
26581
+ return splitControlSurfaceStyles(this.config.style).controlStyles;
26582
+ }
26583
+ hasWrapperFrame() {
26584
+ return hasWrapperSurfaceStyles(this.config.style);
26384
26585
  }
26385
26586
  get visible() {
26386
26587
  return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
@@ -26508,7 +26709,7 @@ class TextFieldWidgetComponent {
26508
26709
  [ngStyle]="getWrapperStyles()"
26509
26710
  data-fd="field"
26510
26711
  [attr.data-fd-field-type]="config.type">
26511
- <div class="relative">
26712
+ <div class="relative flex-1 min-h-0">
26512
26713
  @if (isTextarea()) {
26513
26714
  <textarea
26514
26715
  [id]="fieldId"
@@ -26525,6 +26726,7 @@ class TextFieldWidgetComponent {
26525
26726
  [attr.minlength]="config.html5?.minLength"
26526
26727
  [attr.maxlength]="config.html5?.maxLength"
26527
26728
  [class]="getControlClass(true)"
26729
+ [ngStyle]="getControlStyles()"
26528
26730
  data-fd="field-control"></textarea>
26529
26731
  } @else {
26530
26732
  <input
@@ -26541,6 +26743,7 @@ class TextFieldWidgetComponent {
26541
26743
  [attr.aria-describedby]="getAriaDescribedBy()"
26542
26744
  [attr.aria-label]="getAccessibleLabel()"
26543
26745
  [class]="getControlClass()"
26746
+ [ngStyle]="getControlStyles()"
26544
26747
  data-fd="field-control"
26545
26748
  [attr.min]="config.html5?.min"
26546
26749
  [attr.max]="config.html5?.max"
@@ -26570,7 +26773,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
26570
26773
  [ngStyle]="getWrapperStyles()"
26571
26774
  data-fd="field"
26572
26775
  [attr.data-fd-field-type]="config.type">
26573
- <div class="relative">
26776
+ <div class="relative flex-1 min-h-0">
26574
26777
  @if (isTextarea()) {
26575
26778
  <textarea
26576
26779
  [id]="fieldId"
@@ -26587,6 +26790,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
26587
26790
  [attr.minlength]="config.html5?.minLength"
26588
26791
  [attr.maxlength]="config.html5?.maxLength"
26589
26792
  [class]="getControlClass(true)"
26793
+ [ngStyle]="getControlStyles()"
26590
26794
  data-fd="field-control"></textarea>
26591
26795
  } @else {
26592
26796
  <input
@@ -26603,6 +26807,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
26603
26807
  [attr.aria-describedby]="getAriaDescribedBy()"
26604
26808
  [attr.aria-label]="getAccessibleLabel()"
26605
26809
  [class]="getControlClass()"
26810
+ [ngStyle]="getControlStyles()"
26606
26811
  data-fd="field-control"
26607
26812
  [attr.min]="config.html5?.min"
26608
26813
  [attr.max]="config.html5?.max"
@@ -26695,9 +26900,7 @@ class FileUploadWidgetComponent {
26695
26900
  return ids.join(' ');
26696
26901
  }
26697
26902
  getWrapperStyles() {
26698
- if (!this.config?.style)
26699
- return {};
26700
- return mergeAndNormalize({ width: '100%' }, this.config.style);
26903
+ return mergeAndNormalize({ width: '100%', height: '100%' }, this.config.style);
26701
26904
  }
26702
26905
  get visible() {
26703
26906
  return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
@@ -26849,7 +27052,7 @@ class FileUploadWidgetComponent {
26849
27052
  [ngStyle]="getWrapperStyles()"
26850
27053
  data-fd="field"
26851
27054
  [attr.data-fd-field-type]="config.type">
26852
- <div class="flex flex-col gap-2">
27055
+ <div class="flex min-h-0 flex-1 flex-col gap-2">
26853
27056
  <div [class]="fileUploadShellClass" data-fd="file-upload">
26854
27057
  <input
26855
27058
  #fileInput
@@ -26927,7 +27130,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
26927
27130
  [ngStyle]="getWrapperStyles()"
26928
27131
  data-fd="field"
26929
27132
  [attr.data-fd-field-type]="config.type">
26930
- <div class="flex flex-col gap-2">
27133
+ <div class="flex min-h-0 flex-1 flex-col gap-2">
26931
27134
  <div [class]="fileUploadShellClass" data-fd="file-upload">
26932
27135
  <input
26933
27136
  #fileInput
@@ -27160,9 +27363,7 @@ class SelectWidgetComponent {
27160
27363
  };
27161
27364
  }
27162
27365
  getWrapperStyles() {
27163
- if (!this.config?.style)
27164
- return {};
27165
- return mergeAndNormalize({ width: '100%' }, this.config.style);
27366
+ return mergeAndNormalize({ width: '100%', height: '100%' }, this.config.style);
27166
27367
  }
27167
27368
  get visible() {
27168
27369
  return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
@@ -27421,7 +27622,7 @@ class SelectWidgetComponent {
27421
27622
  [inputAttrs]="getInputAttributes()"
27422
27623
  [typeahead]="searchTerms$"
27423
27624
  [minTermLength]="getMinSearchLength()"
27424
- class="fd-select"
27625
+ class="fd-select flex-1 min-h-0"
27425
27626
  data-fd="field-control"
27426
27627
  [attr.aria-describedby]="getAriaDescribedBy()"
27427
27628
  [attr.aria-invalid]="!!error"
@@ -27442,7 +27643,7 @@ class SelectWidgetComponent {
27442
27643
  <p [id]="helpTextId" [class]="fieldHelpClass" data-fd="field-help">{{ config.helpText }}</p>
27443
27644
  }
27444
27645
  </div>
27445
- `, isInline: true, styles: [":host ::ng-deep ng-select.fd-select{display:block}:host ::ng-deep ng-select.fd-select .ng-select-container{min-height:20px;border:1px solid #E6EAF0;border-radius:4px;background:#fff;box-shadow:none;transition:border-color .2s ease,box-shadow .2s ease}:host ::ng-deep ng-select.fd-select.ng-select-focused:not(.ng-select-opened) .ng-select-container,:host ::ng-deep ng-select.fd-select.ng-select-opened .ng-select-container{border-width:2px;border-color:#7fb2ff}:host ::ng-deep ng-select.fd-select[data-fd-field-state=invalid] .ng-select-container{border-width:2px;border-color:#ef4444}:host ::ng-deep ng-select.fd-select .ng-value-container{padding:2px 12px;gap:4px}:host ::ng-deep ng-select.fd-select .ng-placeholder,:host ::ng-deep ng-select.fd-select .ng-value-label,:host ::ng-deep ng-select.fd-select .ng-input>input{font-family:inherit;font-size:14px;line-height:20px}:host ::ng-deep ng-select.fd-select .ng-placeholder{color:#1c243166}:host ::ng-deep ng-select.fd-select .ng-select-container.ng-has-value .ng-placeholder{display:none}:host ::ng-deep ng-select.fd-select .ng-arrow-wrapper{padding-right:12px}:host ::ng-deep ng-select.fd-select .ng-arrow{border-color:rgba(28,36,49,.6) transparent transparent}:host ::ng-deep ng-select.fd-select .ng-clear-wrapper{color:#1c243199}:host ::ng-deep .ng-dropdown-panel{border:1px solid #E6EAF0;border-radius:8px;background:#fff;box-shadow:0 10px 30px #0000001f}:host ::ng-deep .ng-dropdown-panel .ng-option{padding:10px 14px;font-size:14px;line-height:20px;background:#fff;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked{background:#7fb2ff14;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-selected{background:#7fb2ff24;color:#1c2431}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }] });
27646
+ `, isInline: true, styles: [":host ::ng-deep ng-select.fd-select{display:block;min-height:0}:host ::ng-deep ng-select.fd-select .ng-select-container{height:100%;min-height:20px;border:1px solid #E6EAF0;border-radius:4px;background:#fff;box-shadow:none;transition:border-color .2s ease,box-shadow .2s ease}:host ::ng-deep ng-select.fd-select.ng-select-focused:not(.ng-select-opened) .ng-select-container,:host ::ng-deep ng-select.fd-select.ng-select-opened .ng-select-container{border-width:2px;border-color:#7fb2ff}:host ::ng-deep ng-select.fd-select[data-fd-field-state=invalid] .ng-select-container{border-width:2px;border-color:#ef4444}:host ::ng-deep ng-select.fd-select .ng-value-container{align-items:center;min-height:100%;padding:2px 12px;gap:4px}:host ::ng-deep ng-select.fd-select .ng-placeholder,:host ::ng-deep ng-select.fd-select .ng-value-label,:host ::ng-deep ng-select.fd-select .ng-input>input{font-family:inherit;font-size:14px;line-height:20px}:host ::ng-deep ng-select.fd-select .ng-placeholder{color:#1c243166}:host ::ng-deep ng-select.fd-select .ng-select-container.ng-has-value .ng-placeholder{display:none}:host ::ng-deep ng-select.fd-select .ng-arrow-wrapper{padding-right:12px}:host ::ng-deep ng-select.fd-select .ng-arrow{border-color:rgba(28,36,49,.6) transparent transparent}:host ::ng-deep ng-select.fd-select .ng-clear-wrapper{color:#1c243199}:host ::ng-deep .ng-dropdown-panel{border:1px solid #E6EAF0;border-radius:8px;background:#fff;box-shadow:0 10px 30px #0000001f}:host ::ng-deep .ng-dropdown-panel .ng-option{padding:10px 14px;font-size:14px;line-height:20px;background:#fff;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked{background:#7fb2ff14;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-selected{background:#7fb2ff24;color:#1c2431}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }] });
27446
27647
  }
27447
27648
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SelectWidgetComponent, decorators: [{
27448
27649
  type: Component,
@@ -27469,7 +27670,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
27469
27670
  [inputAttrs]="getInputAttributes()"
27470
27671
  [typeahead]="searchTerms$"
27471
27672
  [minTermLength]="getMinSearchLength()"
27472
- class="fd-select"
27673
+ class="fd-select flex-1 min-h-0"
27473
27674
  data-fd="field-control"
27474
27675
  [attr.aria-describedby]="getAriaDescribedBy()"
27475
27676
  [attr.aria-invalid]="!!error"
@@ -27490,7 +27691,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
27490
27691
  <p [id]="helpTextId" [class]="fieldHelpClass" data-fd="field-help">{{ config.helpText }}</p>
27491
27692
  }
27492
27693
  </div>
27493
- `, styles: [":host ::ng-deep ng-select.fd-select{display:block}:host ::ng-deep ng-select.fd-select .ng-select-container{min-height:20px;border:1px solid #E6EAF0;border-radius:4px;background:#fff;box-shadow:none;transition:border-color .2s ease,box-shadow .2s ease}:host ::ng-deep ng-select.fd-select.ng-select-focused:not(.ng-select-opened) .ng-select-container,:host ::ng-deep ng-select.fd-select.ng-select-opened .ng-select-container{border-width:2px;border-color:#7fb2ff}:host ::ng-deep ng-select.fd-select[data-fd-field-state=invalid] .ng-select-container{border-width:2px;border-color:#ef4444}:host ::ng-deep ng-select.fd-select .ng-value-container{padding:2px 12px;gap:4px}:host ::ng-deep ng-select.fd-select .ng-placeholder,:host ::ng-deep ng-select.fd-select .ng-value-label,:host ::ng-deep ng-select.fd-select .ng-input>input{font-family:inherit;font-size:14px;line-height:20px}:host ::ng-deep ng-select.fd-select .ng-placeholder{color:#1c243166}:host ::ng-deep ng-select.fd-select .ng-select-container.ng-has-value .ng-placeholder{display:none}:host ::ng-deep ng-select.fd-select .ng-arrow-wrapper{padding-right:12px}:host ::ng-deep ng-select.fd-select .ng-arrow{border-color:rgba(28,36,49,.6) transparent transparent}:host ::ng-deep ng-select.fd-select .ng-clear-wrapper{color:#1c243199}:host ::ng-deep .ng-dropdown-panel{border:1px solid #E6EAF0;border-radius:8px;background:#fff;box-shadow:0 10px 30px #0000001f}:host ::ng-deep .ng-dropdown-panel .ng-option{padding:10px 14px;font-size:14px;line-height:20px;background:#fff;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked{background:#7fb2ff14;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-selected{background:#7fb2ff24;color:#1c2431}\n"] }]
27694
+ `, styles: [":host ::ng-deep ng-select.fd-select{display:block;min-height:0}:host ::ng-deep ng-select.fd-select .ng-select-container{height:100%;min-height:20px;border:1px solid #E6EAF0;border-radius:4px;background:#fff;box-shadow:none;transition:border-color .2s ease,box-shadow .2s ease}:host ::ng-deep ng-select.fd-select.ng-select-focused:not(.ng-select-opened) .ng-select-container,:host ::ng-deep ng-select.fd-select.ng-select-opened .ng-select-container{border-width:2px;border-color:#7fb2ff}:host ::ng-deep ng-select.fd-select[data-fd-field-state=invalid] .ng-select-container{border-width:2px;border-color:#ef4444}:host ::ng-deep ng-select.fd-select .ng-value-container{align-items:center;min-height:100%;padding:2px 12px;gap:4px}:host ::ng-deep ng-select.fd-select .ng-placeholder,:host ::ng-deep ng-select.fd-select .ng-value-label,:host ::ng-deep ng-select.fd-select .ng-input>input{font-family:inherit;font-size:14px;line-height:20px}:host ::ng-deep ng-select.fd-select .ng-placeholder{color:#1c243166}:host ::ng-deep ng-select.fd-select .ng-select-container.ng-has-value .ng-placeholder{display:none}:host ::ng-deep ng-select.fd-select .ng-arrow-wrapper{padding-right:12px}:host ::ng-deep ng-select.fd-select .ng-arrow{border-color:rgba(28,36,49,.6) transparent transparent}:host ::ng-deep ng-select.fd-select .ng-clear-wrapper{color:#1c243199}:host ::ng-deep .ng-dropdown-panel{border:1px solid #E6EAF0;border-radius:8px;background:#fff;box-shadow:0 10px 30px #0000001f}:host ::ng-deep .ng-dropdown-panel .ng-option{padding:10px 14px;font-size:14px;line-height:20px;background:#fff;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-marked{background:#7fb2ff14;color:#1c2431}:host ::ng-deep .ng-dropdown-panel .ng-option.ng-option-selected{background:#7fb2ff24;color:#1c2431}\n"] }]
27494
27695
  }], propDecorators: { config: [{
27495
27696
  type: Input
27496
27697
  }], engine: [{
@@ -27536,7 +27737,8 @@ class SearchWidgetComponent {
27536
27737
  }
27537
27738
  getSearchControlClass() {
27538
27739
  return getTextControlClass({
27539
- invalid: !!this.error
27740
+ invalid: !!this.error,
27741
+ framed: this.hasWrapperFrame()
27540
27742
  });
27541
27743
  }
27542
27744
  getAccessibleLabel() {
@@ -27714,11 +27916,17 @@ class SearchWidgetComponent {
27714
27916
  this.cdr.markForCheck();
27715
27917
  }
27716
27918
  getWrapperStyles() {
27717
- if (!this.config?.style)
27718
- return {};
27919
+ const { wrapperStyles } = splitControlSurfaceStyles(this.config.style);
27719
27920
  return mergeAndNormalize({
27720
- width: '100%'
27721
- }, this.config.style);
27921
+ width: '100%',
27922
+ height: '100%'
27923
+ }, wrapperStyles);
27924
+ }
27925
+ getControlStyles() {
27926
+ return splitControlSurfaceStyles(this.config.style).controlStyles;
27927
+ }
27928
+ hasWrapperFrame() {
27929
+ return hasWrapperSurfaceStyles(this.config.style);
27722
27930
  }
27723
27931
  syncEnabledState() {
27724
27932
  const shouldEnable = this.enabled;
@@ -27837,7 +28045,7 @@ class SearchWidgetComponent {
27837
28045
  [ngStyle]="getWrapperStyles()"
27838
28046
  data-fd="field"
27839
28047
  [attr.data-fd-field-type]="config.type">
27840
- <div class="relative">
28048
+ <div class="relative flex-1 min-h-0">
27841
28049
  <input
27842
28050
  [id]="fieldId"
27843
28051
  type="search"
@@ -27854,6 +28062,7 @@ class SearchWidgetComponent {
27854
28062
  role="combobox"
27855
28063
  autocomplete="off"
27856
28064
  [class]="getSearchControlClass()"
28065
+ [ngStyle]="getControlStyles()"
27857
28066
  data-fd="field-control"
27858
28067
  (focus)="onFocus()"
27859
28068
  (click)="onClick()"
@@ -27902,7 +28111,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
27902
28111
  [ngStyle]="getWrapperStyles()"
27903
28112
  data-fd="field"
27904
28113
  [attr.data-fd-field-type]="config.type">
27905
- <div class="relative">
28114
+ <div class="relative flex-1 min-h-0">
27906
28115
  <input
27907
28116
  [id]="fieldId"
27908
28117
  type="search"
@@ -27919,6 +28128,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
27919
28128
  role="combobox"
27920
28129
  autocomplete="off"
27921
28130
  [class]="getSearchControlClass()"
28131
+ [ngStyle]="getControlStyles()"
27922
28132
  data-fd="field-control"
27923
28133
  (focus)="onFocus()"
27924
28134
  (click)="onClick()"
@@ -28644,9 +28854,7 @@ class RadioWidgetComponent {
28644
28854
  }
28645
28855
  }
28646
28856
  getWrapperStyles() {
28647
- if (!this.config?.style)
28648
- return {};
28649
- return mergeAndNormalize({ width: '100%' }, this.config.style);
28857
+ return mergeAndNormalize({ width: '100%', height: '100%' }, this.config.style);
28650
28858
  }
28651
28859
  get visible() {
28652
28860
  return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
@@ -28696,8 +28904,8 @@ class RadioWidgetComponent {
28696
28904
  [ngStyle]="getWrapperStyles()"
28697
28905
  data-fd="field"
28698
28906
  [attr.data-fd-field-type]="config.type">
28699
- <div class="space-y-2" role="radiogroup" [attr.aria-label]="getAccessibleLabel()" [attr.aria-describedby]="getAriaDescribedBy()">
28700
- <div *ngFor="let opt of options; let i = index" [class]="choiceSurfaceClass" data-fd="field-choice">
28907
+ <div class="flex min-h-0 flex-1 flex-col gap-2" role="radiogroup" [attr.aria-label]="getAccessibleLabel()" [attr.aria-describedby]="getAriaDescribedBy()">
28908
+ <div *ngFor="let opt of options; let i = index" [class]="choiceSurfaceClass + ' flex-1 min-h-0'" data-fd="field-choice">
28701
28909
  <input
28702
28910
  [id]="getFieldId(i)"
28703
28911
  type="radio"
@@ -28736,8 +28944,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
28736
28944
  [ngStyle]="getWrapperStyles()"
28737
28945
  data-fd="field"
28738
28946
  [attr.data-fd-field-type]="config.type">
28739
- <div class="space-y-2" role="radiogroup" [attr.aria-label]="getAccessibleLabel()" [attr.aria-describedby]="getAriaDescribedBy()">
28740
- <div *ngFor="let opt of options; let i = index" [class]="choiceSurfaceClass" data-fd="field-choice">
28947
+ <div class="flex min-h-0 flex-1 flex-col gap-2" role="radiogroup" [attr.aria-label]="getAccessibleLabel()" [attr.aria-describedby]="getAriaDescribedBy()">
28948
+ <div *ngFor="let opt of options; let i = index" [class]="choiceSurfaceClass + ' flex-1 min-h-0'" data-fd="field-choice">
28741
28949
  <input
28742
28950
  [id]="getFieldId(i)"
28743
28951
  type="radio"
@@ -28781,6 +28989,10 @@ class CheckboxGroupWidgetComponent {
28781
28989
  requestId = 0;
28782
28990
  destroyRef = inject(DestroyRef);
28783
28991
  cdr = inject(ChangeDetectorRef);
28992
+ fieldContainerClass = FIELD_CONTAINER_CLASS;
28993
+ fieldHelpClass = FIELD_HELP_CLASS;
28994
+ fieldErrorClass = FIELD_ERROR_CLASS;
28995
+ choiceLabelClass = FIELD_CHOICE_LABEL_CLASS;
28784
28996
  options = [];
28785
28997
  dataProvider = inject(DATA_PROVIDER, { optional: true }) || inject(DefaultDataProvider);
28786
28998
  get fieldId() {
@@ -28795,6 +29007,9 @@ class CheckboxGroupWidgetComponent {
28795
29007
  get helpTextId() {
28796
29008
  return `help-${this.config.id}`;
28797
29009
  }
29010
+ getCheckboxClass() {
29011
+ return getChoiceControlClass({ invalid: !!this.error || !!this.loadError });
29012
+ }
28798
29013
  getAriaDescribedBy() {
28799
29014
  const ids = [];
28800
29015
  if (this.error || this.loadError) {
@@ -28914,9 +29129,7 @@ class CheckboxGroupWidgetComponent {
28914
29129
  this.control.markAsTouched();
28915
29130
  }
28916
29131
  getWrapperStyles() {
28917
- if (!this.config?.style)
28918
- return {};
28919
- return mergeAndNormalize({ width: '100%' }, this.config.style);
29132
+ return mergeAndNormalize({ width: '100%', height: '100%' }, this.config.style);
28920
29133
  }
28921
29134
  get visible() {
28922
29135
  return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
@@ -28955,9 +29168,13 @@ class CheckboxGroupWidgetComponent {
28955
29168
  }
28956
29169
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: CheckboxGroupWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
28957
29170
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: CheckboxGroupWidgetComponent, isStandalone: true, selector: "app-checkbox-group-widget", inputs: { config: "config", engine: "engine", control: "control" }, usesOnChanges: true, ngImport: i0, template: `
28958
- <div class="w-full font-sans" [class.hidden]="!visible" [ngStyle]="getWrapperStyles()">
28959
- <div class="space-y-2" role="group" [attr.aria-label]="getAccessibleLabel()" [attr.aria-describedby]="getAriaDescribedBy()">
28960
- <div *ngFor="let opt of options; let i = index" class="flex items-center">
29171
+ <div [class]="fieldContainerClass"
29172
+ [class.hidden]="!visible"
29173
+ [ngStyle]="getWrapperStyles()"
29174
+ data-fd="field"
29175
+ [attr.data-fd-field-type]="config.type">
29176
+ <div class="flex min-h-0 flex-1 flex-col gap-2" role="group" [attr.aria-label]="getAccessibleLabel()" [attr.aria-describedby]="getAriaDescribedBy()">
29177
+ <div *ngFor="let opt of options; let i = index" class="flex min-h-0 flex-1 items-center gap-2" data-fd="field-choice">
28961
29178
  <input
28962
29179
  [id]="getFieldId(i)"
28963
29180
  type="checkbox"
@@ -28969,17 +29186,18 @@ class CheckboxGroupWidgetComponent {
28969
29186
  [disabled]="!enabled"
28970
29187
  [attr.aria-required]="required"
28971
29188
  [attr.aria-invalid]="!!error"
28972
- class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
28973
- <label [for]="getFieldId(i)" class="ml-2 block text-sm text-gray-700 cursor-pointer select-none">
29189
+ [class]="getCheckboxClass()"
29190
+ data-fd="field-control">
29191
+ <label [for]="getFieldId(i)" [class]="choiceLabelClass + ' cursor-pointer select-none'">
28974
29192
  {{ opt.label }}
28975
29193
  </label>
28976
29194
  </div>
28977
29195
  <div *ngIf="options.length === 0" class="text-xs text-gray-400 italic">No options available</div>
28978
29196
  </div>
28979
29197
 
28980
- <p *ngIf="error" [id]="errorId" class="mt-1 text-sm text-red-600" role="alert" aria-live="assertive">{{ error }}</p>
28981
- <p *ngIf="loadError && !error" [id]="errorId" class="mt-1 text-xs text-red-500" role="alert" aria-live="assertive">{{ loadError }}</p>
28982
- <p *ngIf="config.helpText && !error && !loadError" [id]="helpTextId" class="mt-1 text-xs text-gray-500">{{ config.helpText }}</p>
29198
+ <p *ngIf="error" [id]="errorId" [class]="fieldErrorClass" data-fd="field-error" role="alert" aria-live="assertive">{{ error }}</p>
29199
+ <p *ngIf="loadError && !error" [id]="errorId" [class]="fieldErrorClass" data-fd="field-error" role="alert" aria-live="assertive">{{ loadError }}</p>
29200
+ <p *ngIf="config.helpText && !error && !loadError" [id]="helpTextId" [class]="fieldHelpClass" data-fd="field-help">{{ config.helpText }}</p>
28983
29201
  </div>
28984
29202
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }] });
28985
29203
  }
@@ -28990,9 +29208,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
28990
29208
  standalone: true,
28991
29209
  imports: [CommonModule, ReactiveFormsModule],
28992
29210
  template: `
28993
- <div class="w-full font-sans" [class.hidden]="!visible" [ngStyle]="getWrapperStyles()">
28994
- <div class="space-y-2" role="group" [attr.aria-label]="getAccessibleLabel()" [attr.aria-describedby]="getAriaDescribedBy()">
28995
- <div *ngFor="let opt of options; let i = index" class="flex items-center">
29211
+ <div [class]="fieldContainerClass"
29212
+ [class.hidden]="!visible"
29213
+ [ngStyle]="getWrapperStyles()"
29214
+ data-fd="field"
29215
+ [attr.data-fd-field-type]="config.type">
29216
+ <div class="flex min-h-0 flex-1 flex-col gap-2" role="group" [attr.aria-label]="getAccessibleLabel()" [attr.aria-describedby]="getAriaDescribedBy()">
29217
+ <div *ngFor="let opt of options; let i = index" class="flex min-h-0 flex-1 items-center gap-2" data-fd="field-choice">
28996
29218
  <input
28997
29219
  [id]="getFieldId(i)"
28998
29220
  type="checkbox"
@@ -29004,17 +29226,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
29004
29226
  [disabled]="!enabled"
29005
29227
  [attr.aria-required]="required"
29006
29228
  [attr.aria-invalid]="!!error"
29007
- class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
29008
- <label [for]="getFieldId(i)" class="ml-2 block text-sm text-gray-700 cursor-pointer select-none">
29229
+ [class]="getCheckboxClass()"
29230
+ data-fd="field-control">
29231
+ <label [for]="getFieldId(i)" [class]="choiceLabelClass + ' cursor-pointer select-none'">
29009
29232
  {{ opt.label }}
29010
29233
  </label>
29011
29234
  </div>
29012
29235
  <div *ngIf="options.length === 0" class="text-xs text-gray-400 italic">No options available</div>
29013
29236
  </div>
29014
29237
 
29015
- <p *ngIf="error" [id]="errorId" class="mt-1 text-sm text-red-600" role="alert" aria-live="assertive">{{ error }}</p>
29016
- <p *ngIf="loadError && !error" [id]="errorId" class="mt-1 text-xs text-red-500" role="alert" aria-live="assertive">{{ loadError }}</p>
29017
- <p *ngIf="config.helpText && !error && !loadError" [id]="helpTextId" class="mt-1 text-xs text-gray-500">{{ config.helpText }}</p>
29238
+ <p *ngIf="error" [id]="errorId" [class]="fieldErrorClass" data-fd="field-error" role="alert" aria-live="assertive">{{ error }}</p>
29239
+ <p *ngIf="loadError && !error" [id]="errorId" [class]="fieldErrorClass" data-fd="field-error" role="alert" aria-live="assertive">{{ loadError }}</p>
29240
+ <p *ngIf="config.helpText && !error && !loadError" [id]="helpTextId" [class]="fieldHelpClass" data-fd="field-help">{{ config.helpText }}</p>
29018
29241
  </div>
29019
29242
  `
29020
29243
  }]
@@ -29084,9 +29307,7 @@ class CheckboxWidgetComponent {
29084
29307
  // Cleanup handled by takeUntilDestroyed
29085
29308
  }
29086
29309
  getWrapperStyles() {
29087
- if (!this.config?.style)
29088
- return {};
29089
- return mergeAndNormalize({ width: '100%' }, this.config.style);
29310
+ return mergeAndNormalize({ width: '100%', height: '100%' }, this.config.style);
29090
29311
  }
29091
29312
  get visible() {
29092
29313
  return this.engine ? this.engine.isFieldVisible(this.config.id) : true;
@@ -29136,7 +29357,7 @@ class CheckboxWidgetComponent {
29136
29357
  [ngStyle]="getWrapperStyles()"
29137
29358
  data-fd="field"
29138
29359
  [attr.data-fd-field-type]="config.type">
29139
- <div class="flex items-start gap-3" data-fd="field-choice">
29360
+ <div class="flex min-h-0 flex-1 items-center gap-3" data-fd="field-choice">
29140
29361
  <div class="flex items-center">
29141
29362
  <input
29142
29363
  [id]="fieldId"
@@ -29171,7 +29392,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
29171
29392
  [ngStyle]="getWrapperStyles()"
29172
29393
  data-fd="field"
29173
29394
  [attr.data-fd-field-type]="config.type">
29174
- <div class="flex items-start gap-3" data-fd="field-choice">
29395
+ <div class="flex min-h-0 flex-1 items-center gap-3" data-fd="field-choice">
29175
29396
  <div class="flex items-center">
29176
29397
  <input
29177
29398
  [id]="fieldId"
@@ -29299,10 +29520,9 @@ class RepeatableGroupWidgetComponent {
29299
29520
  return row.id;
29300
29521
  }
29301
29522
  getWrapperStyles() {
29302
- if (!this.config?.style)
29303
- return {};
29304
29523
  return mergeAndNormalize({
29305
- width: '100%'
29524
+ width: '100%',
29525
+ height: '100%'
29306
29526
  }, this.config.style);
29307
29527
  }
29308
29528
  get visible() {
@@ -33901,5 +34121,5 @@ function provideHttpDataSourceClient(config) {
33901
34121
  * Generated bundle index. Do not edit.
33902
34122
  */
33903
34123
 
33904
- export { APPEARANCE_FIELDS, CONTENT_TEXT_CLASS, CONTENT_TEXT_MUTED_CLASS, CORE_DESIGNER_PLUGINS, CURRENT_SCHEMA_VERSION, DATA_PROVIDER, DATA_SOURCE_CLIENT, DEFAULT_TEMPLATE_LIBRARY, DEFAULT_WEBSITE_SECTIONS, DEFAULT_WIDGET_PACKS, DESIGNER_PLUGINS, DESIGNER_SECTIONS, DataCatalog, DataPanelComponent, DataProvider, DefaultDataProvider, DefaultDataSourceClient, DefaultFileUploadClient, DesignerContext, DesignerStateService, DynamicPropertiesComponent, EFFECTS_FIELDS, EMAIL_SAFE_STYLE_SECTIONS, EMAIL_WIDGETS, EmailRendererComponent, EventsPanelComponent, EventsWorkspaceComponent, FIELD_CHOICE_LABEL_CLASS, FIELD_CHOICE_SURFACE_CLASS, FIELD_CONTAINER_CLASS, FIELD_ERROR_CLASS, FIELD_HELP_CLASS, FIELD_LABEL_CLASS, FIELD_OPTION_CLASS, FIELD_REQUIRED_CLASS, FIELD_RESULTS_PANEL_CLASS, FIELD_WIDGETS, FILE_UPLOAD_CARD_CLASS, FILE_UPLOAD_CLIENT, FILE_UPLOAD_SHELL_CLASS, FULL_WEB_STYLE_SECTIONS, FieldPaletteComponent, FormDesignerShellComponent, FormEngine, FormViewerComponent, GlobalDataManagerComponent, HTTP_DATA_SOURCE_CLIENT_CONFIG, HttpDataSourceClient, InMemoryDataCatalogService, InspectorAdvancedSectionComponent, InspectorBackgroundsSectionComponent, InspectorBordersSectionComponent, InspectorEffectsSectionComponent, InspectorLayoutSectionComponent, InspectorPositionSectionComponent, InspectorSizeSectionComponent, InspectorSpacingSectionComponent, InspectorTypographySectionComponent, JsonFormDesignerComponent, JsonFormRendererComponent, LAYOUT_FIELDS, LayoutCanvasComponent, LayoutNodeComponent, PAGE_WIDGETS, PropertiesPanelComponent, RulesPanelComponent, RuntimeFieldDataAccessRegistryService, SELECT_THEME_HOOKS, SELECT_THEME_TOKENS, SPACING_BOX_MODEL_FIELD, SPACING_MARGIN_FIELDS, SPACING_PADDING_FIELDS, STANDARD_FORM_STYLE_SECTIONS, STYLE_APPEARANCE_SECTION, STYLE_EFFECTS_SECTION, STYLE_LAYOUT_SECTION, STYLE_SECTIONS, STYLE_SPACING_SECTION, STYLE_TRANSFORM_SECTION, STYLE_TYPOGRAPHY_SECTION, TABLE_CELL_CLASS, TABLE_EMPTY_CLASS, TABLE_GRID_CLASS, TABLE_HEAD_CELL_CLASS, TABLE_HEAD_CLASS, TABLE_ICON_BUTTON_CLASS, TABLE_ROOT_CLASS, TABLE_ROW_CLASS, TABLE_TOOLBAR_CLASS, TRANSFORM_FIELDS, TYPOGRAPHY_FIELDS, ThemeService, UiAccordionComponent, UiBoxModelComponent, UiColorSwatchComponent, UiDimensionComponent, UiEdgeBoxComponent, UiFieldWrapperComponent, UiInputComponent, UiRangeNumberComponent, UiSelectIconComponent, UiTabComponent, UiTabsComponent, WIDGET_DEFINITIONS, WIDGET_ID_SEPARATOR, WebsiteBrickStudioComponent, WebsiteDesignerShellComponent, WebsitePreviewShellComponent, WebsiteProjectService, WidgetDefinitionResolverService, WidgetInspectorComponent, appendSectionToSchema, buildWidgetId, checkSchemaForApiOnlySources, createDefaultWebsiteBrick, createDefaultWebsiteBricks, createDefaultWebsiteTheme, createEmptySchema, createFormEngine, createPluginContext, createWebsiteBrick, createWebsitePage, createWebsiteProject, defineWidget, flattenPluginWidgets, getButtonClass, getChoiceControlClass, getEffectiveDataConfig, getFileInputClass, getHeadingClass, getTextControlClass, getWidgetsForFlavor, inferSchema, isWidgetVisibleInPalette, mergeAndNormalize, normalizeRuntimeOptions, normalizeStyle, parseCsv, parseJsonArray, parseSchema, provideDesignerPlugins, provideHttpDataSourceClient, serializeSchema, slugifyId, stripEmbeddedSourceData };
34124
+ export { APPEARANCE_FIELDS, CONTENT_TEXT_CLASS, CONTENT_TEXT_MUTED_CLASS, CORE_DESIGNER_PLUGINS, CURRENT_SCHEMA_VERSION, DATA_PROVIDER, DATA_SOURCE_CLIENT, DEFAULT_TEMPLATE_LIBRARY, DEFAULT_WEBSITE_SECTIONS, DEFAULT_WIDGET_PACKS, DESIGNER_PLUGINS, DESIGNER_SECTIONS, DataCatalog, DataPanelComponent, DataProvider, DefaultDataProvider, DefaultDataSourceClient, DefaultFileUploadClient, DesignerContext, DesignerStateService, DynamicPropertiesComponent, EFFECTS_FIELDS, EMAIL_SAFE_STYLE_SECTIONS, EMAIL_WIDGETS, EmailRendererComponent, EventsPanelComponent, EventsWorkspaceComponent, FIELD_CHOICE_LABEL_CLASS, FIELD_CHOICE_SURFACE_CLASS, FIELD_CONTAINER_CLASS, FIELD_ERROR_CLASS, FIELD_HELP_CLASS, FIELD_LABEL_CLASS, FIELD_OPTION_CLASS, FIELD_REQUIRED_CLASS, FIELD_RESULTS_PANEL_CLASS, FIELD_WIDGETS, FILE_UPLOAD_CARD_CLASS, FILE_UPLOAD_CLIENT, FILE_UPLOAD_SHELL_CLASS, FULL_WEB_STYLE_SECTIONS, FieldPaletteComponent, FormDesignerShellComponent, FormEngine, FormViewerComponent, GlobalDataManagerComponent, HTTP_DATA_SOURCE_CLIENT_CONFIG, HttpDataSourceClient, InMemoryDataCatalogService, InspectorAdvancedSectionComponent, InspectorBackgroundsSectionComponent, InspectorBordersSectionComponent, InspectorEffectsSectionComponent, InspectorLayoutSectionComponent, InspectorPositionSectionComponent, InspectorSizeSectionComponent, InspectorSpacingSectionComponent, InspectorTypographySectionComponent, JsonFormDesignerComponent, JsonFormRendererComponent, LAYOUT_FIELDS, LayoutCanvasComponent, LayoutNodeComponent, PAGE_WIDGETS, PropertiesPanelComponent, RulesPanelComponent, RuntimeFieldDataAccessRegistryService, SELECT_THEME_HOOKS, SELECT_THEME_TOKENS, SPACING_BOX_MODEL_FIELD, SPACING_MARGIN_FIELDS, SPACING_PADDING_FIELDS, STANDARD_FORM_STYLE_SECTIONS, STYLE_APPEARANCE_SECTION, STYLE_EFFECTS_SECTION, STYLE_LAYOUT_SECTION, STYLE_SECTIONS, STYLE_SPACING_SECTION, STYLE_TRANSFORM_SECTION, STYLE_TYPOGRAPHY_SECTION, TABLE_CELL_CLASS, TABLE_EMPTY_CLASS, TABLE_GRID_CLASS, TABLE_HEAD_CELL_CLASS, TABLE_HEAD_CLASS, TABLE_ICON_BUTTON_CLASS, TABLE_ROOT_CLASS, TABLE_ROW_CLASS, TABLE_TOOLBAR_CLASS, TRANSFORM_FIELDS, TYPOGRAPHY_FIELDS, ThemeService, UiAccordionComponent, UiBoxModelComponent, UiColorSwatchComponent, UiDimensionComponent, UiEdgeBoxComponent, UiFieldWrapperComponent, UiInputComponent, UiRangeNumberComponent, UiSelectIconComponent, UiTabComponent, UiTabsComponent, WIDGET_DEFINITIONS, WIDGET_ID_SEPARATOR, WebsiteBrickStudioComponent, WebsiteDesignerShellComponent, WebsitePreviewShellComponent, WebsiteProjectService, WidgetDefinitionResolverService, WidgetInspectorComponent, appendSectionToSchema, buildWidgetId, checkSchemaForApiOnlySources, createDefaultWebsiteBrick, createDefaultWebsiteBricks, createDefaultWebsiteTheme, createEmptySchema, createFormEngine, createPluginContext, createWebsiteBrick, createWebsitePage, createWebsiteProject, defineWidget, flattenPluginWidgets, getButtonClass, getChoiceControlClass, getEffectiveDataConfig, getFileInputClass, getHeadingClass, getTextControlClass, getWidgetsForFlavor, hasWrapperSurfaceStyles, inferSchema, isWidgetVisibleInPalette, mergeAndNormalize, normalizeRuntimeOptions, normalizeStyle, parseCsv, parseJsonArray, parseSchema, provideDesignerPlugins, provideHttpDataSourceClient, serializeSchema, slugifyId, splitControlSurfaceStyles, stripEmbeddedSourceData };
33905
34125
  //# sourceMappingURL=ngx-form-designer.mjs.map