wuic-framework-lib 1.5.0 → 1.7.1

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.
Files changed (27) hide show
  1. package/fesm2022/{wuic-framework-lib-chart-list.component-0J1ghIrS.mjs → wuic-framework-lib-chart-list.component-Dq9IEKsY.mjs} +50 -38
  2. package/fesm2022/{wuic-framework-lib-code-editor.component-C21mvjyr.mjs → wuic-framework-lib-code-editor.component-B6IpTSo8.mjs} +174 -274
  3. package/fesm2022/{wuic-framework-lib-designer.component-x10ZzUEy.mjs → wuic-framework-lib-designer.component-D6cbqNFg.mjs} +499 -581
  4. package/fesm2022/wuic-framework-lib-first-run-wizard.component-D1ZQUl-q.mjs +1630 -0
  5. package/fesm2022/{wuic-framework-lib-framework-docs.component-xTGLbEnp.mjs → wuic-framework-lib-framework-docs.component-C_o5r7pg.mjs} +4320 -1255
  6. package/fesm2022/{wuic-framework-lib-pivot-builder.component-BkFFjPm4.mjs → wuic-framework-lib-pivot-builder.component-DkWGzJpr.mjs} +580 -68
  7. package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-Bi-TrJB6.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-D29go5yA.mjs} +2 -2
  8. package/fesm2022/wuic-framework-lib-report-designer.component-DcpCWghx.mjs +380 -0
  9. package/fesm2022/wuic-framework-lib-report-scaffold-dialog.component-CgUjG7Bi.mjs +431 -0
  10. package/fesm2022/{wuic-framework-lib-report-viewer.component-BR-BfI2r.mjs → wuic-framework-lib-report-viewer.component-C4Opgl_M.mjs} +8 -13
  11. package/fesm2022/{wuic-framework-lib-scene3d-designer.component-BQzFxSXP.mjs → wuic-framework-lib-scene3d-designer.component-8l3vsyEb.mjs} +323 -88
  12. package/fesm2022/{wuic-framework-lib-scene3d-light-baker-gpu-0LjqhSNn.mjs → wuic-framework-lib-scene3d-light-baker-gpu-C1w-8Aai.mjs} +2 -2
  13. package/fesm2022/{wuic-framework-lib-scene3d-shader-effect-CQLWkuh1.mjs → wuic-framework-lib-scene3d-shader-effect-DjHyCAFK.mjs} +612 -32
  14. package/fesm2022/{wuic-framework-lib-scene3d-viewer.component-imoV3HOs.mjs → wuic-framework-lib-scene3d-viewer.component-nMSl5jbe.mjs} +149 -18
  15. package/fesm2022/{wuic-framework-lib-scheduler-list.component-xzlTEkoq.mjs → wuic-framework-lib-scheduler-list.component-Cvk3Zg0Q.mjs} +169 -53
  16. package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-CrS6fOGj.mjs → wuic-framework-lib-spreadsheet-list-sf.component-C1U7JPiq.mjs} +149 -108
  17. package/fesm2022/{wuic-framework-lib-stimulsoft-license.service-BIyxB4pO.mjs → wuic-framework-lib-stimulsoft-license.service-CsNNSFYs.mjs} +3 -3
  18. package/fesm2022/wuic-framework-lib-timeline-list.component-cZbPgNh1.mjs +805 -0
  19. package/fesm2022/{wuic-framework-lib-workflow-designer.component-5xtQ7-6z.mjs → wuic-framework-lib-workflow-designer.component-C_4RQGa0.mjs} +180 -150
  20. package/fesm2022/{wuic-framework-lib-wuic-framework-lib-3TZ-j-yL.mjs → wuic-framework-lib-wuic-framework-lib-BZZwta8b.mjs} +6785 -2347
  21. package/fesm2022/wuic-framework-lib.mjs +1 -1
  22. package/package.json +21 -2
  23. package/styles/_wuic-tokens.scss +82 -0
  24. package/styles/styles.scss +160 -0
  25. package/types/wuic-framework-lib.d.ts +4269 -2691
  26. package/fesm2022/wuic-framework-lib-first-run-wizard.component-BuSxs_CM.mjs +0 -1316
  27. package/fesm2022/wuic-framework-lib-report-designer.component-ZvB46-LV.mjs +0 -194
@@ -5,24 +5,24 @@ import { SplitterModule } from 'primeng/splitter';
5
5
  import * as i12 from 'primeng/dragdrop';
6
6
  import { DragDropModule } from 'primeng/dragdrop';
7
7
  import { NgClass, NgStyle, NgTemplateOutlet, AsyncPipe, JsonPipe, NgFor, NgIf, NgComponentOutlet } from '@angular/common';
8
- import { W as WtoolboxService, D as DynamicGenericTemplateComponent, a as DynamicCompilerService, b as DataSourceComponent, c as DataRepeaterComponent, F as FilterBarComponent, L as LazyParametricDialogComponent, P as PagerComponent, M as MetadataProviderService, d as ParametricDialogComponent, e as MetadatiColonna, f as DataProviderService, U as UserInfoService, T as TranslationManagerService, g as MetadataEditorService, C as ChatbotHostRegistryService, h as WorkflowRuntimeMetadataService, i as FieldEditorComponent, j as MetadataEditorComponent, A as ArchetypeConfiguratorComponent } from './wuic-framework-lib-wuic-framework-lib-3TZ-j-yL.mjs';
8
+ import { W as WtoolboxService, D as DynamicGenericTemplateComponent, a as DynamicCompilerService, b as DataSourceComponent, c as DataRepeaterComponent, F as FilterBarComponent, L as LazyParametricDialogComponent, P as PagerComponent, M as MetadataProviderService, t as toHsbaModel, d as clampAlpha, e as toPersistedColor, f as ParametricDialogComponent, g as MetadatiColonna, h as DataProviderService, U as UserInfoService, T as TranslationManagerService, i as MetadataEditorService, C as ChatbotHostRegistryService, j as WorkflowRuntimeMetadataService, k as FieldEditorComponent, l as MetadataEditorComponent, A as ArchetypeConfiguratorComponent } from './wuic-framework-lib-wuic-framework-lib-BZZwta8b.mjs';
9
9
  import { fromEvent, BehaviorSubject, merge, filter, Observable, switchMap, take, map, takeUntil, tap, timeInterval, scan, mergeMap, of, delay, repeat, Subject, startWith, pairwise, skipWhile, combineLatest } from 'rxjs';
10
10
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
11
11
  import { CdkAccordionModule, CdkAccordion, CdkAccordionItem } from '@angular/cdk/accordion';
12
- import * as i6 from 'primeng/select';
12
+ import * as i5 from 'primeng/select';
13
13
  import { SelectModule } from 'primeng/select';
14
14
  import * as i1 from '@angular/forms';
15
15
  import { FormsModule } from '@angular/forms';
16
- import * as i2$1 from 'primeng/colorpicker';
16
+ import * as i6 from 'primeng/colorpicker';
17
17
  import { ColorPickerModule } from 'primeng/colorpicker';
18
- import * as i2$2 from 'primeng/autocomplete';
18
+ import * as i2$1 from 'primeng/autocomplete';
19
19
  import { AutoCompleteModule } from 'primeng/autocomplete';
20
- import * as i2$3 from '@ngx-translate/core';
20
+ import * as i8 from '@ngx-translate/core';
21
21
  import { TranslateModule } from '@ngx-translate/core';
22
22
  import * as i1$1 from '@angular/router';
23
23
  import { UrlSegmentGroup, UrlTree, ActivatedRouteSnapshot, RouterStateSnapshot, RouterState, ActivatedRoute } from '@angular/router';
24
24
  import { SafeSubscriber } from 'rxjs/internal/Subscriber';
25
- import * as i10$1 from 'primeng/contextmenu';
25
+ import * as i14 from 'primeng/contextmenu';
26
26
  import { ContextMenuModule } from 'primeng/contextmenu';
27
27
  import * as i3 from 'primeng/api';
28
28
  import { TreeDragDropService } from 'primeng/api';
@@ -43,7 +43,7 @@ class PropConverterPipe {
43
43
  if (value) {
44
44
  if (args.length > 0) {
45
45
  if (args[0] === 'toArray') {
46
- return Array(parseInt(value.toString())).fill(1).map((x, i) => i);
46
+ return new Array(Number.parseInt(value.toString())).fill(1).map((x, i) => i);
47
47
  }
48
48
  if (args[0] === 'fromArray') {
49
49
  return value.length;
@@ -68,8 +68,8 @@ class NgxDraggablePoint {
68
68
  x;
69
69
  y;
70
70
  constructor(x, y) {
71
- this.x = (!!x) ? x : 0;
72
- this.y = (!!y) ? y : 0;
71
+ this.x = x || 0;
72
+ this.y = y || 0;
73
73
  }
74
74
  }
75
75
 
@@ -136,10 +136,10 @@ class NgxDraggableRect {
136
136
  };
137
137
  }
138
138
  constructor(x, y, width, height) {
139
- this.x = (!!x) ? x : 0;
140
- this.y = (!!y) ? y : 0;
141
- this.width = (!!width) ? width : 0;
142
- this.height = (!!height) ? height : 0;
139
+ this.x = x || 0;
140
+ this.y = y || 0;
141
+ this.width = width || 0;
142
+ this.height = height || 0;
143
143
  }
144
144
  }
145
145
 
@@ -175,15 +175,15 @@ class NgxDraggableDomBoundsCheckEvent {
175
175
  * @param isConstrained Whether the element should be constrained or not.
176
176
  */
177
177
  constructor(top, right, bottom, left, elP0, translation, isConstrained) {
178
- this.top = (!!top) ? top : false;
179
- this.right = (!!right) ? right : false;
180
- this.bottom = (!!bottom) ? bottom : false;
181
- this.left = (!!left) ? left : false;
182
- if (!!elP0) {
178
+ this.top = top ?? false;
179
+ this.right = right ?? false;
180
+ this.bottom = bottom ?? false;
181
+ this.left = left ?? false;
182
+ if (elP0) {
183
183
  this.constrainedCenter = elP0;
184
184
  }
185
- this.translation = (!!translation) ? translation : new NgxDraggablePoint(0, 0);
186
- this.isConstrained = (!!isConstrained) ? isConstrained : false;
185
+ this.translation = translation ?? new NgxDraggablePoint(0, 0);
186
+ this.isConstrained = isConstrained ?? false;
187
187
  }
188
188
  }
189
189
 
@@ -217,8 +217,8 @@ class NgxDraggableDomMoveEvent {
217
217
  * @param position The position of the target HTMLElement.
218
218
  */
219
219
  constructor(target, position) {
220
- this._target = (!!target) ? target : undefined;
221
- this._position = (!!position) ? position : undefined;
220
+ this._target = target || undefined;
221
+ this._position = position || undefined;
222
222
  }
223
223
  }
224
224
 
@@ -386,11 +386,11 @@ class NgxDraggableDomUtilities {
386
386
  static getTransformMatrixForElement(el) {
387
387
  // create the numerical matrix we will use
388
388
  const matrix = [1, 0, 0, 1, 0, 0];
389
- if (window) {
389
+ if (globalThis) {
390
390
  // get the computed transform style
391
- let transform = window.getComputedStyle(el, null).getPropertyValue('transform');
391
+ let transform = globalThis.getComputedStyle(el, null).getPropertyValue('transform');
392
392
  // strip non matrix values from the string
393
- transform = transform.replace(/matrix/g, '').replace(/\(/g, '').replace(/\)/g, '').replace(/ /g, '');
393
+ transform = transform.replaceAll('matrix', '').replaceAll('(', '').replaceAll(')', '').replaceAll(' ', '');
394
394
  // if we have a transform set, convert the string matrix to a numerical one
395
395
  if (transform !== 'none') {
396
396
  // split the string based on commas
@@ -427,7 +427,7 @@ class NgxDraggableDomUtilities {
427
427
  */
428
428
  static getTotalRotationForElement(node, rotation = 0) {
429
429
  // if we can't calculate the computed style or we have no node to analyze, return the current calculated rotation
430
- if (!node || !window) {
430
+ if (!node || !globalThis) {
431
431
  return rotation;
432
432
  }
433
433
  // if we have reached the body, stop processing beyond here
@@ -527,7 +527,7 @@ class NgxDraggableDomDirective {
527
527
  return null;
528
528
  }
529
529
  // get the bounding box of the element
530
- const boundsBounds = this.bounds.getBoundingClientRect();
530
+ const boundsBounds = (this.bounds).getBoundingClientRect();
531
531
  return new NgxDraggablePoint(this.scrollLeft + boundsBounds.left + (boundsBounds.width / 2), this.scrollTop + boundsBounds.top + (boundsBounds.height / 2));
532
532
  }
533
533
  /**
@@ -536,7 +536,7 @@ class NgxDraggableDomDirective {
536
536
  * @return The current scroll position of the document in the x direction.
537
537
  */
538
538
  get scrollLeft() {
539
- if (!!window) {
539
+ if (globalThis) {
540
540
  return window.pageXOffset;
541
541
  }
542
542
  else if (!!document && !!document.documentElement) {
@@ -552,7 +552,7 @@ class NgxDraggableDomDirective {
552
552
  * @return The current scroll position of the document in the y direction.
553
553
  */
554
554
  get scrollTop() {
555
- if (!!window) {
555
+ if (globalThis) {
556
556
  return window.pageYOffset;
557
557
  }
558
558
  else if (!!document && !!document.documentElement) {
@@ -654,7 +654,7 @@ class NgxDraggableDomDirective {
654
654
  */
655
655
  onTouchStart(event) {
656
656
  // block multiTouch events if we are configured to do so
657
- if (this.ignoreMultiTouchEvents && event && event.touches && event.touches.length > 1) {
657
+ if (this.ignoreMultiTouchEvents && event?.touches && event.touches.length > 1) {
658
658
  return;
659
659
  }
660
660
  // stop all default behavior and propagation of the event so it is fully consumed by us
@@ -749,13 +749,8 @@ class NgxDraggableDomDirective {
749
749
  * @param event The touch event to handle as a TouchEvent (or any solely for working around issues with Safari).
750
750
  */
751
751
  onTouchEnd(event) {
752
- // stop all default behavior and propagation of the event so it is fully consumed by us
753
- event.stopImmediatePropagation();
754
- // prevent the default mouse behavior on images so that browser image dragging is disabled
755
- if (event.target instanceof HTMLImageElement) {
756
- event.preventDefault();
757
- }
758
- this.putBack();
752
+ // same consume-and-put-back behavior as the mouse release handler
753
+ this.onMouseUp(event);
759
754
  }
760
755
  /**
761
756
  * Event handler for when the element is moved via a touch event.
@@ -764,7 +759,7 @@ class NgxDraggableDomDirective {
764
759
  */
765
760
  onTouchMove(event) {
766
761
  // block multiTouch events if we are configured to do so
767
- if (this.ignoreMultiTouchEvents && event && event.touches && event.touches.length > 1) {
762
+ if (this.ignoreMultiTouchEvents && event?.touches && event.touches.length > 1) {
768
763
  // ensure any element that is being dragged is put back
769
764
  this.putBack(false);
770
765
  return;
@@ -852,7 +847,7 @@ class NgxDraggableDomDirective {
852
847
  // check the bounds based on the element position
853
848
  boundsCheck = this.boundsCheck(new NgxDraggablePoint(dragPosition.x, dragPosition.y));
854
849
  // hold the element in position if we are requested to be constrained
855
- if (boundsCheck && boundsCheck.isConstrained) {
850
+ if (boundsCheck?.isConstrained) {
856
851
  // update the translation using the constrained center point and bounds center
857
852
  translation = boundsCheck.translation;
858
853
  }
@@ -868,7 +863,7 @@ class NgxDraggableDomDirective {
868
863
  translation.y = Math.round((_dragEl.offsetTop + translation.y) / _snapGrid) * _snapGrid - _dragEl.offsetTop;
869
864
  }
870
865
  // if it is possible, get the transform from the computed style and modify the matrix to maintain transform properties
871
- if (window) {
866
+ if (globalThis) {
872
867
  // update the x and y values as part of the matrix
873
868
  matrix[4] = translation.x;
874
869
  matrix[5] = translation.y;
@@ -915,9 +910,9 @@ class NgxDraggableDomDirective {
915
910
  this.oldZIndex = this.el.nativeElement.style.zIndex ? this.el.nativeElement.style.zIndex : '';
916
911
  this.oldPosition = this.el.nativeElement.style.position ? this.el.nativeElement.style.position : '';
917
912
  // fetch the old z-index and position from computing the style applied to the element
918
- if (window) {
919
- this.oldZIndex = window.getComputedStyle(this.el.nativeElement, null).getPropertyValue('z-index');
920
- this.oldPosition = window.getComputedStyle(this.el.nativeElement, null).getPropertyValue('position');
913
+ if (globalThis) {
914
+ this.oldZIndex = globalThis.getComputedStyle(this.el.nativeElement, null).getPropertyValue('z-index');
915
+ this.oldPosition = globalThis.getComputedStyle(this.el.nativeElement, null).getPropertyValue('position');
921
916
  }
922
917
  // check if old position is draggable
923
918
  if (this.oldPosition && (this.oldPosition === 'absolute' ||
@@ -954,7 +949,7 @@ class NgxDraggableDomDirective {
954
949
  // compute the current rotation of all parent nodes
955
950
  this.computedRotation = NgxDraggableDomUtilities.getTotalRotationForElement(this.el.nativeElement.parentElement);
956
951
  // normalize the start position for the rotation
957
- this.startPosition = NgxDraggableMath.rotatePoint(this.startPosition, (!!boundsCenter) ? boundsCenter : new NgxDraggablePoint(0, 0), -this.computedRotation);
952
+ this.startPosition = NgxDraggableMath.rotatePoint(this.startPosition, boundsCenter ?? new NgxDraggablePoint(0, 0), -this.computedRotation);
958
953
  // get the current transformation matrix and extract the current translation
959
954
  matrix = NgxDraggableDomUtilities.getTransformMatrixForElement(this.el.nativeElement);
960
955
  translation.x = matrix[4];
@@ -963,7 +958,7 @@ class NgxDraggableDomDirective {
963
958
  this.startPosition.x -= translation.x;
964
959
  this.startPosition.y -= translation.y;
965
960
  // reapply the rotation to the start position
966
- this.startPosition = NgxDraggableMath.rotatePoint(this.startPosition, (!!boundsCenter) ? boundsCenter : new NgxDraggablePoint(0, 0), this.computedRotation);
961
+ this.startPosition = NgxDraggableMath.rotatePoint(this.startPosition, boundsCenter ?? new NgxDraggablePoint(0, 0), this.computedRotation);
967
962
  // determine the clientX and clientY position based on the event type
968
963
  const clientX = (event instanceof MouseEvent) ? event.clientX : event.changedTouches[0]?.clientX;
969
964
  const clientY = (event instanceof MouseEvent) ? event.clientY : event.changedTouches[0]?.clientY;
@@ -1021,7 +1016,7 @@ class NgxDraggableDomDirective {
1021
1016
  if (this.bounds) {
1022
1017
  // get the current center point of the element
1023
1018
  const elCenter = this.elCenter;
1024
- if (!!elCenter) {
1019
+ if (elCenter) {
1025
1020
  // check the bounds based on the element position
1026
1021
  const boundsCheck = this.boundsCheck(elCenter);
1027
1022
  // emit the edge event so consumers know the current state of the position
@@ -1143,7 +1138,7 @@ class NgxDraggableDomDirective {
1143
1138
  if (isBLOutside && elBL.x >= (checkBounds.left + checkBounds.width) &&
1144
1139
  NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0) > greatestConstrainDistance) {
1145
1140
  constrainPoint = new NgxDraggablePoint(elBL.x, elBL.y);
1146
- greatestConstrainDistance = NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0);
1141
+ NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0);
1147
1142
  }
1148
1143
  // calculate the displacement
1149
1144
  displaceX = checkBounds.left + checkBounds.width - (constrainPoint ? constrainPoint.x : 0);
@@ -1168,7 +1163,7 @@ class NgxDraggableDomDirective {
1168
1163
  if (isBLOutside && elBL.x <= checkBounds.left &&
1169
1164
  NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0) > greatestConstrainDistance) {
1170
1165
  constrainPoint = new NgxDraggablePoint(elBL.x, elBL.y);
1171
- greatestConstrainDistance = NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0);
1166
+ NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0);
1172
1167
  }
1173
1168
  // calculate the displacement
1174
1169
  displaceX = checkBounds.left - (constrainPoint ? constrainPoint.x : 0);
@@ -1196,7 +1191,7 @@ class NgxDraggableDomDirective {
1196
1191
  if (isBLOutside && elBL.y >= (checkBounds.top + checkBounds.height) &&
1197
1192
  NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0) > greatestConstrainDistance) {
1198
1193
  constrainPoint = new NgxDraggablePoint(elBL.x, elBL.y);
1199
- greatestConstrainDistance = NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0);
1194
+ NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0);
1200
1195
  }
1201
1196
  // calculate the displacement
1202
1197
  displaceY = checkBounds.top + checkBounds.height - (constrainPoint ? constrainPoint.y : 0);
@@ -1221,7 +1216,7 @@ class NgxDraggableDomDirective {
1221
1216
  if (isBLOutside && elBL.y <= checkBounds.top &&
1222
1217
  NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0) > greatestConstrainDistance) {
1223
1218
  constrainPoint = new NgxDraggablePoint(elBL.x, elBL.y);
1224
- greatestConstrainDistance = NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0);
1219
+ NgxDraggableMath.getDistanceBetweenPoints(elBL, boundsP0);
1225
1220
  }
1226
1221
  // calculate the displacement
1227
1222
  displaceY = checkBounds.top - (constrainPoint ? constrainPoint.y : 0);
@@ -1345,7 +1340,7 @@ class ResizeHandle {
1345
1340
  this._handle.removeEventListener('mousedown', this._onResize);
1346
1341
  this._handle.removeEventListener('touchstart', this._onResize);
1347
1342
  if (this.parent && !this.existHandle) {
1348
- this.parent.removeChild(this._handle);
1343
+ this._handle.remove();
1349
1344
  }
1350
1345
  this._handle = null;
1351
1346
  this._onResize = null;
@@ -1379,9 +1374,9 @@ class Position {
1379
1374
  * Fix issue: Multiple phone draggables at the same time
1380
1375
  * https://github.com/xieziyu/angular2-draggable/issues/128
1381
1376
  */
1382
- for (let i = 0; i < e.changedTouches.length; i++) {
1383
- if (e.changedTouches[i].target === el) {
1384
- return new Position(e.changedTouches[i].clientX, e.changedTouches[i].clientY);
1377
+ for (const touch of e.changedTouches) {
1378
+ if (touch.target === el) {
1379
+ return new Position(touch.clientX, touch.clientY);
1385
1380
  }
1386
1381
  }
1387
1382
  }
@@ -1395,13 +1390,13 @@ class Position {
1395
1390
  }
1396
1391
  static getCurrent(el) {
1397
1392
  let pos = new Position(0, 0);
1398
- if (window) {
1399
- const computed = window.getComputedStyle(el);
1393
+ if (globalThis) {
1394
+ const computed = globalThis.getComputedStyle(el);
1400
1395
  if (computed) {
1401
- let x = parseInt(computed.getPropertyValue('left'), 10);
1402
- let y = parseInt(computed.getPropertyValue('top'), 10);
1403
- pos.x = isNaN(x) ? 0 : x;
1404
- pos.y = isNaN(y) ? 0 : y;
1396
+ let x = Number.parseInt(computed.getPropertyValue('left'), 10);
1397
+ let y = Number.parseInt(computed.getPropertyValue('top'), 10);
1398
+ pos.x = Number.isNaN(Number(x)) ? 0 : x;
1399
+ pos.y = Number.isNaN(Number(y)) ? 0 : y;
1405
1400
  }
1406
1401
  return pos;
1407
1402
  }
@@ -1455,11 +1450,11 @@ class Size {
1455
1450
  }
1456
1451
  static getCurrent(el) {
1457
1452
  let size = new Size(0, 0);
1458
- if (window) {
1459
- const computed = window.getComputedStyle(el);
1453
+ if (globalThis) {
1454
+ const computed = globalThis.getComputedStyle(el);
1460
1455
  if (computed) {
1461
- size.width = parseInt(computed.getPropertyValue('width'), 10);
1462
- size.height = parseInt(computed.getPropertyValue('height'), 10);
1456
+ size.width = Number.parseInt(computed.getPropertyValue('width'), 10);
1457
+ size.height = Number.parseInt(computed.getPropertyValue('height'), 10);
1463
1458
  }
1464
1459
  return size;
1465
1460
  }
@@ -1506,7 +1501,7 @@ class HelperBlock {
1506
1501
  }
1507
1502
  remove() {
1508
1503
  if (this.parent && this._added) {
1509
- this.parent.removeChild(this._helper);
1504
+ this._helper.remove();
1510
1505
  this._added = false;
1511
1506
  }
1512
1507
  }
@@ -1693,7 +1688,7 @@ class AngularResizableDirective {
1693
1688
  }
1694
1689
  else {
1695
1690
  let r = Number(this.rzAspectRatio);
1696
- this._aspectRatio = isNaN(r) ? 0 : r;
1691
+ this._aspectRatio = Number.isNaN(Number(r)) ? 0 : r;
1697
1692
  }
1698
1693
  }
1699
1694
  /** Use it to update containment */
@@ -1725,7 +1720,7 @@ class AngularResizableDirective {
1725
1720
  tmpHandleTypes = ['n', 'e', 's', 'w', 'ne', 'se', 'nw', 'sw'];
1726
1721
  }
1727
1722
  else {
1728
- tmpHandleTypes = this.rzHandles.replace(/ /g, '').toLowerCase().split(',');
1723
+ tmpHandleTypes = this.rzHandles.replaceAll(' ', '').toLowerCase().split(',');
1729
1724
  }
1730
1725
  for (let type of tmpHandleTypes) {
1731
1726
  // default handle theme: ng-resizable-$type.
@@ -1752,7 +1747,7 @@ class AngularResizableDirective {
1752
1747
  createHandleByType(type, css) {
1753
1748
  const _el = this.el.nativeElement;
1754
1749
  const _h = this.rzHandleDoms[type] ? this.rzHandleDoms[type].nativeElement : null;
1755
- if (!type.match(/^(se|sw|ne|nw|n|e|s|w)$/)) {
1750
+ if (!/^(se|sw|ne|nw|n|e|s|w)$/.exec(type)) {
1756
1751
  console.error('Invalid handle type:', type);
1757
1752
  return null;
1758
1753
  }
@@ -1786,7 +1781,7 @@ class AngularResizableDirective {
1786
1781
  this.draggingSub.add(fromEvent(document, 'touchmove', { passive: false }).subscribe(event => this.onMouseMove(event)));
1787
1782
  this.draggingSub.add(fromEvent(document, 'mouseup', { passive: false }).subscribe(() => this.onMouseLeave()));
1788
1783
  // fix for issue #164
1789
- let isIEOrEdge = /msie\s|trident\//i.test(window.navigator.userAgent);
1784
+ let isIEOrEdge = /msie\s|trident\//i.test(globalThis.navigator.userAgent);
1790
1785
  if (!isIEOrEdge) {
1791
1786
  this.draggingSub.add(fromEvent(document, 'mouseleave', { passive: false }).subscribe(() => this.onMouseLeave()));
1792
1787
  }
@@ -1862,10 +1857,10 @@ class AngularResizableDirective {
1862
1857
  }
1863
1858
  updateDirection() {
1864
1859
  this._direction = {
1865
- n: !!this._handleResizing.type.match(/n/),
1866
- s: !!this._handleResizing.type.match(/s/),
1867
- w: !!this._handleResizing.type.match(/w/),
1868
- e: !!this._handleResizing.type.match(/e/),
1860
+ n: /n/.test(this._handleResizing.type),
1861
+ s: /s/.test(this._handleResizing.type),
1862
+ w: /w/.test(this._handleResizing.type),
1863
+ e: /e/.test(this._handleResizing.type),
1869
1864
  };
1870
1865
  this._directionChanged = { ...this._direction };
1871
1866
  // if aspect ration should be preserved:
@@ -2029,24 +2024,24 @@ class AngularResizableDirective {
2029
2024
  }
2030
2025
  getBounding() {
2031
2026
  const el = this._containment;
2032
- const computed = window.getComputedStyle(el);
2027
+ const computed = globalThis.getComputedStyle(el);
2033
2028
  if (computed) {
2034
2029
  let p = computed.getPropertyValue('position');
2035
- const nativeEl = window.getComputedStyle(this.el.nativeElement);
2030
+ const nativeEl = globalThis.getComputedStyle(this.el.nativeElement);
2036
2031
  let transforms = nativeEl
2037
2032
  .getPropertyValue('transform')
2038
- .replace(/[^-\d,]/g, '')
2033
+ .replaceAll(/[^-\d,]/g, '')
2039
2034
  .split(',');
2040
2035
  this._bounding = {};
2041
2036
  this._bounding.width = el.clientWidth;
2042
2037
  this._bounding.height = el.clientHeight;
2043
- this._bounding.pr = parseInt(computed.getPropertyValue('padding-right'), 10);
2044
- this._bounding.pb = parseInt(computed.getPropertyValue('padding-bottom'), 10);
2038
+ this._bounding.pr = Number.parseInt(computed.getPropertyValue('padding-right'), 10);
2039
+ this._bounding.pb = Number.parseInt(computed.getPropertyValue('padding-bottom'), 10);
2045
2040
  this._bounding.deltaL = this.el.nativeElement.offsetLeft - this._currPos.x;
2046
2041
  this._bounding.deltaT = this.el.nativeElement.offsetTop - this._currPos.y;
2047
2042
  if (transforms.length >= 6) {
2048
- this._bounding.translateX = parseInt(transforms[4], 10);
2049
- this._bounding.translateY = parseInt(transforms[5], 10);
2043
+ this._bounding.translateX = Number.parseInt(transforms[4], 10);
2044
+ this._bounding.translateY = Number.parseInt(transforms[5], 10);
2050
2045
  }
2051
2046
  else {
2052
2047
  this._bounding.translateX = 0;
@@ -2059,7 +2054,7 @@ class AngularResizableDirective {
2059
2054
  }
2060
2055
  }
2061
2056
  resetBounding() {
2062
- if (this._bounding && this._bounding.position === 'static') {
2057
+ if (this._bounding?.position === 'static') {
2063
2058
  this.renderer.setStyle(this._containment, 'position', 'relative');
2064
2059
  }
2065
2060
  this._bounding = null;
@@ -2137,7 +2132,7 @@ class DataBoundDirective {
2137
2132
  this.cd = cd;
2138
2133
  }
2139
2134
  async ngOnChanges(changes) {
2140
- if (changes['databound'] && changes['databound'].currentValue) {
2135
+ if (changes['databound']?.currentValue) {
2141
2136
  const source = changes['databound'].currentValue;
2142
2137
  if (!(source instanceof BehaviorSubject)) {
2143
2138
  return;
@@ -2158,17 +2153,17 @@ class DataBoundDirective {
2158
2153
  });
2159
2154
  });
2160
2155
  }
2161
- else if (changes['bindingFunction'] && changes['bindingFunction'].currentValue && this.ds) {
2156
+ else if (changes['bindingFunction']?.currentValue && this.ds) {
2162
2157
  new Function('resultInfo, metaInfo, inputs, wtoolbox', this.bindingFunction)(this.ds.resultInfo, this.ds.metaInfo, this.inputs, WtoolboxService);
2163
2158
  this.cd.detectChanges();
2164
2159
  }
2165
- else if (changes['itemTemplate'] && changes['itemTemplate'].currentValue && changes['itemTemplate'].previousValue != changes['itemTemplate'].currentValue) {
2160
+ else if (changes['itemTemplate']?.currentValue && changes['itemTemplate'].previousValue != changes['itemTemplate'].currentValue) {
2166
2161
  this.inputs.itemTemplateComponent = DynamicGenericTemplateComponent.getComponentFromTemplate(this.inputs.itemTemplate || '', '[data-bound] itemTemplate (host-supplied)', String(this.ds?.metaInfo?.tableMetadata?.md_route_name || ''));
2167
2162
  if (this.ds) {
2168
2163
  await this.ds.fetchData();
2169
2164
  }
2170
2165
  }
2171
- else if (changes['clickCallback'] && changes['clickCallback'].currentValue) {
2166
+ else if (changes['clickCallback']?.currentValue) {
2172
2167
  this.inputs._wtoolbox = WtoolboxService;
2173
2168
  this.inputs.clickCallback__fn = new Function('resultInfo, metaInfo, inputs, event, wtoolbox', this.clickCallback);
2174
2169
  this.cd.detectChanges();
@@ -2251,7 +2246,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2251
2246
  */
2252
2247
  function getPointFromEvent(event) {
2253
2248
  // NOTE: In firefox TouchEvent is only defined for touch capable devices
2254
- const isTouchEvent = (e) => window.TouchEvent && event instanceof TouchEvent;
2249
+ const isTouchEvent = (e) => globalThis.TouchEvent && event instanceof TouchEvent;
2255
2250
  if (isTouchEvent(event)) {
2256
2251
  if (event.changedTouches.length === 0) {
2257
2252
  return undefined;
@@ -3145,17 +3140,17 @@ class SplitComponent {
3145
3140
  else {
3146
3141
  const percentSize = (tempAreasPixelSizes[index] / dragStartContext.totalAreasPixelSize) * 100;
3147
3142
  // Fix javascript only working with float numbers which are inaccurate compared to decimals
3148
- area._internalSize.set(parseFloat(percentSize.toFixed(10)));
3143
+ area._internalSize.set(Number.parseFloat(percentSize.toFixed(10)));
3149
3144
  }
3150
3145
  });
3151
3146
  this.dragProgressSubject.next(this.createDragInteractionEvent(this.draggedGutterIndex()));
3152
3147
  }
3153
3148
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SplitComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3154
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SplitComponent, isStandalone: true, selector: "p-splitter", inputs: { gutterSize: { classPropertyName: "gutterSize", publicName: "gutterSize", isSignal: true, isRequired: false, transformFunction: null }, gutterStep: { classPropertyName: "gutterStep", publicName: "gutterStep", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, gutterClickDeltaPx: { classPropertyName: "gutterClickDeltaPx", publicName: "gutterClickDeltaPx", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, gutterAriaLabel: { classPropertyName: "gutterAriaLabel", publicName: "gutterAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, restrictMove: { classPropertyName: "restrictMove", publicName: "restrictMove", isSignal: true, isRequired: false, transformFunction: null }, useTransition: { classPropertyName: "useTransition", publicName: "useTransition", isSignal: true, isRequired: false, transformFunction: null }, gutterDblClickDuration: { classPropertyName: "gutterDblClickDuration", publicName: "gutterDblClickDuration", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { gutterClick: "gutterClick", gutterDblClick: "gutterDblClick", dragStart: "dragStart", dragEnd: "dragEnd", transitionEnd: "transitionEnd" }, host: { properties: { "class": "this.hostClassesBinding", "dir": "this.hostDirBinding" } }, queries: [{ propertyName: "_areas", predicate: SPLIT_AREA_CONTRACT, isSignal: true }, { propertyName: "customGutter", first: true, predicate: SplitGutterDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-content></ng-content>\n@for (area of _areas(); track area) {\n @if (!$last) {\n <div\n #gutter\n class=\"as-split-gutter\"\n role=\"separator\"\n tabindex=\"0\"\n [attr.aria-label]=\"gutterAriaLabel()\"\n [attr.aria-orientation]=\"direction()\"\n [attr.aria-valuemin]=\"getAriaValue(area.minSize())\"\n [attr.aria-valuemax]=\"getAriaValue(area.maxSize())\"\n [attr.aria-valuenow]=\"getAriaValue(area._internalSize())\"\n [attr.aria-valuetext]=\"getAriaAreaSizeText(area)\"\n [ngStyle]=\"getGutterGridStyle($index + 1)\"\n [class.as-dragged]=\"draggedGutterIndex() === $index\"\n asSplitCustomEventsBehavior\n [asSplitCustomMultiClickThreshold]=\"gutterDblClickDuration()\"\n [asSplitCustomClickDeltaInPx]=\"gutterClickDeltaPx()\"\n (asSplitCustomClick)=\"gutterClicked($index)\"\n (asSplitCustomDblClick)=\"gutterDoubleClicked($index)\"\n (asSplitCustomMouseDown)=\"gutterMouseDown($event, gutter, $index, $index, $index + 1)\"\n (asSplitCustomKeyDown)=\"gutterKeyDown($event, $index, $index, $index + 1)\"\n >\n @if (customGutter()?.template) {\n <ng-container *asSplitGutterDynamicInjector=\"$index + 1; let injector\">\n <ng-container\n *ngTemplateOutlet=\"\n customGutter().template;\n context: {\n areaBefore: area,\n areaAfter: _areas()[$index + 1],\n gutterNum: $index + 1,\n first: $first,\n last: $index === _areas().length - 2,\n isDragged: draggedGutterIndex() === $index\n };\n injector: injector\n \"\n ></ng-container>\n </ng-container>\n } @else {\n <div class=\"as-split-gutter-icon\"></div>\n }\n </div>\n }\n}\n", styles: ["@property --as-gutter-background-color{syntax: \"<color>\"; inherits: true; initial-value: #eeeeee;}@property --as-gutter-icon-horizontal{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);}@property --as-gutter-icon-vertical{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC);}@property --as-gutter-icon-disabled{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);}@property --as-transition-duration{syntax: \"<time>\"; inherits: true; initial-value: .3s;}@property --as-gutter-disabled-cursor{syntax: \"*\"; inherits: true; initial-value: default;}:host{--_as-gutter-background-color: var(--as-gutter-background-color, #eeeeee);--_as-gutter-icon-horizontal: var(--as-gutter-icon-horizontal, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==));--_as-gutter-icon-vertical: var(--as-gutter-icon-vertical, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC));--_as-gutter-icon-disabled: var(--as-gutter-icon-disabled, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==));--_as-transition-duration: var(--as-transition-duration, .3s);--_as-gutter-disabled-cursor: var(--as-gutter-disabled-cursor, default)}:host{display:grid;overflow:hidden;height:100%;width:100%}:host(.as-transition){transition:grid-template var(--_as-transition-duration)}.as-split-gutter{background-color:var(--_as-gutter-background-color);display:flex;align-items:center;justify-content:center;touch-action:none}:host(.as-horizontal)>.as-split-gutter{cursor:col-resize;height:100%}:host(.as-vertical)>.as-split-gutter{cursor:row-resize;width:100%}:host(.as-disabled)>.as-split-gutter{cursor:var(--_as-gutter-disabled-cursor)}.as-split-gutter-icon{width:100%;height:100%;background-position:center center;background-repeat:no-repeat}:host(.as-horizontal)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-horizontal)}:host(.as-vertical)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-vertical)}:host(.as-disabled)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-disabled)}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: SplitCustomEventsBehaviorDirective, selector: "[asSplitCustomEventsBehavior]", inputs: ["asSplitCustomMultiClickThreshold", "asSplitCustomClickDeltaInPx"], outputs: ["asSplitCustomMouseDown", "asSplitCustomClick", "asSplitCustomDblClick", "asSplitCustomKeyDown"] }, { kind: "directive", type: SplitGutterDynamicInjectorDirective, selector: "[asSplitGutterDynamicInjector]", inputs: ["asSplitGutterDynamicInjector"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3149
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SplitComponent, isStandalone: true, selector: "p-splitter", inputs: { gutterSize: { classPropertyName: "gutterSize", publicName: "gutterSize", isSignal: true, isRequired: false, transformFunction: null }, gutterStep: { classPropertyName: "gutterStep", publicName: "gutterStep", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, gutterClickDeltaPx: { classPropertyName: "gutterClickDeltaPx", publicName: "gutterClickDeltaPx", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, gutterAriaLabel: { classPropertyName: "gutterAriaLabel", publicName: "gutterAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, restrictMove: { classPropertyName: "restrictMove", publicName: "restrictMove", isSignal: true, isRequired: false, transformFunction: null }, useTransition: { classPropertyName: "useTransition", publicName: "useTransition", isSignal: true, isRequired: false, transformFunction: null }, gutterDblClickDuration: { classPropertyName: "gutterDblClickDuration", publicName: "gutterDblClickDuration", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { gutterClick: "gutterClick", gutterDblClick: "gutterDblClick", dragStart: "dragStart", dragEnd: "dragEnd", transitionEnd: "transitionEnd" }, host: { properties: { "class": "this.hostClassesBinding", "dir": "this.hostDirBinding" } }, queries: [{ propertyName: "_areas", predicate: SPLIT_AREA_CONTRACT, isSignal: true }, { propertyName: "customGutter", first: true, predicate: SplitGutterDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-content></ng-content>\n@for (area of _areas(); track area) {\n @if (!$last) {\n <div\n #gutter\n class=\"as-split-gutter\"\n role=\"separator\"\n tabindex=\"0\"\n [attr.aria-label]=\"gutterAriaLabel()\"\n [attr.aria-orientation]=\"direction()\"\n [attr.aria-valuemin]=\"getAriaValue(area.minSize())\"\n [attr.aria-valuemax]=\"getAriaValue(area.maxSize())\"\n [attr.aria-valuenow]=\"getAriaValue(area._internalSize())\"\n [attr.aria-valuetext]=\"getAriaAreaSizeText(area)\"\n [ngStyle]=\"getGutterGridStyle($index + 1)\"\n [class.as-dragged]=\"draggedGutterIndex() === $index\"\n asSplitCustomEventsBehavior\n [asSplitCustomMultiClickThreshold]=\"gutterDblClickDuration()\"\n [asSplitCustomClickDeltaInPx]=\"gutterClickDeltaPx()\"\n (asSplitCustomClick)=\"gutterClicked($index)\"\n (asSplitCustomDblClick)=\"gutterDoubleClicked($index)\"\n (asSplitCustomMouseDown)=\"gutterMouseDown($event, gutter, $index, $index, $index + 1)\"\n (asSplitCustomKeyDown)=\"gutterKeyDown($event, $index, $index, $index + 1)\"\n >\n @if (customGutter()?.template) {\n <ng-container *asSplitGutterDynamicInjector=\"$index + 1; let injector\">\n <ng-container\n *ngTemplateOutlet=\"\n customGutter().template;\n context: {\n areaBefore: area,\n areaAfter: _areas()[$index + 1],\n gutterNum: $index + 1,\n first: $first,\n last: $index === _areas().length - 2,\n isDragged: draggedGutterIndex() === $index\n };\n injector: injector\n \"\n ></ng-container>\n </ng-container>\n } @else {\n <div class=\"as-split-gutter-icon\"></div>\n }\n </div>\n }\n}\n", styles: ["@property --as-gutter-background-color{syntax: \"<color>\"; inherits: true; initial-value: #eeeeee;}@property --as-gutter-icon-horizontal{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);}@property --as-gutter-icon-vertical{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC);}@property --as-gutter-icon-disabled{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);}@property --as-transition-duration{syntax: \"<time>\"; inherits: true; initial-value: .3s;}@property --as-gutter-disabled-cursor{syntax: \"*\"; inherits: true; initial-value: default;}:host{--_as-gutter-background-color: var(--as-gutter-background-color, #eeeeee);--_as-gutter-icon-horizontal: var(--as-gutter-icon-horizontal, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==));--_as-gutter-icon-vertical: var(--as-gutter-icon-vertical, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC));--_as-gutter-icon-disabled: var(--as-gutter-icon-disabled, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==));--_as-transition-duration: var(--as-transition-duration, .3s);--_as-gutter-disabled-cursor: var(--as-gutter-disabled-cursor, default);display:grid;overflow:hidden;height:100%;width:100%}:host(.as-transition){transition:grid-template var(--_as-transition-duration)}.as-split-gutter{background-color:var(--_as-gutter-background-color);display:flex;align-items:center;justify-content:center;touch-action:none}:host(.as-horizontal)>.as-split-gutter{cursor:col-resize;height:100%}:host(.as-vertical)>.as-split-gutter{cursor:row-resize;width:100%}:host(.as-disabled)>.as-split-gutter{cursor:var(--_as-gutter-disabled-cursor)}.as-split-gutter-icon{width:100%;height:100%;background-position:center center;background-repeat:no-repeat}:host(.as-horizontal)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-horizontal)}:host(.as-vertical)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-vertical)}:host(.as-disabled)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-disabled)}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: SplitCustomEventsBehaviorDirective, selector: "[asSplitCustomEventsBehavior]", inputs: ["asSplitCustomMultiClickThreshold", "asSplitCustomClickDeltaInPx"], outputs: ["asSplitCustomMouseDown", "asSplitCustomClick", "asSplitCustomDblClick", "asSplitCustomKeyDown"] }, { kind: "directive", type: SplitGutterDynamicInjectorDirective, selector: "[asSplitGutterDynamicInjector]", inputs: ["asSplitGutterDynamicInjector"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3155
3150
  }
3156
3151
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SplitComponent, decorators: [{
3157
3152
  type: Component,
3158
- args: [{ selector: 'p-splitter', imports: [NgStyle, SplitCustomEventsBehaviorDirective, SplitGutterDynamicInjectorDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>\n@for (area of _areas(); track area) {\n @if (!$last) {\n <div\n #gutter\n class=\"as-split-gutter\"\n role=\"separator\"\n tabindex=\"0\"\n [attr.aria-label]=\"gutterAriaLabel()\"\n [attr.aria-orientation]=\"direction()\"\n [attr.aria-valuemin]=\"getAriaValue(area.minSize())\"\n [attr.aria-valuemax]=\"getAriaValue(area.maxSize())\"\n [attr.aria-valuenow]=\"getAriaValue(area._internalSize())\"\n [attr.aria-valuetext]=\"getAriaAreaSizeText(area)\"\n [ngStyle]=\"getGutterGridStyle($index + 1)\"\n [class.as-dragged]=\"draggedGutterIndex() === $index\"\n asSplitCustomEventsBehavior\n [asSplitCustomMultiClickThreshold]=\"gutterDblClickDuration()\"\n [asSplitCustomClickDeltaInPx]=\"gutterClickDeltaPx()\"\n (asSplitCustomClick)=\"gutterClicked($index)\"\n (asSplitCustomDblClick)=\"gutterDoubleClicked($index)\"\n (asSplitCustomMouseDown)=\"gutterMouseDown($event, gutter, $index, $index, $index + 1)\"\n (asSplitCustomKeyDown)=\"gutterKeyDown($event, $index, $index, $index + 1)\"\n >\n @if (customGutter()?.template) {\n <ng-container *asSplitGutterDynamicInjector=\"$index + 1; let injector\">\n <ng-container\n *ngTemplateOutlet=\"\n customGutter().template;\n context: {\n areaBefore: area,\n areaAfter: _areas()[$index + 1],\n gutterNum: $index + 1,\n first: $first,\n last: $index === _areas().length - 2,\n isDragged: draggedGutterIndex() === $index\n };\n injector: injector\n \"\n ></ng-container>\n </ng-container>\n } @else {\n <div class=\"as-split-gutter-icon\"></div>\n }\n </div>\n }\n}\n", styles: ["@property --as-gutter-background-color{syntax: \"<color>\"; inherits: true; initial-value: #eeeeee;}@property --as-gutter-icon-horizontal{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);}@property --as-gutter-icon-vertical{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC);}@property --as-gutter-icon-disabled{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);}@property --as-transition-duration{syntax: \"<time>\"; inherits: true; initial-value: .3s;}@property --as-gutter-disabled-cursor{syntax: \"*\"; inherits: true; initial-value: default;}:host{--_as-gutter-background-color: var(--as-gutter-background-color, #eeeeee);--_as-gutter-icon-horizontal: var(--as-gutter-icon-horizontal, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==));--_as-gutter-icon-vertical: var(--as-gutter-icon-vertical, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC));--_as-gutter-icon-disabled: var(--as-gutter-icon-disabled, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==));--_as-transition-duration: var(--as-transition-duration, .3s);--_as-gutter-disabled-cursor: var(--as-gutter-disabled-cursor, default)}:host{display:grid;overflow:hidden;height:100%;width:100%}:host(.as-transition){transition:grid-template var(--_as-transition-duration)}.as-split-gutter{background-color:var(--_as-gutter-background-color);display:flex;align-items:center;justify-content:center;touch-action:none}:host(.as-horizontal)>.as-split-gutter{cursor:col-resize;height:100%}:host(.as-vertical)>.as-split-gutter{cursor:row-resize;width:100%}:host(.as-disabled)>.as-split-gutter{cursor:var(--_as-gutter-disabled-cursor)}.as-split-gutter-icon{width:100%;height:100%;background-position:center center;background-repeat:no-repeat}:host(.as-horizontal)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-horizontal)}:host(.as-vertical)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-vertical)}:host(.as-disabled)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-disabled)}\n"] }]
3153
+ args: [{ selector: 'p-splitter', imports: [NgStyle, SplitCustomEventsBehaviorDirective, SplitGutterDynamicInjectorDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>\n@for (area of _areas(); track area) {\n @if (!$last) {\n <div\n #gutter\n class=\"as-split-gutter\"\n role=\"separator\"\n tabindex=\"0\"\n [attr.aria-label]=\"gutterAriaLabel()\"\n [attr.aria-orientation]=\"direction()\"\n [attr.aria-valuemin]=\"getAriaValue(area.minSize())\"\n [attr.aria-valuemax]=\"getAriaValue(area.maxSize())\"\n [attr.aria-valuenow]=\"getAriaValue(area._internalSize())\"\n [attr.aria-valuetext]=\"getAriaAreaSizeText(area)\"\n [ngStyle]=\"getGutterGridStyle($index + 1)\"\n [class.as-dragged]=\"draggedGutterIndex() === $index\"\n asSplitCustomEventsBehavior\n [asSplitCustomMultiClickThreshold]=\"gutterDblClickDuration()\"\n [asSplitCustomClickDeltaInPx]=\"gutterClickDeltaPx()\"\n (asSplitCustomClick)=\"gutterClicked($index)\"\n (asSplitCustomDblClick)=\"gutterDoubleClicked($index)\"\n (asSplitCustomMouseDown)=\"gutterMouseDown($event, gutter, $index, $index, $index + 1)\"\n (asSplitCustomKeyDown)=\"gutterKeyDown($event, $index, $index, $index + 1)\"\n >\n @if (customGutter()?.template) {\n <ng-container *asSplitGutterDynamicInjector=\"$index + 1; let injector\">\n <ng-container\n *ngTemplateOutlet=\"\n customGutter().template;\n context: {\n areaBefore: area,\n areaAfter: _areas()[$index + 1],\n gutterNum: $index + 1,\n first: $first,\n last: $index === _areas().length - 2,\n isDragged: draggedGutterIndex() === $index\n };\n injector: injector\n \"\n ></ng-container>\n </ng-container>\n } @else {\n <div class=\"as-split-gutter-icon\"></div>\n }\n </div>\n }\n}\n", styles: ["@property --as-gutter-background-color{syntax: \"<color>\"; inherits: true; initial-value: #eeeeee;}@property --as-gutter-icon-horizontal{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);}@property --as-gutter-icon-vertical{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC);}@property --as-gutter-icon-disabled{syntax: \"<url>\"; inherits: true; initial-value: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);}@property --as-transition-duration{syntax: \"<time>\"; inherits: true; initial-value: .3s;}@property --as-gutter-disabled-cursor{syntax: \"*\"; inherits: true; initial-value: default;}:host{--_as-gutter-background-color: var(--as-gutter-background-color, #eeeeee);--_as-gutter-icon-horizontal: var(--as-gutter-icon-horizontal, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==));--_as-gutter-icon-vertical: var(--as-gutter-icon-vertical, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC));--_as-gutter-icon-disabled: var(--as-gutter-icon-disabled, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==));--_as-transition-duration: var(--as-transition-duration, .3s);--_as-gutter-disabled-cursor: var(--as-gutter-disabled-cursor, default);display:grid;overflow:hidden;height:100%;width:100%}:host(.as-transition){transition:grid-template var(--_as-transition-duration)}.as-split-gutter{background-color:var(--_as-gutter-background-color);display:flex;align-items:center;justify-content:center;touch-action:none}:host(.as-horizontal)>.as-split-gutter{cursor:col-resize;height:100%}:host(.as-vertical)>.as-split-gutter{cursor:row-resize;width:100%}:host(.as-disabled)>.as-split-gutter{cursor:var(--_as-gutter-disabled-cursor)}.as-split-gutter-icon{width:100%;height:100%;background-position:center center;background-repeat:no-repeat}:host(.as-horizontal)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-horizontal)}:host(.as-vertical)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-vertical)}:host(.as-disabled)>.as-split-gutter>.as-split-gutter-icon{background-image:var(--_as-gutter-icon-disabled)}\n"] }]
3159
3154
  }], ctorParameters: () => [], propDecorators: { _areas: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SPLIT_AREA_CONTRACT), { isSignal: true }] }], customGutter: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SplitGutterDirective), { isSignal: true }] }], gutterSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterSize", required: false }] }], gutterStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterStep", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], gutterClickDeltaPx: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterClickDeltaPx", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], gutterAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterAriaLabel", required: false }] }], restrictMove: [{ type: i0.Input, args: [{ isSignal: true, alias: "restrictMove", required: false }] }], useTransition: [{ type: i0.Input, args: [{ isSignal: true, alias: "useTransition", required: false }] }], gutterDblClickDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterDblClickDuration", required: false }] }], gutterClick: [{ type: i0.Output, args: ["gutterClick"] }], gutterDblClick: [{ type: i0.Output, args: ["gutterDblClick"] }], dragStart: [{ type: i0.Output, args: ["dragStart"] }], dragEnd: [{ type: i0.Output, args: ["dragEnd"] }], transitionEnd: [{ type: i0.Output, args: ["transitionEnd"] }], hostClassesBinding: [{
3160
3155
  type: HostBinding,
3161
3156
  args: ['class']
@@ -3221,7 +3216,7 @@ class SplitAreaComponent {
3221
3216
  /**
3222
3217
  * Indice corrente per index, usato per posizionamento o navigazione nel componente.
3223
3218
  */
3224
- index = computed(() => this.split._areas().findIndex((area) => area === this), ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
3219
+ index = computed(() => this.split._areas().indexOf(this), ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
3225
3220
  /**
3226
3221
  * Proprieta di stato del componente per grid area num, usata dalla logica interna e dal template.
3227
3222
  */
@@ -3487,7 +3482,7 @@ class DynamicDashboardTemplateComponent {
3487
3482
  let cache = [];
3488
3483
  let str = JSON.stringify(obj, function (key, value) {
3489
3484
  if (typeof value === "object" && value !== null) {
3490
- if (cache.indexOf(value) !== -1) {
3485
+ if (cache.includes(value)) {
3491
3486
  // Circular reference found, discard key
3492
3487
  return;
3493
3488
  }
@@ -3506,10 +3501,6 @@ class DynamicDashboardTemplateComponent {
3506
3501
  * @param parentElement Parametro utilizzato dal metodo nel flusso elaborativo.
3507
3502
  */
3508
3503
  onResizing(event, element, parentElement) {
3509
- if (parentElement) {
3510
- }
3511
- else {
3512
- }
3513
3504
  element.inputs.width = DynamicDashboardTemplateComponent.snap(event.size.width) + 'px';
3514
3505
  element.inputs.height = DynamicDashboardTemplateComponent.snap(event.size.height) + 'px';
3515
3506
  // Mark "designer mutation in progress" so the next window:mouseup in
@@ -3522,13 +3513,9 @@ class DynamicDashboardTemplateComponent {
3522
3513
  * @param element Parametro utilizzato dal metodo nel flusso elaborativo.
3523
3514
  */
3524
3515
  onMoving($event, element) {
3525
- // debugger;
3526
- // element.inputs.left = $event.position.x + 'px';
3527
- // element.inputs.top = $event.position.y + 'px';
3528
- // element.inputs.position = 'absolute';
3529
3516
  let scaleX = 1, skewY = 0, skewX = 0, scaleY = 1;
3530
3517
  if (element.inputs.transform) {
3531
- let matrix = element.inputs.transform.replace('matrix(', '').replace(')', '').split(',').map(x => parseFloat(x));
3518
+ let matrix = element.inputs.transform.replace('matrix(', '').replace(')', '').split(',').map(x => Number.parseFloat(x));
3532
3519
  if (matrix.length >= 1) {
3533
3520
  scaleX = matrix[0];
3534
3521
  }
@@ -3679,7 +3666,7 @@ class DynamicDashboardTemplateComponent {
3679
3666
  * Abilita drag/drop solo in contesto designer.
3680
3667
  */
3681
3668
  isDesignerMode() {
3682
- const hash = String(window?.location?.hash || '').toLowerCase();
3669
+ const hash = String(globalThis?.location?.hash || '').toLowerCase();
3683
3670
  return hash.includes('/designer');
3684
3671
  }
3685
3672
  /**
@@ -3695,9 +3682,9 @@ class DynamicDashboardTemplateComponent {
3695
3682
  */
3696
3683
  static getComponentFromTemplate(template, route, templateField) {
3697
3684
  const normalizedTemplate = String(template || '')
3698
- .replace(/wuic-parametric-dialog(?!-lazy)/g, 'wuic-parametric-dialog-lazy')
3699
- .replace(/ngxDraggableDom\s*=\s*\"true\"/g, '[ngxDraggableDom]="isDesignerMode()"')
3700
- .replace(/ngxDraggableDom\s*=\s*\'true\'/g, '[ngxDraggableDom]="isDesignerMode()"');
3685
+ .replaceAll(/wuic-parametric-dialog(?!-lazy)/g, 'wuic-parametric-dialog-lazy')
3686
+ .replaceAll(/ngxDraggableDom\s*=\s*"true"/g, '[ngxDraggableDom]="isDesignerMode()"')
3687
+ .replaceAll(/ngxDraggableDom\s*=\s*'true'/g, '[ngxDraggableDom]="isDesignerMode()"');
3701
3688
  return DynamicCompilerService.compile({
3702
3689
  template: normalizedTemplate,
3703
3690
  baseClass: DynamicDashboardTemplateComponent,
@@ -3779,6 +3766,18 @@ class DashboardComponent {
3779
3766
  * Input dal componente padre per dashboard elements; usata nella configurazione e nel rendering del componente.
3780
3767
  */
3781
3768
  dashboardElements;
3769
+ /**
3770
+ * Chrome "card" opzionale per i widget top-level (surface + bordo + radius
3771
+ * + shadow dai token --wuic-*). Opt-in dal boardcontent wrapper-object
3772
+ * (`{"widgetChrome": true, "dashboardElements": [...]}`): default false per
3773
+ * non alterare l'aspetto delle dashboard esistenti. Parser tollerante
3774
+ * boolean-like come le altre config archetype.
3775
+ */
3776
+ widgetChrome = false;
3777
+ get hasWidgetChrome() {
3778
+ const v = this.widgetChrome;
3779
+ return v === true || v === 1 || String(v).trim().toLowerCase() === 'true' || String(v).trim() === '1';
3780
+ }
3782
3781
  /**
3783
3782
  * Layout assoluto vs flusso normale: il "modo" con cui la dashboard e' stata
3784
3783
  * SALVATA e' codificato per-elemento nel boardcontent (`inputs.position`).
@@ -3828,13 +3827,18 @@ class DashboardComponent {
3828
3827
  }
3829
3828
  ;
3830
3829
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3831
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DashboardComponent, isStandalone: true, selector: "wuic-dashboard", inputs: { dashboardElements: "dashboardElements" }, host: { properties: { "class.wuic-dashboard-absolute-layout": "this.hasAbsoluteLayout" } }, ngImport: i0, template: "@for (dashboardElement of dashboardElements; track dashboardElement.uniqueName) {\r\n<ng-container *ngComponentOutlet=\"getComponent(dashboardElement); inputs: getComponentInputs(dashboardElement)\"></ng-container>\r\n}\r\n", styles: [":host(.wuic-dashboard-absolute-layout){position:relative;display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }] });
3830
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DashboardComponent, isStandalone: true, selector: "wuic-dashboard", inputs: { dashboardElements: "dashboardElements", widgetChrome: "widgetChrome" }, host: { properties: { "class.wuic-dashboard-widget-chrome": "this.hasWidgetChrome", "class.wuic-dashboard-absolute-layout": "this.hasAbsoluteLayout" } }, ngImport: i0, template: "@for (dashboardElement of dashboardElements; track dashboardElement.uniqueName) {\r\n<ng-container *ngComponentOutlet=\"getComponent(dashboardElement); inputs: getComponentInputs(dashboardElement)\"></ng-container>\r\n}\r\n", styles: [":host(.wuic-dashboard-absolute-layout){position:relative;display:block;width:100%;height:100%}:host(.wuic-dashboard-widget-chrome){display:block;padding:var(--wuic-space-3, 16px)}:host(.wuic-dashboard-widget-chrome)>:not(wuic-data-source):not(.datasource-descriptor){display:block;background:var(--wuic-surface, #ffffff);border:1px solid var(--wuic-border-soft, #e6ebf2);border-radius:var(--wuic-radius-lg, 10px);box-shadow:var(--wuic-shadow-1, 0 1px 3px rgba(15, 23, 42, .08));padding:var(--wuic-space-3, 16px);margin-bottom:var(--wuic-space-3, 16px)}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }] });
3832
3831
  }
3833
3832
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DashboardComponent, decorators: [{
3834
3833
  type: Component,
3835
- args: [{ selector: 'wuic-dashboard', imports: [NgComponentOutlet], template: "@for (dashboardElement of dashboardElements; track dashboardElement.uniqueName) {\r\n<ng-container *ngComponentOutlet=\"getComponent(dashboardElement); inputs: getComponentInputs(dashboardElement)\"></ng-container>\r\n}\r\n", styles: [":host(.wuic-dashboard-absolute-layout){position:relative;display:block;width:100%;height:100%}\n"] }]
3834
+ args: [{ selector: 'wuic-dashboard', imports: [NgComponentOutlet], template: "@for (dashboardElement of dashboardElements; track dashboardElement.uniqueName) {\r\n<ng-container *ngComponentOutlet=\"getComponent(dashboardElement); inputs: getComponentInputs(dashboardElement)\"></ng-container>\r\n}\r\n", styles: [":host(.wuic-dashboard-absolute-layout){position:relative;display:block;width:100%;height:100%}:host(.wuic-dashboard-widget-chrome){display:block;padding:var(--wuic-space-3, 16px)}:host(.wuic-dashboard-widget-chrome)>:not(wuic-data-source):not(.datasource-descriptor){display:block;background:var(--wuic-surface, #ffffff);border:1px solid var(--wuic-border-soft, #e6ebf2);border-radius:var(--wuic-radius-lg, 10px);box-shadow:var(--wuic-shadow-1, 0 1px 3px rgba(15, 23, 42, .08));padding:var(--wuic-space-3, 16px);margin-bottom:var(--wuic-space-3, 16px)}\n"] }]
3836
3835
  }], ctorParameters: () => [], propDecorators: { dashboardElements: [{
3837
3836
  type: Input
3837
+ }], widgetChrome: [{
3838
+ type: Input
3839
+ }], hasWidgetChrome: [{
3840
+ type: HostBinding,
3841
+ args: ['class.wuic-dashboard-widget-chrome']
3838
3842
  }], hasAbsoluteLayout: [{
3839
3843
  type: HostBinding,
3840
3844
  args: ['class.wuic-dashboard-absolute-layout']
@@ -3905,8 +3909,8 @@ class CssSheetEditorComponent {
3905
3909
  if (!this.valore) {
3906
3910
  this.valore = '#FFFFFF';
3907
3911
  }
3908
- this.pickerValue = this.toHsbaModel(this.valore);
3909
- this.alphaValue = this.clampAlpha(this.pickerValue?.a);
3912
+ this.pickerValue = toHsbaModel(this.valore);
3913
+ this.alphaValue = clampAlpha(this.pickerValue?.a);
3910
3914
  }
3911
3915
  /**
3912
3916
  * Gestisce i cambiamenti degli input aggiornando lo stato derivato e le dipendenze del componente.
@@ -4114,11 +4118,11 @@ class CssSheetEditorComponent {
4114
4118
  onPendingColorChanged(value) {
4115
4119
  const raw = value;
4116
4120
  const hsba = {
4117
- ...(raw || {}),
4118
- a: this.clampAlpha(raw?.a ?? this.alphaValue)
4121
+ ...(raw),
4122
+ a: clampAlpha(raw?.a ?? this.alphaValue)
4119
4123
  };
4120
- this.alphaValue = this.clampAlpha(hsba?.a);
4121
- const newValue = this.toPersistedColor(raw);
4124
+ this.alphaValue = clampAlpha(hsba?.a);
4125
+ const newValue = toPersistedColor(raw, this.alphaValue);
4122
4126
  this.pickerValue = raw;
4123
4127
  this.pendingStyleValue = this.valore = newValue;
4124
4128
  }
@@ -4220,7 +4224,7 @@ class CssSheetEditorComponent {
4220
4224
  * @returns Stringa risultante calcolata da `normalizePath` per chiavi/label o valori testuali.
4221
4225
  */
4222
4226
  normalizePath(path) {
4223
- return String(path || '').trim().replace(/\\/g, '/');
4227
+ return String(path || '').trim().replaceAll('\\', '/');
4224
4228
  }
4225
4229
  /**
4226
4230
  * Costruisce il payload/struttura risultante in `buildAssetSheetPath` partendo dai dati correnti.
@@ -4236,11 +4240,11 @@ class CssSheetEditorComponent {
4236
4240
  if (normalizedName.includes('/') || normalizedName.includes('\\')) {
4237
4241
  return '';
4238
4242
  }
4239
- normalizedName = normalizedName.replace(/\s+/g, '-');
4243
+ normalizedName = normalizedName.replaceAll(/\s+/g, '-');
4240
4244
  if (!normalizedName.toLowerCase().endsWith('.css')) {
4241
4245
  normalizedName += '.css';
4242
4246
  }
4243
- const folder = String(this.assetsFolder || '').trim().replace(/\\/g, '/').replace(/^\/+|\/+$/g, '');
4247
+ const folder = String(this.assetsFolder || '').trim().replaceAll('\\', '/').replaceAll(/^\/+|\/+$/g, '');
4244
4248
  if (!folder) {
4245
4249
  return '';
4246
4250
  }
@@ -4284,167 +4288,16 @@ class CssSheetEditorComponent {
4284
4288
  return found || null;
4285
4289
  }
4286
4290
  async onAlphaChange(rawAlpha) {
4287
- this.alphaValue = this.clampAlpha(rawAlpha);
4291
+ this.alphaValue = clampAlpha(rawAlpha);
4288
4292
  this.pickerValue = {
4289
- ...(this.pickerValue || {}),
4293
+ ...(this.pickerValue),
4290
4294
  a: this.alphaValue
4291
4295
  };
4292
- const newValue = this.toPersistedColor(this.pickerValue);
4296
+ const newValue = toPersistedColor(this.pickerValue, this.alphaValue);
4293
4297
  this.pendingStyleValue = this.valore = newValue;
4294
4298
  }
4295
- toPersistedColor(raw) {
4296
- if (raw === undefined || raw === null) {
4297
- return '';
4298
- }
4299
- if (typeof raw === 'string') {
4300
- return raw.trim();
4301
- }
4302
- const h = Number(raw?.h);
4303
- const s = Number(raw?.s);
4304
- const b = Number(raw?.b);
4305
- let a = Number(raw?.a);
4306
- if (!Number.isFinite(h) || !Number.isFinite(s) || !Number.isFinite(b)) {
4307
- return String(raw);
4308
- }
4309
- if (!Number.isFinite(a)) {
4310
- a = this.alphaValue;
4311
- }
4312
- a = this.clampAlpha(a);
4313
- return this.hsbaToRgbaString(h, s, b, a);
4314
- }
4315
- toHsbaModel(value) {
4316
- const fallback = { h: 0, s: 0, b: 100, a: 1 };
4317
- if (value === undefined || value === null) {
4318
- return fallback;
4319
- }
4320
- if (typeof value === 'object' && value?.h !== undefined && value?.s !== undefined && value?.b !== undefined) {
4321
- return {
4322
- h: Number(value.h) || 0,
4323
- s: Number(value.s) || 0,
4324
- b: Number(value.b) || 0,
4325
- a: Number.isFinite(Number(value.a)) ? Number(value.a) : 1
4326
- };
4327
- }
4328
- const str = String(value).trim();
4329
- if (!str) {
4330
- return fallback;
4331
- }
4332
- const rgbMatch = str.match(/^rgba?\(([^)]+)\)$/i);
4333
- if (rgbMatch) {
4334
- const parts = rgbMatch[1].split(',').map((x) => x.trim());
4335
- const r = Number(parts[0]);
4336
- const g = Number(parts[1]);
4337
- const b = Number(parts[2]);
4338
- const a = parts.length > 3 ? Number(parts[3]) : 1;
4339
- if (Number.isFinite(r) && Number.isFinite(g) && Number.isFinite(b)) {
4340
- return this.rgbaToHsbaModel(r, g, b, Number.isFinite(a) ? a : 1);
4341
- }
4342
- return fallback;
4343
- }
4344
- const hex = str.replace('#', '');
4345
- if (/^[0-9a-f]{3,8}$/i.test(hex)) {
4346
- const normalized = hex.length === 3
4347
- ? hex.split('').map((x) => `${x}${x}`).join('') + 'ff'
4348
- : hex.length === 4
4349
- ? hex.split('').map((x) => `${x}${x}`).join('')
4350
- : hex.length === 6
4351
- ? `${hex}ff`
4352
- : hex;
4353
- const r = parseInt(normalized.slice(0, 2), 16);
4354
- const g = parseInt(normalized.slice(2, 4), 16);
4355
- const b = parseInt(normalized.slice(4, 6), 16);
4356
- const a = parseInt(normalized.slice(6, 8), 16) / 255;
4357
- return this.rgbaToHsbaModel(r, g, b, a);
4358
- }
4359
- return fallback;
4360
- }
4361
- rgbaToHsbaModel(rRaw, gRaw, bRaw, aRaw) {
4362
- const r = Math.max(0, Math.min(255, rRaw)) / 255;
4363
- const g = Math.max(0, Math.min(255, gRaw)) / 255;
4364
- const b = Math.max(0, Math.min(255, bRaw)) / 255;
4365
- const a = Math.max(0, Math.min(1, aRaw));
4366
- const max = Math.max(r, g, b);
4367
- const min = Math.min(r, g, b);
4368
- const delta = max - min;
4369
- let h = 0;
4370
- if (delta !== 0) {
4371
- if (max === r) {
4372
- h = 60 * (((g - b) / delta) % 6);
4373
- }
4374
- else if (max === g) {
4375
- h = 60 * (((b - r) / delta) + 2);
4376
- }
4377
- else {
4378
- h = 60 * (((r - g) / delta) + 4);
4379
- }
4380
- }
4381
- if (h < 0) {
4382
- h += 360;
4383
- }
4384
- const s = max === 0 ? 0 : (delta / max) * 100;
4385
- const v = max * 100;
4386
- return {
4387
- h: Math.round(h),
4388
- s: Math.round(s),
4389
- b: Math.round(v),
4390
- a: Number(a.toFixed(3))
4391
- };
4392
- }
4393
- hsbaToRgbaString(hRaw, sRaw, bRaw, aRaw) {
4394
- const h = ((hRaw % 360) + 360) % 360;
4395
- const s = Math.max(0, Math.min(100, sRaw)) / 100;
4396
- const v = Math.max(0, Math.min(100, bRaw)) / 100;
4397
- const a = Math.max(0, Math.min(1, aRaw));
4398
- const c = v * s;
4399
- const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
4400
- const m = v - c;
4401
- let r1 = 0;
4402
- let g1 = 0;
4403
- let b1 = 0;
4404
- if (h < 60) {
4405
- r1 = c;
4406
- g1 = x;
4407
- b1 = 0;
4408
- }
4409
- else if (h < 120) {
4410
- r1 = x;
4411
- g1 = c;
4412
- b1 = 0;
4413
- }
4414
- else if (h < 180) {
4415
- r1 = 0;
4416
- g1 = c;
4417
- b1 = x;
4418
- }
4419
- else if (h < 240) {
4420
- r1 = 0;
4421
- g1 = x;
4422
- b1 = c;
4423
- }
4424
- else if (h < 300) {
4425
- r1 = x;
4426
- g1 = 0;
4427
- b1 = c;
4428
- }
4429
- else {
4430
- r1 = c;
4431
- g1 = 0;
4432
- b1 = x;
4433
- }
4434
- const r = Math.round((r1 + m) * 255);
4435
- const g = Math.round((g1 + m) * 255);
4436
- const b = Math.round((b1 + m) * 255);
4437
- return `rgba(${r}, ${g}, ${b}, ${Number(a.toFixed(3))})`;
4438
- }
4439
- clampAlpha(value) {
4440
- const parsed = Number(value);
4441
- if (!Number.isFinite(parsed)) {
4442
- return 1;
4443
- }
4444
- return Math.max(0, Math.min(1, parsed));
4445
- }
4446
4299
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CssSheetEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4447
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CssSheetEditorComponent, isStandalone: true, selector: "wuic-css-sheet-editor", inputs: { visible: "visible", sheets: "sheets", selectedSheetPath: "selectedSheetPath", styleProps: "styleProps", assetsFolder: "assetsFolder" }, outputs: { visibleChange: "visibleChange", applyEditor: "applyEditor" }, usesOnChanges: true, ngImport: i0, template: "<p-dialog [header]=\"'CSS Editor'\" [(visible)]=\"visible\" (visibleChange)=\"visibleChange.emit($event)\" [modal]=\"true\"\n [closable]=\"true\" [style]=\"{ width: '1100px', maxWidth: '98vw' }\">\n <div class=\"css-editor-layout\">\n <div class=\"css-editor-col\">\n <div class=\"css-editor-row\">\n <label>File CSS</label>\n <p-select [options]=\"draftSheets\" optionLabel=\"SheetPath\" optionValue=\"SheetPath\"\n [(ngModel)]=\"selectedSheetPathDraft\" (ngModelChange)=\"onSelectedSheetChanged()\" appendTo=\"body\"\n [style]=\"{ width: '100%' }\">\n </p-select>\n </div>\n <div class=\"css-editor-row css-editor-inline\">\n <input type=\"text\" [(ngModel)]=\"newSheetName\" pattern=\"^[^/\\\\]+$\"\n [placeholder]=\"'Nuovo file in assets/' + (assetsFolder || '<dash_route>') + ' (solo nome, es. dashboard-custom.css)'\" />\n <p-button label=\"Crea file\" (onClick)=\"addSheet()\" [disabled]=\"!assetsFolder\"></p-button>\n </div>\n @if (!assetsFolder) {\n <div class=\"css-editor-row\">\n <small>Salva prima la dashboard per definire il folder (dash_route).</small>\n </div>\n }\n <div class=\"css-editor-row\">\n <p-button severity=\"danger\" label=\"Rimuovi file selezionato\" (onClick)=\"removeSelectedSheet()\"\n [disabled]=\"!currentSheet\"></p-button>\n </div>\n </div>\n\n @if (currentSheet) {\n <div class=\"css-editor-col\">\n <div class=\"css-editor-row\">\n <label>Classi</label>\n <p-select [options]=\"currentSheet?.classes || []\" optionLabel=\"SelectorString\" optionValue=\"SelectorString\"\n [(ngModel)]=\"selectedClassSelector\" (ngModelChange)=\"onSelectedClassChanged()\" appendTo=\"body\"\n [style]=\"{ width: '100%' }\">\n </p-select>\n </div>\n <div class=\"css-editor-row css-editor-inline\">\n <input type=\"text\" [(ngModel)]=\"newClassName\" placeholder=\"Nuova classe (es. card-title)\" />\n <p-button label=\"Crea classe\" (onClick)=\"addClassToSelectedSheet()\" [disabled]=\"!currentSheet\"></p-button>\n </div>\n <div class=\"css-editor-row\">\n <p-button severity=\"danger\" label=\"Rimuovi classe selezionata\" (onClick)=\"removeSelectedClass()\"\n [disabled]=\"!currentClass\"></p-button>\n </div>\n </div>\n }\n </div>\n\n @if (currentClass) {\n <div class=\"css-editor-styles\">\n <div class=\"css-editor-row css-style-row\" style=\"margin-bottom: 8px;\">\n <p-select [options]=\"styleProps\" optionLabel=\"key\" optionValue=\"key\" [(ngModel)]=\"pendingStyleKey\"\n (ngModelChange)=\"onPendingStyleKeyChanged()\" appendTo=\"body\" [style]=\"{ width: '260px' }\">\n </p-select>\n\n @if (isPropertyDictionary(pendingStyleKey)) {\n <p-select [options]=\"getPropertyValues(pendingStyleKey)\" [(ngModel)]=\"pendingStyleValue\" appendTo=\"body\"\n [style]=\"{ width: '320px' }\">\n </p-select>\n } @else if (isPropertyColor(pendingStyleKey)) {\n\n <div class=\"css-style-color-input\">\n <div class=\"color-editor-root\" [ngStyle]=\"{ '--wuic-color-editor-preview': valore || 'transparent' }\">\n <p-colorPicker format=\"hsb\" [ngModel]=\"pickerValue\" (ngModelChange)=\"onPendingColorChanged($event)\"\n appendTo=\"body\">\n </p-colorPicker>\n </div>\n <input type=\"text\" [(ngModel)]=\"pendingStyleValue\" style=\"width: 252px;\" />\n </div>\n <div class=\"color-editor-alpha-row\">\n <label class=\"color-editor-alpha-label\">Alpha</label>\n <input type=\"range\" min=\"0\" max=\"1\" step=\"0.01\" [ngModel]=\"alphaValue\"\n (ngModelChange)=\"onAlphaChange($event)\" />\n <input type=\"number\" min=\"0\" max=\"1\" step=\"0.01\" [ngModel]=\"alphaValue\"\n (ngModelChange)=\"onAlphaChange($event)\" />\n </div>\n\n } @else {\n <input type=\"text\" [(ngModel)]=\"pendingStyleValue\" style=\"width: 320px;\" />\n }\n\n <p-button label=\"Aggiungi propriet\u00E0 corrente\" (onClick)=\"addStyleToSelectedClass()\"\n [disabled]=\"!currentClass || !pendingStyleKey\"></p-button>\n </div>\n\n @for (style of currentClass.Styles; track style; let i = $index) {\n <div class=\"css-style-row\">\n <div class=\"css-style-readonly-key\">{{ style.Key }}</div>\n <div class=\"css-style-readonly-value\">{{ style.Value }}</div>\n\n <p-button icon=\"pi pi-trash\" severity=\"danger\" [text]=\"true\" (onClick)=\"removeStyle(i)\"></p-button>\n </div>\n }\n </div>\n }\n\n <ng-template pTemplate=\"footer\">\n <p-button label=\"Chiudi\" severity=\"secondary\" (onClick)=\"close()\"></p-button>\n </ng-template>\n</p-dialog>", styles: [".css-editor-layout{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}.css-editor-col{border:1px solid #d0d0d0;border-radius:6px;padding:12px}.css-editor-row{display:flex;flex-direction:column;gap:8px;margin-bottom:10px}.css-editor-inline{flex-direction:row;align-items:center}.css-editor-inline input{flex:1}.css-editor-styles{border:1px solid #d0d0d0;border-radius:6px;padding:12px;max-height:420px;overflow:auto}.css-style-row{display:flex;align-items:center;gap:8px;margin-bottom:8px}.css-style-readonly-key{width:260px;min-height:32px;display:flex;align-items:center;padding:0 8px;border:1px solid #d0d0d0;border-radius:4px;background:#f9f9f9;font-family:monospace}.css-style-readonly-value{width:320px;min-height:32px;display:flex;align-items:center;padding:0 8px;border:1px solid #d0d0d0;border-radius:4px;background:#f9f9f9;font-family:monospace}.css-style-color-input{display:flex;align-items:center;gap:8px;width:320px}@media(max-width:1024px){.css-editor-layout{grid-template-columns:1fr}.css-style-row{flex-wrap:wrap}}.color-editor-root{--wuic-color-editor-preview: transparent;border:solid 1px}:host ::ng-deep .color-editor-root .p-colorpicker-preview{background-image:linear-gradient(var(--wuic-color-editor-preview),var(--wuic-color-editor-preview)),linear-gradient(45deg,#d5d9e2 25%,transparent 25%),linear-gradient(-45deg,#d5d9e2 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#d5d9e2 75%),linear-gradient(-45deg,transparent 75%,#d5d9e2 75%)!important;background-size:10px 10px!important;background-position:0 0,0 5px,5px -5px,-5px 0!important;background-color:transparent!important}.color-editor-alpha-row{display:flex;align-items:center;gap:.5rem;margin-top:.5rem}.color-editor-alpha-label{min-width:2.8rem;font-size:.85rem}.color-editor-alpha-row input[type=range]{flex:1 1 auto}.color-editor-alpha-row input[type=number]{width:4.5rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i6.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ColorPickerModule }, { kind: "component", type: i2$1.ColorPicker, selector: "p-colorPicker, p-colorpicker, p-color-picker", inputs: ["styleClass", "showTransitionOptions", "hideTransitionOptions", "inline", "format", "tabindex", "inputId", "autoZIndex", "autofocus", "defaultColor", "appendTo", "overlayOptions", "motionOptions"], outputs: ["onChange", "onShow", "onHide"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
4300
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CssSheetEditorComponent, isStandalone: true, selector: "wuic-css-sheet-editor", inputs: { visible: "visible", sheets: "sheets", selectedSheetPath: "selectedSheetPath", styleProps: "styleProps", assetsFolder: "assetsFolder" }, outputs: { visibleChange: "visibleChange", applyEditor: "applyEditor" }, usesOnChanges: true, ngImport: i0, template: "<p-dialog [header]=\"'CSS Editor'\" [(visible)]=\"visible\" (visibleChange)=\"visibleChange.emit($event)\" [modal]=\"true\"\n [closable]=\"true\" [style]=\"{ width: '1100px', maxWidth: '98vw' }\">\n <div class=\"css-editor-layout\">\n <div class=\"css-editor-col\">\n <div class=\"css-editor-row\">\n <label>File CSS</label>\n <p-select [options]=\"draftSheets\" optionLabel=\"SheetPath\" optionValue=\"SheetPath\"\n [(ngModel)]=\"selectedSheetPathDraft\" (ngModelChange)=\"onSelectedSheetChanged()\" appendTo=\"body\"\n [style]=\"{ width: '100%' }\">\n </p-select>\n </div>\n <div class=\"css-editor-row css-editor-inline\">\n <input type=\"text\" [(ngModel)]=\"newSheetName\" pattern=\"^[^/\\\\]+$\"\n [placeholder]=\"'Nuovo file in assets/' + (assetsFolder || '<dash_route>') + ' (solo nome, es. dashboard-custom.css)'\" />\n <p-button label=\"Crea file\" (onClick)=\"addSheet()\" [disabled]=\"!assetsFolder\"></p-button>\n </div>\n @if (!assetsFolder) {\n <div class=\"css-editor-row\">\n <small>Salva prima la dashboard per definire il folder (dash_route).</small>\n </div>\n }\n <div class=\"css-editor-row\">\n <p-button severity=\"danger\" label=\"Rimuovi file selezionato\" (onClick)=\"removeSelectedSheet()\"\n [disabled]=\"!currentSheet\"></p-button>\n </div>\n </div>\n\n @if (currentSheet) {\n <div class=\"css-editor-col\">\n <div class=\"css-editor-row\">\n <label>Classi</label>\n <p-select [options]=\"currentSheet?.classes || []\" optionLabel=\"SelectorString\" optionValue=\"SelectorString\"\n [(ngModel)]=\"selectedClassSelector\" (ngModelChange)=\"onSelectedClassChanged()\" appendTo=\"body\"\n [style]=\"{ width: '100%' }\">\n </p-select>\n </div>\n <div class=\"css-editor-row css-editor-inline\">\n <input type=\"text\" [(ngModel)]=\"newClassName\" placeholder=\"Nuova classe (es. card-title)\" />\n <p-button label=\"Crea classe\" (onClick)=\"addClassToSelectedSheet()\" [disabled]=\"!currentSheet\"></p-button>\n </div>\n <div class=\"css-editor-row\">\n <p-button severity=\"danger\" label=\"Rimuovi classe selezionata\" (onClick)=\"removeSelectedClass()\"\n [disabled]=\"!currentClass\"></p-button>\n </div>\n </div>\n }\n </div>\n\n @if (currentClass) {\n <div class=\"css-editor-styles\">\n <div class=\"css-editor-row css-style-row\" style=\"margin-bottom: 8px;\">\n <p-select [options]=\"styleProps\" optionLabel=\"key\" optionValue=\"key\" [(ngModel)]=\"pendingStyleKey\"\n (ngModelChange)=\"onPendingStyleKeyChanged()\" appendTo=\"body\" [style]=\"{ width: '260px' }\">\n </p-select>\n\n @if (isPropertyDictionary(pendingStyleKey)) {\n <p-select [options]=\"getPropertyValues(pendingStyleKey)\" [(ngModel)]=\"pendingStyleValue\" appendTo=\"body\"\n [style]=\"{ width: '320px' }\">\n </p-select>\n } @else if (isPropertyColor(pendingStyleKey)) {\n\n <div class=\"css-style-color-input\">\n <div class=\"color-editor-root\" [ngStyle]=\"{ '--wuic-color-editor-preview': valore || 'transparent' }\">\n <p-colorPicker format=\"hsb\" [ngModel]=\"pickerValue\" (ngModelChange)=\"onPendingColorChanged($event)\"\n appendTo=\"body\">\n </p-colorPicker>\n </div>\n <input type=\"text\" [(ngModel)]=\"pendingStyleValue\" style=\"width: 252px;\" />\n </div>\n <div class=\"color-editor-alpha-row\">\n <label class=\"color-editor-alpha-label\">Alpha</label>\n <input type=\"range\" min=\"0\" max=\"1\" step=\"0.01\" [ngModel]=\"alphaValue\"\n (ngModelChange)=\"onAlphaChange($event)\" />\n <input type=\"number\" min=\"0\" max=\"1\" step=\"0.01\" [ngModel]=\"alphaValue\"\n (ngModelChange)=\"onAlphaChange($event)\" />\n </div>\n\n } @else {\n <input type=\"text\" [(ngModel)]=\"pendingStyleValue\" style=\"width: 320px;\" />\n }\n\n <p-button label=\"Aggiungi propriet\u00E0 corrente\" (onClick)=\"addStyleToSelectedClass()\"\n [disabled]=\"!currentClass || !pendingStyleKey\"></p-button>\n </div>\n\n @for (style of currentClass.Styles; track style; let i = $index) {\n <div class=\"css-style-row\">\n <div class=\"css-style-readonly-key\">{{ style.Key }}</div>\n <div class=\"css-style-readonly-value\">{{ style.Value }}</div>\n\n <p-button icon=\"pi pi-trash\" severity=\"danger\" [text]=\"true\" (onClick)=\"removeStyle(i)\"></p-button>\n </div>\n }\n </div>\n }\n\n <ng-template pTemplate=\"footer\">\n <p-button label=\"Chiudi\" severity=\"secondary\" (onClick)=\"close()\"></p-button>\n </ng-template>\n</p-dialog>", styles: [".css-editor-layout{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}.css-editor-col{border:1px solid #d0d0d0;border-radius:6px;padding:12px}.css-editor-row{display:flex;flex-direction:column;gap:8px;margin-bottom:10px}.css-editor-inline{flex-direction:row;align-items:center}.css-editor-inline input{flex:1}.css-editor-styles{border:1px solid #d0d0d0;border-radius:6px;padding:12px;max-height:420px;overflow:auto}.css-style-row{display:flex;align-items:center;gap:8px;margin-bottom:8px}.css-style-readonly-key{width:260px;min-height:32px;display:flex;align-items:center;padding:0 8px;border:1px solid #d0d0d0;border-radius:4px;background:#f9f9f9;font-family:monospace}.css-style-readonly-value{width:320px;min-height:32px;display:flex;align-items:center;padding:0 8px;border:1px solid #d0d0d0;border-radius:4px;background:#f9f9f9;font-family:monospace}.css-style-color-input{display:flex;align-items:center;gap:8px;width:320px}@media(max-width:1024px){.css-editor-layout{grid-template-columns:1fr}.css-style-row{flex-wrap:wrap}}.color-editor-root{--wuic-color-editor-preview: transparent;border:solid 1px}:host ::ng-deep .color-editor-root .p-colorpicker-preview{background-image:linear-gradient(var(--wuic-color-editor-preview),var(--wuic-color-editor-preview)),linear-gradient(45deg,#d5d9e2 25%,transparent 25%),linear-gradient(-45deg,#d5d9e2 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#d5d9e2 75%),linear-gradient(-45deg,transparent 75%,#d5d9e2 75%)!important;background-size:10px 10px!important;background-position:0 0,0 5px,5px -5px,-5px 0!important;background-color:transparent!important}.color-editor-alpha-row{display:flex;align-items:center;gap:.5rem;margin-top:.5rem}.color-editor-alpha-label{min-width:2.8rem;font-size:.85rem}.color-editor-alpha-row input[type=range]{flex:1 1 auto}.color-editor-alpha-row input[type=number]{width:4.5rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ColorPickerModule }, { kind: "component", type: i6.ColorPicker, selector: "p-colorPicker, p-colorpicker, p-color-picker", inputs: ["styleClass", "showTransitionOptions", "hideTransitionOptions", "inline", "format", "tabindex", "inputId", "autoZIndex", "autofocus", "defaultColor", "appendTo", "overlayOptions", "motionOptions"], outputs: ["onChange", "onShow", "onHide"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
4448
4301
  }
4449
4302
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CssSheetEditorComponent, decorators: [{
4450
4303
  type: Component,
@@ -4555,6 +4408,8 @@ class DesignerComponent {
4555
4408
  reopenDashboardDialogVisible = false;
4556
4409
  reopenDialogSelectedDashboardRoute = null;
4557
4410
  noEdit;
4411
+ /** Chrome card dei widget top-level (flag board-level dal boardcontent wrapper-object). */
4412
+ dashboardWidgetChrome = false;
4558
4413
  currentDashboardRoute = '';
4559
4414
  currentDashboardDescription = '';
4560
4415
  showArchetypeConfigurator = false;
@@ -4917,7 +4772,6 @@ class DesignerComponent {
4917
4772
  size: 50,
4918
4773
  areas: 2,
4919
4774
  resize: (event, splitter) => {
4920
- // let indx = event.gutterNum;
4921
4775
  splitter.nestedComponents.forEach((area, i) => {
4922
4776
  area.inputs.size = event.sizes[i];
4923
4777
  });
@@ -4976,29 +4830,18 @@ class DesignerComponent {
4976
4830
  delete this.accordionAreaInputs['cssClass'];
4977
4831
  this.accordionAreaInputs['height'] = null;
4978
4832
  this.accordionAreaInputs['display'] = 'block';
4979
- // this.accordionAreaInputs['borderStyle'] = 'none';
4980
4833
  this.accordionAreaInputs['borderTopStyle'] = 'none';
4981
4834
  this.accordionAreaInputs['borderLeftStyle'] = 'none';
4982
4835
  this.accordionAreaInputs['borderRightStyle'] = 'none';
4983
4836
  this.accordionAreaInputs['borderBottomStyle'] = 'solid';
4984
4837
  this.accordionAreaInputs['borderBottomWidth'] = '1px';
4985
4838
  this.accordionAreaInputs['borderBottomColor'] = '#e2e8f0';
4986
- // let divCtx = [
4987
- // {
4988
- // label: 'Add DIV',
4989
- // icon: 'pi pi-plus',
4990
- // command: (menuItem) => {
4991
- // debugger;
4992
- // }
4993
- // } as any
4994
- // ];
4995
- // divCtx.push(...this.defaultCtxItems);
4996
4839
  this.availableTools = [
4997
4840
  {
4998
4841
  group: 'HTML',
4999
4842
  toolId: 1,
5000
4843
  name: 'TABLE',
5001
- tag: `<table [attr.id]="uniqueName" ngxDraggableDom="true" (moved)="onMoving($event, this)" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}><tr *ngFor="let nestedTR of nestedComponents" [attr.id]="nestedTR.uniqueName" ${this.htmlStyleString.replace(/0/g, 'nestedTR.inputs')}><td *ngFor="let nestedTD of nestedTR.nestedComponents" [attr.id]="nestedTD.uniqueName" [attr.colspan]="nestedTD.inputs?.colSpan || null" [attr.rowspan]="nestedTD.inputs?.rowSpan || null" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, nestedTD)" ${this.htmlStyleString.replace(/0/g, 'nestedTD.inputs')}><wuic-dashboard [dashboardElements]="nestedTD.nestedComponents"></wuic-dashboard></td></tr></table>`,
4844
+ tag: `<table [attr.id]="uniqueName" ngxDraggableDom="true" (moved)="onMoving($event, this)" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}><tr *ngFor="let nestedTR of nestedComponents" [attr.id]="nestedTR.uniqueName" ${this.htmlStyleString.replaceAll('0', 'nestedTR.inputs')}><td *ngFor="let nestedTD of nestedTR.nestedComponents" [attr.id]="nestedTD.uniqueName" [attr.colspan]="nestedTD.inputs?.colSpan || null" [attr.rowspan]="nestedTD.inputs?.rowSpan || null" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, nestedTD)" ${this.htmlStyleString.replaceAll('0', 'nestedTD.inputs')}><wuic-dashboard [dashboardElements]="nestedTD.nestedComponents"></wuic-dashboard></td></tr></table>`,
5002
4845
  icon: 'pi pi-table',
5003
4846
  inputProps: tableProps,
5004
4847
  inputs: tableFullInputs,
@@ -5013,7 +4856,7 @@ class DesignerComponent {
5013
4856
  tag: ``,
5014
4857
  icon: 'pi pi-bars',
5015
4858
  inputProps: this.htmlInputProperties,
5016
- inputs: Object.assign({}, tableFullInputs, { cssClass: [] }),
4859
+ inputs: { ...tableFullInputs, cssClass: [] },
5017
4860
  nestedComponents: []
5018
4861
  },
5019
4862
  {
@@ -5023,21 +4866,24 @@ class DesignerComponent {
5023
4866
  name: 'TD',
5024
4867
  tag: ``,
5025
4868
  icon: 'pi pi-bars',
5026
- inputProps: Object.assign({}, this.htmlInputProperties, {
4869
+ inputProps: {
4870
+ ...this.htmlInputProperties,
5027
4871
  colSpan: { type: 'string', propertyCaption: 'Col span' },
5028
4872
  rowSpan: { type: 'string', propertyCaption: 'Row span' }
5029
- }),
5030
- inputs: Object.assign({}, tableFullInputs, {
4873
+ },
4874
+ inputs: {
4875
+ ...tableFullInputs,
5031
4876
  colSpan: '',
5032
- rowSpan: ''
5033
- }, { cssClass: [] }),
4877
+ rowSpan: '',
4878
+ cssClass: []
4879
+ },
5034
4880
  nestedComponents: []
5035
4881
  },
5036
4882
  {
5037
4883
  group: 'HTML',
5038
4884
  toolId: 2,
5039
4885
  name: 'DIV',
5040
- tag: `<div [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}><wuic-dashboard [dashboardElements]="nestedComponents"></wuic-dashboard></div>`,
4886
+ tag: `<div [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}><wuic-dashboard [dashboardElements]="nestedComponents"></wuic-dashboard></div>`,
5041
4887
  icon: 'pi pi-stop',
5042
4888
  inputProps: this.htmlInputProperties,
5043
4889
  inputs: this.htmlInputs,
@@ -5048,7 +4894,7 @@ class DesignerComponent {
5048
4894
  group: 'HTML',
5049
4895
  toolId: 3,
5050
4896
  name: 'SPAN',
5051
- tag: `<span [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{inputs.innerText}}</span>`,
4897
+ tag: `<span [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{inputs.innerText}}</span>`,
5052
4898
  icon: 'pi pi-language',
5053
4899
  inputProps: this.bindableHtmlProps,
5054
4900
  inputs: this.bindableHtmlInputs
@@ -5057,25 +4903,27 @@ class DesignerComponent {
5057
4903
  group: 'HTML',
5058
4904
  toolId: 17,
5059
4905
  name: 'LABEL',
5060
- tag: `<label [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{getLabelDisplayValue(inputs)}}</label>`,
4906
+ tag: `<label [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{getLabelDisplayValue(inputs)}}</label>`,
5061
4907
  icon: 'pi pi-tag',
5062
- inputProps: Object.assign({}, this.bindableHtmlProps, {
4908
+ inputProps: {
4909
+ ...this.bindableHtmlProps,
5063
4910
  displayField: { type: 'dictionary', values: [''], propertyCaption: 'Display Field' },
5064
4911
  displayFormula: { type: 'button', propertyCaption: 'Display Formula', hideCaption: true, callback: this.openLabelDisplayFormulaEditor.bind(this) }
5065
- }),
5066
- inputs: Object.assign({}, this.bindableHtmlInputs, {
4912
+ },
4913
+ inputs: {
4914
+ ...this.bindableHtmlInputs,
5067
4915
  datasource: null,
5068
4916
  componentRef: null,
5069
4917
  innerText: 'Label',
5070
4918
  displayField: '',
5071
4919
  displayFormula: ''
5072
- })
4920
+ }
5073
4921
  },
5074
4922
  {
5075
4923
  group: 'HTML',
5076
4924
  toolId: 4,
5077
4925
  name: 'Hx',
5078
- tag: `<h1 *ngIf="inputs.headerType == 'h1'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{inputs.innerText}}</h1><h2 *ngIf="inputs.headerType == 'h2'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{inputs.innerText}}</h2><h3 *ngIf="inputs.headerType == 'h3'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{inputs.innerText}}</h3><h4 *ngIf="inputs.headerType == 'h4'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{inputs.innerText}}</h4><h5 *ngIf="inputs.headerType == 'h5'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{inputs.innerText}}</h5><h6 *ngIf="inputs.headerType == 'h6'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{inputs.innerText}}</h6>`,
4926
+ tag: `<h1 *ngIf="inputs.headerType == 'h1'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{inputs.innerText}}</h1><h2 *ngIf="inputs.headerType == 'h2'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{inputs.innerText}}</h2><h3 *ngIf="inputs.headerType == 'h3'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{inputs.innerText}}</h3><h4 *ngIf="inputs.headerType == 'h4'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{inputs.innerText}}</h4><h5 *ngIf="inputs.headerType == 'h5'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{inputs.innerText}}</h5><h6 *ngIf="inputs.headerType == 'h6'" [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{inputs.innerText}}</h6>`,
5079
4927
  icon: 'pi pi-chevron-up',
5080
4928
  inputProps: this.headerProps,
5081
4929
  inputs: this.headerInputs
@@ -5084,7 +4932,7 @@ class DesignerComponent {
5084
4932
  group: 'HTML',
5085
4933
  toolId: 5,
5086
4934
  name: 'ANCHOR',
5087
- tag: `<a [attr.id]="uniqueName" [href]="inputs.href" [target]="inputs.target" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>{{inputs.innerText}}</a>`,
4935
+ tag: `<a [attr.id]="uniqueName" [href]="inputs.href" [target]="inputs.target" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>{{inputs.innerText}}</a>`,
5088
4936
  icon: 'pi pi-link',
5089
4937
  inputProps: this.anchorProps,
5090
4938
  inputs: this.anchorInputs
@@ -5093,7 +4941,7 @@ class DesignerComponent {
5093
4941
  group: 'HTML',
5094
4942
  toolId: 6,
5095
4943
  name: 'IMG',
5096
- tag: `<img [attr.id]="uniqueName" [src]="inputs.src" [alt]="inputs.alt" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
4944
+ tag: `<img [attr.id]="uniqueName" [src]="inputs.src" [alt]="inputs.alt" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')} />`,
5097
4945
  icon: 'pi pi-image',
5098
4946
  inputProps: this.imgProps,
5099
4947
  inputs: this.imgInputs
@@ -5102,47 +4950,51 @@ class DesignerComponent {
5102
4950
  group: 'HTML',
5103
4951
  toolId: 18,
5104
4952
  name: 'IFRAME',
5105
- tag: `<iframe [attr.id]="uniqueName" [attr.src]="inputs.src" [attr.frameborder]="inputs.frameBorder" [attr.allowfullscreen]="inputs.allowFullscreen ? '' : null" ngxDraggableDom="true" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}></iframe>`,
4953
+ tag: `<iframe [attr.id]="uniqueName" [attr.src]="inputs.src" [attr.frameborder]="inputs.frameBorder" [attr.allowfullscreen]="inputs.allowFullscreen ? '' : null" ngxDraggableDom="true" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}></iframe>`,
5106
4954
  icon: 'pi pi-window-maximize',
5107
- inputProps: Object.assign({}, this.htmlInputProperties, {
4955
+ inputProps: {
4956
+ ...this.htmlInputProperties,
5108
4957
  src: { type: 'string', propertyCaption: 'Source URL' },
5109
4958
  frameBorder: { type: 'dictionary', values: ['0', '1'], propertyCaption: 'Frame Border' },
5110
4959
  allowFullscreen: { type: 'boolean', propertyCaption: 'Allow Fullscreen' }
5111
- }),
5112
- inputs: Object.assign({}, this.htmlInputs, {
4960
+ },
4961
+ inputs: {
4962
+ ...this.htmlInputs,
5113
4963
  src: '',
5114
4964
  frameBorder: '0',
5115
4965
  allowFullscreen: false,
5116
4966
  width: '480px',
5117
4967
  height: '280px'
5118
- })
4968
+ }
5119
4969
  },
5120
4970
  {
5121
4971
  group: 'HTML',
5122
4972
  toolId: 130,
5123
4973
  name: 'IMAGE',
5124
- tag: `<wuic-image-wrapper-lazy [attr.id]="uniqueName" [src]="inputs.src" [alt]="inputs.alt" [preview]="inputs.preview" [previewImageSrc]="inputs.previewImageSrc" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}></wuic-image-wrapper-lazy>`,
4974
+ tag: `<wuic-image-wrapper-lazy [attr.id]="uniqueName" [src]="inputs.src" [alt]="inputs.alt" [preview]="inputs.preview" [previewImageSrc]="inputs.previewImageSrc" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}></wuic-image-wrapper-lazy>`,
5125
4975
  icon: 'pi pi-images',
5126
- inputProps: Object.assign({}, this.htmlInputProperties, {
4976
+ inputProps: {
4977
+ ...this.htmlInputProperties,
5127
4978
  src: { type: 'string', propertyCaption: 'Source URL' },
5128
4979
  previewImageSrc: { type: 'string', propertyCaption: 'Preview (full-size) URL' },
5129
4980
  alt: { type: 'string', propertyCaption: 'Alt text' },
5130
4981
  preview: { type: 'boolean', propertyCaption: 'Enable lightbox preview' }
5131
- }),
5132
- inputs: Object.assign({}, this.htmlInputs, {
4982
+ },
4983
+ inputs: {
4984
+ ...this.htmlInputs,
5133
4985
  src: '',
5134
4986
  previewImageSrc: '',
5135
4987
  alt: '',
5136
4988
  preview: true,
5137
4989
  width: '240px',
5138
4990
  height: '160px'
5139
- })
4991
+ }
5140
4992
  },
5141
4993
  {
5142
4994
  group: 'HTML',
5143
4995
  toolId: 7,
5144
4996
  name: 'UL',
5145
- tag: `<ul [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [itemTemplate]="inputs.itemTemplate" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>
4997
+ tag: `<ul [attr.id]="uniqueName" [databound]="inputs.datasource?.component" [itemTemplate]="inputs.itemTemplate" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>
5146
4998
  <li *ngFor="let li of (inputs.datasource?.component?.value?.resultInfo?.dato || (inputs.optionsCsv || '').split(','))">
5147
4999
  <ng-container *ngIf="inputs.displayFormula; else ulItemTemplate">{{getUlItemDisplayValue(inputs, li)}}</ng-container>
5148
5000
  <ng-template #ulItemTemplate>
@@ -5152,28 +5004,30 @@ class DesignerComponent {
5152
5004
  </ul>`,
5153
5005
  icon: 'pi pi-list',
5154
5006
  inputProps: (() => {
5155
- const ulProps = Object.assign({}, this.htmlItemTemplateProps, {
5007
+ const ulProps = {
5008
+ ...this.htmlItemTemplateProps,
5156
5009
  optionsCsv: { type: 'string', propertyCaption: 'Options CSV' },
5157
5010
  valueField: { type: 'dictionary', values: [''], propertyCaption: 'Value Field' },
5158
5011
  textField: { type: 'dictionary', values: [''], propertyCaption: 'Text Field' },
5159
5012
  displayFormula: { type: 'button', propertyCaption: 'Display Formula', hideCaption: true, callback: this.openUlDisplayFormulaEditor.bind(this) }
5160
- });
5013
+ };
5161
5014
  delete ulProps['bindingFunction'];
5162
5015
  return ulProps;
5163
5016
  })(),
5164
- inputs: Object.assign({}, this.bindableHtmlInputs, {
5017
+ inputs: {
5018
+ ...this.bindableHtmlInputs,
5165
5019
  optionsCsv: 'Item 1,Item 2,Item 3',
5166
5020
  valueField: '',
5167
5021
  textField: '',
5168
5022
  displayFormula: ''
5169
- }),
5023
+ },
5170
5024
  nestedComponents: []
5171
5025
  },
5172
5026
  {
5173
5027
  group: 'HTML',
5174
5028
  toolId: 8,
5175
5029
  name: 'BUTTON',
5176
- tag: `<button [attr.id]="uniqueName" (click)="inputs.clickCallback__fn(inputs.datasource?.component?.value?.resultInfo, inputs.datasource?.component?.value?.metaInfo, inputs, $event, inputs._wtoolbox)" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [itemTemplate]="inputs.itemTemplate" [clickCallback]="inputs.clickCallback" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}><ng-container *ngComponentOutlet="inputs.itemTemplateComponent; inputs: { rowData: inputs.templateData, metaInfo: inputs.datasource?.component?.value?.metaInfo, datasource: inputs.datasource?.component?.value }"></ng-container></button>`,
5030
+ tag: `<button [attr.id]="uniqueName" (click)="inputs.clickCallback__fn(inputs.datasource?.component?.value?.resultInfo, inputs.datasource?.component?.value?.metaInfo, inputs, $event, inputs._wtoolbox)" [databound]="inputs.datasource?.component" [bindingFunction]="inputs.bindingFunction" [itemTemplate]="inputs.itemTemplate" [clickCallback]="inputs.clickCallback" [inputs]="inputs" ngxDraggableDom="true" ngResizable [rzHandles] = "'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}><ng-container *ngComponentOutlet="inputs.itemTemplateComponent; inputs: { rowData: inputs.templateData, metaInfo: inputs.datasource?.component?.value?.metaInfo, datasource: inputs.datasource?.component?.value }"></ng-container></button>`,
5177
5031
  icon: 'pi pi-arrow-circle-down',
5178
5032
  inputProps: this.htmlButtonProps,
5179
5033
  inputs: this.bindableHtmlInputs
@@ -5182,58 +5036,64 @@ class DesignerComponent {
5182
5036
  group: 'HTML',
5183
5037
  toolId: 9,
5184
5038
  name: 'INPUT',
5185
- tag: `<input [attr.id]="uniqueName" [type]="inputs.inputType || 'text'" [placeholder]="inputs.placeholder" [readonly]="inputs.readonly" [disabled]="inputs.disabled" [value]="inputs.value" (input)="inputs.value=$any($event.target).value" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
5039
+ tag: `<input [attr.id]="uniqueName" [type]="inputs.inputType || 'text'" [placeholder]="inputs.placeholder" [readonly]="inputs.readonly" [disabled]="inputs.disabled" [value]="inputs.value" (input)="inputs.value=$any($event.target).value" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')} />`,
5186
5040
  icon: 'pi pi-pencil',
5187
- inputProps: Object.assign({}, this.htmlInputProperties, {
5041
+ inputProps: {
5042
+ ...this.htmlInputProperties,
5188
5043
  inputType: { type: 'dictionary', propertyCaption: 'Type', values: ['text', 'number', 'email', 'password', 'search', 'url'] },
5189
5044
  placeholder: { type: 'string', propertyCaption: 'Placeholder' },
5190
5045
  value: { type: 'string', propertyCaption: 'Value' },
5191
5046
  readonly: { type: 'boolean', propertyCaption: 'Readonly' },
5192
5047
  disabled: { type: 'boolean', propertyCaption: 'Disabled' }
5193
- }),
5194
- inputs: Object.assign({}, this.htmlInputs, {
5048
+ },
5049
+ inputs: {
5050
+ ...this.htmlInputs,
5195
5051
  inputType: 'text',
5196
5052
  placeholder: '',
5197
5053
  value: '',
5198
5054
  readonly: false,
5199
5055
  disabled: false,
5200
5056
  height: '32px'
5201
- })
5057
+ }
5202
5058
  },
5203
5059
  {
5204
5060
  group: 'HTML',
5205
5061
  toolId: 10,
5206
5062
  name: 'TEXTAREA',
5207
- tag: `<textarea [attr.id]="uniqueName" [placeholder]="inputs.placeholder" [readonly]="inputs.readonly" [disabled]="inputs.disabled" [rows]="inputs.rows" [value]="inputs.value" (input)="inputs.value=$any($event.target).value" ngxDraggableDom="true" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}></textarea>`,
5063
+ tag: `<textarea [attr.id]="uniqueName" [placeholder]="inputs.placeholder" [readonly]="inputs.readonly" [disabled]="inputs.disabled" [rows]="inputs.rows" [value]="inputs.value" (input)="inputs.value=$any($event.target).value" ngxDraggableDom="true" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}></textarea>`,
5208
5064
  icon: 'pi pi-align-left',
5209
- inputProps: Object.assign({}, this.htmlInputProperties, {
5065
+ inputProps: {
5066
+ ...this.htmlInputProperties,
5210
5067
  placeholder: { type: 'string', propertyCaption: 'Placeholder' },
5211
5068
  value: { type: 'txt_area', propertyCaption: 'Value' },
5212
5069
  rows: { type: 'string', propertyCaption: 'Rows' },
5213
5070
  readonly: { type: 'boolean', propertyCaption: 'Readonly' },
5214
5071
  disabled: { type: 'boolean', propertyCaption: 'Disabled' }
5215
- }),
5216
- inputs: Object.assign({}, this.htmlInputs, {
5072
+ },
5073
+ inputs: {
5074
+ ...this.htmlInputs,
5217
5075
  placeholder: '',
5218
5076
  value: '',
5219
5077
  rows: '4',
5220
5078
  readonly: false,
5221
5079
  disabled: false,
5222
5080
  height: '96px'
5223
- })
5081
+ }
5224
5082
  },
5225
5083
  {
5226
5084
  group: 'HTML',
5227
5085
  toolId: 11,
5228
5086
  name: 'CHECKBOX',
5229
- tag: `<label [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}><input type="checkbox" [checked]="inputs.checked" (change)="inputs.checked=$any($event.target).checked" [disabled]="inputs.disabled" /> {{inputs.label}}</label>`,
5087
+ tag: `<label [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}><input type="checkbox" [checked]="inputs.checked" (change)="inputs.checked=$any($event.target).checked" [disabled]="inputs.disabled" /> {{inputs.label}}</label>`,
5230
5088
  icon: 'pi pi-check-square',
5231
- inputProps: Object.assign({}, this.htmlInputProperties, {
5089
+ inputProps: {
5090
+ ...this.htmlInputProperties,
5232
5091
  label: { type: 'string', propertyCaption: 'Label' },
5233
5092
  checked: { type: 'boolean', propertyCaption: 'Checked' },
5234
5093
  disabled: { type: 'boolean', propertyCaption: 'Disabled' }
5235
- }),
5236
- inputs: Object.assign({}, this.htmlInputs, {
5094
+ },
5095
+ inputs: {
5096
+ ...this.htmlInputs,
5237
5097
  label: 'Checkbox',
5238
5098
  checked: false,
5239
5099
  disabled: false,
@@ -5244,16 +5104,17 @@ class DesignerComponent {
5244
5104
  borderRightStyle: 'none',
5245
5105
  borderBottomStyle: 'none',
5246
5106
  borderLeftStyle: 'none'
5247
- })
5107
+ }
5248
5108
  },
5249
5109
  {
5250
5110
  group: 'HTML',
5251
5111
  toolId: 12,
5252
5112
  name: 'SEPARATOR',
5253
- tag: `<hr [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
5113
+ tag: `<hr [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')} />`,
5254
5114
  icon: 'pi pi-minus',
5255
5115
  inputProps: this.htmlInputProperties,
5256
- inputs: Object.assign({}, this.htmlInputs, {
5116
+ inputs: {
5117
+ ...this.htmlInputs,
5257
5118
  width: '100%',
5258
5119
  height: '2px',
5259
5120
  // borderStyle: 'none',
@@ -5263,16 +5124,17 @@ class DesignerComponent {
5263
5124
  borderRightStyle: 'none',
5264
5125
  borderBottomStyle: 'none',
5265
5126
  borderLeftStyle: 'none'
5266
- })
5127
+ }
5267
5128
  },
5268
5129
  {
5269
5130
  group: 'HTML',
5270
5131
  toolId: 19,
5271
5132
  name: 'HR',
5272
- tag: `<hr [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
5133
+ tag: `<hr [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')} />`,
5273
5134
  icon: 'pi pi-minus',
5274
5135
  inputProps: this.htmlInputProperties,
5275
- inputs: Object.assign({}, this.htmlInputs, {
5136
+ inputs: {
5137
+ ...this.htmlInputs,
5276
5138
  width: '100%',
5277
5139
  height: '2px',
5278
5140
  // borderStyle: 'none',
@@ -5282,19 +5144,21 @@ class DesignerComponent {
5282
5144
  borderRightStyle: 'none',
5283
5145
  borderBottomStyle: 'none',
5284
5146
  borderLeftStyle: 'none'
5285
- })
5147
+ }
5286
5148
  },
5287
5149
  {
5288
5150
  group: 'HTML',
5289
5151
  toolId: 13,
5290
5152
  name: 'KPI',
5291
- tag: `<div [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}><div style="font-size:12px; opacity:.75;">{{inputs.caption}}</div><div style="font-size:28px; font-weight:700; line-height:1.2;">{{inputs.value}}</div></div>`,
5153
+ tag: `<div [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}><div style="font-size:12px; opacity:.75;">{{inputs.caption}}</div><div style="font-size:28px; font-weight:700; line-height:1.2;">{{inputs.value}}</div></div>`,
5292
5154
  icon: 'pi pi-chart-line',
5293
- inputProps: Object.assign({}, this.htmlInputProperties, {
5155
+ inputProps: {
5156
+ ...this.htmlInputProperties,
5294
5157
  caption: { type: 'string', propertyCaption: 'Caption' },
5295
5158
  value: { type: 'string', propertyCaption: 'Value' }
5296
- }),
5297
- inputs: Object.assign({}, this.htmlInputs, {
5159
+ },
5160
+ inputs: {
5161
+ ...this.htmlInputs,
5298
5162
  caption: 'KPI',
5299
5163
  value: '0',
5300
5164
  width: '180px',
@@ -5307,42 +5171,47 @@ class DesignerComponent {
5307
5171
  // borderStyle: 'solid',
5308
5172
  // borderWidth: '1px',
5309
5173
  // borderColor: '#d1d5db'
5310
- })
5174
+ }
5311
5175
  },
5312
5176
  {
5313
5177
  group: 'HTML',
5314
5178
  toolId: 14,
5315
5179
  name: 'DATE',
5316
- tag: `<input [attr.id]="uniqueName" type="date" [readonly]="inputs.readonly" [disabled]="inputs.disabled" [value]="inputs.value" (input)="inputs.value=$any($event.target).value" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
5180
+ tag: `<input [attr.id]="uniqueName" type="date" [readonly]="inputs.readonly" [disabled]="inputs.disabled" [value]="inputs.value" (input)="inputs.value=$any($event.target).value" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')} />`,
5317
5181
  icon: 'pi pi-calendar',
5318
- inputProps: Object.assign({}, this.htmlInputProperties, {
5182
+ inputProps: {
5183
+ ...this.htmlInputProperties,
5319
5184
  value: { type: 'string', propertyCaption: 'Value (yyyy-mm-dd)' },
5320
5185
  readonly: { type: 'boolean', propertyCaption: 'Readonly' },
5321
5186
  disabled: { type: 'boolean', propertyCaption: 'Disabled' }
5322
- }),
5323
- inputs: Object.assign({}, this.htmlInputs, {
5187
+ },
5188
+ inputs: {
5189
+ ...this.htmlInputs,
5324
5190
  value: '',
5325
5191
  readonly: false,
5326
5192
  disabled: false,
5327
5193
  width: '180px',
5328
5194
  height: '32px'
5329
- })
5195
+ }
5330
5196
  },
5331
5197
  {
5332
5198
  group: 'HTML',
5333
5199
  toolId: 15,
5334
5200
  name: 'SELECT',
5335
- tag: `<select [attr.id]="uniqueName" [disabled]="inputs.disabled" [value]="inputs.value" (change)="inputs.value=$any($event.target).value" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}><option *ngFor="let opt of (inputs.datasource?.component?.value?.resultInfo?.dato || (inputs.optionsCsv || '').split(','))" [value]="inputs.datasource?.component?.value?.resultInfo?.dato ? (opt?.[inputs.valueField] ?? '') : opt.trim()">{{getSelectOptionLabel(inputs, opt)}}</option></select>`,
5201
+ tag: `<select [attr.id]="uniqueName" [disabled]="inputs.disabled" [value]="inputs.value" (change)="inputs.value=$any($event.target).value" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}><option *ngFor="let opt of (inputs.datasource?.component?.value?.resultInfo?.dato || (inputs.optionsCsv || '').split(','))" [value]="inputs.datasource?.component?.value?.resultInfo?.dato ? (opt?.[inputs.valueField] ?? '') : opt.trim()">{{getSelectOptionLabel(inputs, opt)}}</option></select>`,
5336
5202
  icon: 'pi pi-list',
5337
- inputProps: Object.assign({}, this.htmlInputProperties, this.dsProperties, {
5203
+ inputProps: {
5204
+ ...this.htmlInputProperties,
5205
+ ...this.dsProperties,
5338
5206
  optionsCsv: { type: 'string', propertyCaption: 'Options CSV' },
5339
5207
  valueField: { type: 'dictionary', values: [''], propertyCaption: 'Value Field' },
5340
5208
  textField: { type: 'dictionary', values: [''], propertyCaption: 'Text Field' },
5341
5209
  displayFormula: { type: 'button', propertyCaption: 'Display Formula', hideCaption: true, callback: this.openSelectDisplayFormulaEditor.bind(this) },
5342
5210
  value: { type: 'string', propertyCaption: 'Selected Value' },
5343
5211
  disabled: { type: 'boolean', propertyCaption: 'Disabled' }
5344
- }),
5345
- inputs: Object.assign({}, this.htmlInputs, {
5212
+ },
5213
+ inputs: {
5214
+ ...this.htmlInputs,
5346
5215
  datasource: null,
5347
5216
  componentRef: null,
5348
5217
  optionsCsv: 'Option 1,Option 2,Option 3',
@@ -5353,15 +5222,17 @@ class DesignerComponent {
5353
5222
  disabled: false,
5354
5223
  width: '180px',
5355
5224
  height: '32px'
5356
- })
5225
+ }
5357
5226
  },
5358
5227
  {
5359
5228
  group: 'HTML',
5360
5229
  toolId: 16,
5361
5230
  name: 'MULTISELECT',
5362
- tag: `<select [attr.id]="uniqueName" multiple="true" [disabled]="inputs.disabled" [size]="inputs.size || 4" (change)="inputs.values = [].slice.call($any($event.target).selectedOptions || []).map(x => x.value)" ngxDraggableDom="true" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}><option *ngFor="let opt of (inputs.datasource?.component?.value?.resultInfo?.dato || (inputs.optionsCsv || '').split(','))" [value]="inputs.datasource?.component?.value?.resultInfo?.dato ? (opt?.[inputs.valueField] ?? '') : opt.trim()" [selected]="(inputs.values || []).includes((inputs.datasource?.component?.value?.resultInfo?.dato ? (opt?.[inputs.valueField] ?? '') : opt.trim()) + '')">{{getSelectOptionLabel(inputs, opt)}}</option></select>`,
5231
+ tag: `<select [attr.id]="uniqueName" multiple="true" [disabled]="inputs.disabled" [size]="inputs.size || 4" (change)="inputs.values = [].slice.call($any($event.target).selectedOptions || []).map(x => x.value)" ngxDraggableDom="true" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}><option *ngFor="let opt of (inputs.datasource?.component?.value?.resultInfo?.dato || (inputs.optionsCsv || '').split(','))" [value]="inputs.datasource?.component?.value?.resultInfo?.dato ? (opt?.[inputs.valueField] ?? '') : opt.trim()" [selected]="(inputs.values || []).includes((inputs.datasource?.component?.value?.resultInfo?.dato ? (opt?.[inputs.valueField] ?? '') : opt.trim()) + '')">{{getSelectOptionLabel(inputs, opt)}}</option></select>`,
5363
5232
  icon: 'pi pi-check-square',
5364
- inputProps: Object.assign({}, this.htmlInputProperties, this.dsProperties, {
5233
+ inputProps: {
5234
+ ...this.htmlInputProperties,
5235
+ ...this.dsProperties,
5365
5236
  optionsCsv: { type: 'string', propertyCaption: 'Options CSV' },
5366
5237
  valueField: { type: 'dictionary', values: [''], propertyCaption: 'Value Field' },
5367
5238
  textField: { type: 'dictionary', values: [''], propertyCaption: 'Text Field' },
@@ -5369,8 +5240,9 @@ class DesignerComponent {
5369
5240
  values: { type: 'txt_area', propertyCaption: 'Selected Values (array)' },
5370
5241
  size: { type: 'string', propertyCaption: 'Visible Rows' },
5371
5242
  disabled: { type: 'boolean', propertyCaption: 'Disabled' }
5372
- }),
5373
- inputs: Object.assign({}, this.htmlInputs, {
5243
+ },
5244
+ inputs: {
5245
+ ...this.htmlInputs,
5374
5246
  datasource: null,
5375
5247
  componentRef: null,
5376
5248
  optionsCsv: 'Option 1,Option 2,Option 3',
@@ -5382,7 +5254,7 @@ class DesignerComponent {
5382
5254
  disabled: false,
5383
5255
  width: '200px',
5384
5256
  height: '96px'
5385
- })
5257
+ }
5386
5258
  },
5387
5259
  {
5388
5260
  group: 'DATA',
@@ -5457,7 +5329,7 @@ class DesignerComponent {
5457
5329
  name: 'FILTERBAR',
5458
5330
  tag: `<wuic-filter-bar [attr.id]="uniqueName" [datasource]="inputs.datasource?.component"></wuic-filter-bar>`,
5459
5331
  icon: 'pi pi-filter',
5460
- inputProps: Object.assign({}, this.dsProperties),
5332
+ inputProps: { ...this.dsProperties },
5461
5333
  inputs: {
5462
5334
  datasource: null,
5463
5335
  componentRef: null
@@ -5469,10 +5341,11 @@ class DesignerComponent {
5469
5341
  name: 'PAGER',
5470
5342
  tag: `<wuic-pager [attr.id]="uniqueName" [datasource]="inputs.datasource?.component" [pageSize]="inputs.pageSize" [currentPage]="inputs.currentPage"></wuic-pager>`,
5471
5343
  icon: 'pi pi-angle-double-right',
5472
- inputProps: Object.assign({}, this.dsProperties, {
5344
+ inputProps: {
5345
+ ...this.dsProperties,
5473
5346
  pageSize: { type: 'string', propertyCaption: 'Page Size' },
5474
5347
  currentPage: { type: 'string', propertyCaption: 'Current Page' }
5475
- }),
5348
+ },
5476
5349
  inputs: {
5477
5350
  datasource: null,
5478
5351
  componentRef: null,
@@ -5484,12 +5357,12 @@ class DesignerComponent {
5484
5357
  group: 'CONTAINER',
5485
5358
  toolId: 1000,
5486
5359
  name: 'TABVIEW',
5487
- tag: `<p-tabView [attr.id]="uniqueName" [tabs]="nestedComponents" ngxDraggableDom="true" (moved)="onMoving($event, this)" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" ${this.htmlStyleString.replace('[ngStyle]', '[style]').replace(/0/g, 'inputs')}>
5360
+ tag: `<p-tabView [attr.id]="uniqueName" [tabs]="nestedComponents" ngxDraggableDom="true" (moved)="onMoving($event, this)" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" ${this.htmlStyleString.replace('[ngStyle]', '[style]').replaceAll('0', 'inputs')}>
5488
5361
  <wuic-dashboard [dashboardElements]="nestedComponents"></wuic-dashboard>
5489
5362
  </p-tabView>`,
5490
5363
  icon: 'pi pi-folder',
5491
5364
  inputProps: this.htmlInputProperties,
5492
- inputs: Object.assign({}, this.htmlInputs, { cssClass: [] }),
5365
+ inputs: { ...this.htmlInputs, cssClass: [] },
5493
5366
  nestedComponents: [],
5494
5367
  allowedChildren: ['TABPANEL']
5495
5368
  },
@@ -5515,8 +5388,8 @@ class DesignerComponent {
5515
5388
  group: 'CONTAINER',
5516
5389
  toolId: 1002,
5517
5390
  name: 'SPLITTER',
5518
- tag: `<p-splitter [attr.id]="uniqueName" [direction]="inputs.direction" (dragEnd)="inputs.resize?.($event, this)" ngxDraggableDom="true" (moved)="onMoving($event, this)" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>
5519
- <p-splitter-area *ngFor="let nestedArea of nestedComponents" [attr.id]="nestedArea.uniqueName" [size]="nestedArea.inputs.size" ${this.htmlStyleString.replace(/0/g, 'nestedArea.inputs')}>
5391
+ tag: `<p-splitter [attr.id]="uniqueName" [direction]="inputs.direction" (dragEnd)="inputs.resize?.($event, this)" ngxDraggableDom="true" (moved)="onMoving($event, this)" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>
5392
+ <p-splitter-area *ngFor="let nestedArea of nestedComponents" [attr.id]="nestedArea.uniqueName" [size]="nestedArea.inputs.size" ${this.htmlStyleString.replaceAll('0', 'nestedArea.inputs')}>
5520
5393
  <wuic-dashboard [dashboardElements]="nestedArea.nestedComponents"></wuic-dashboard>
5521
5394
  </p-splitter-area>
5522
5395
  </p-splitter>`,
@@ -5543,9 +5416,9 @@ class DesignerComponent {
5543
5416
  group: 'CONTAINER',
5544
5417
  toolId: 1004,
5545
5418
  name: 'ACCORDION',
5546
- tag: ` <cdk-accordion class="wuic-accordion-tab" [attr.id]="uniqueName" (dragEnd)="inputs.resize?.($event, this)" ngxDraggableDom="true" (moved)="onMoving($event, this)" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')}>
5419
+ tag: ` <cdk-accordion class="wuic-accordion-tab" [attr.id]="uniqueName" (dragEnd)="inputs.resize?.($event, this)" ngxDraggableDom="true" (moved)="onMoving($event, this)" ngResizable [rzHandles]="'se'" (rzResizing)="onResizing($event, this)" ${this.htmlStyleString.replaceAll('0', 'inputs')}>
5547
5420
  <cdk-accordion-item *ngFor="let nestedItem of nestedComponents" [attr.id]="nestedItem.uniqueName"
5548
- ${this.htmlStyleString.replace(/0/g, 'nestedItem.inputs')}>
5421
+ ${this.htmlStyleString.replaceAll('0', 'nestedItem.inputs')}>
5549
5422
  <div class="wuic-accordion-header">
5550
5423
  <a class="wuic-accordion-header-link" (click)="inputs.toggle?.($event, this, nestedItem)">{{nestedItem.inputs.header}}</a>
5551
5424
  </div>
@@ -5584,7 +5457,7 @@ class DesignerComponent {
5584
5457
  * oppure ricarica la lista dashboard salvate.
5585
5458
  */
5586
5459
  async ngOnInit() {
5587
- this.lastKnownHashRoute = String(window?.location?.hash || '');
5460
+ this.lastKnownHashRoute = String(globalThis?.location?.hash || '');
5588
5461
  this.refreshAvailableProjectCssClasses();
5589
5462
  // Registra handler chatbot per kind 'designer_inject': il chatbot
5590
5463
  // popover (globale, vedi rag-chatbot.component.ts onApplyAction)
@@ -5735,7 +5608,10 @@ class DesignerComponent {
5735
5608
  let topParent = null;
5736
5609
  const declared = (node && typeof node.parent_unique_name === 'string') ? node.parent_unique_name.trim() : '';
5737
5610
  if (declared) {
5738
- if (declared.startsWith('<') && declared.endsWith('>')) {
5611
+ if (this.isRootPlaceholder(declared)) {
5612
+ topParent = null; // alias esplicito del caso 3: va al ROOT
5613
+ }
5614
+ else if (declared.startsWith('<') && declared.endsWith('>')) {
5739
5615
  if (lastTopLevelInjected) {
5740
5616
  const resolved = this.resolveLayoutPlaceholder(declared, lastTopLevelInjected);
5741
5617
  if (resolved)
@@ -5764,7 +5640,7 @@ class DesignerComponent {
5764
5640
  // risolvibile dentro DATASOURCE__6" e i DATAREPEATER restano 0/3. Cosi'
5765
5641
  // tutti i nodi di un layout multi-cella risolvono contro lo stesso container.
5766
5642
  const PLACEHOLDER_CONTAINERS = ['TABLE', 'SPLITTER', 'ACCORDION', 'TABVIEW'];
5767
- if (PLACEHOLDER_CONTAINERS.indexOf(String(node.tool_name || '').toUpperCase()) >= 0) {
5643
+ if (PLACEHOLDER_CONTAINERS.includes(String(node.tool_name || '').toUpperCase())) {
5768
5644
  lastTopLevelInjected = this.findLastInjectedNode(String(node.tool_name || ''), topParent) || lastTopLevelInjected;
5769
5645
  }
5770
5646
  }
@@ -5812,13 +5688,13 @@ class DesignerComponent {
5812
5688
  // (es. backgroundColor non e' in inputs di default ma e' in
5813
5689
  // htmlInputProperties -> inputProps). Coerente col property panel
5814
5690
  // che legge inputProps per costruire l'UI.
5815
- if (!target.inputProps || !Object.prototype.hasOwnProperty.call(target.inputProps, propName)) {
5691
+ if (!target.inputProps || !Object.hasOwn(target.inputProps, propName)) {
5816
5692
  return { ok: false, message: `set_property: proprieta' '${propName}' non esposta su ${target.name} (${targetName})` };
5817
5693
  }
5818
5694
  // Inizializza inputs[propName] se non esiste, cosi' setValue() canonico
5819
5695
  // (o l'assign fallback) lo trova.
5820
- if (target.inputs && !Object.prototype.hasOwnProperty.call(target.inputs, propName)) {
5821
- target.inputs[propName] = undefined;
5696
+ if (target.inputs && !Object.hasOwn(target.inputs, propName)) {
5697
+ (target.inputs)[propName] = undefined;
5822
5698
  }
5823
5699
  // Trova la toolProp matching (chiave 'key' === propName) per delegare a setValue
5824
5700
  // canonico - applica converter, conditional, hooks specifici (datasource/select).
@@ -5835,8 +5711,8 @@ class DesignerComponent {
5835
5711
  // Fallback: la prop non e' nelle toolProps (raro - inputProps inconsistenti).
5836
5712
  // Assign diretto su inputs[prop], distinguendo BehaviorSubject vs primitivo.
5837
5713
  const cur = target.inputs[propName];
5838
- if (cur && typeof cur.next === 'function' && typeof cur.subscribe === 'function') {
5839
- cur.next(newValue);
5714
+ if (cur && typeof (cur).next === 'function' && typeof (cur).subscribe === 'function') {
5715
+ (cur).next(newValue);
5840
5716
  }
5841
5717
  else {
5842
5718
  target.inputs[propName] = newValue;
@@ -6074,16 +5950,16 @@ class DesignerComponent {
6074
5950
  continue;
6075
5951
  }
6076
5952
  // BehaviorSubject: per datasource estrai uniqueName dell'oggetto wrappato
6077
- if (v && typeof v.subscribe === 'function') {
6078
- const inner = v.value;
5953
+ if (v && typeof (v).subscribe === 'function') {
5954
+ const inner = (v).value;
6079
5955
  const wrappedName = inner?.uniqueName || inner?.component?.uniqueName;
6080
5956
  if (wrappedName)
6081
5957
  parts.push(`${key}=${wrappedName}`);
6082
5958
  continue;
6083
5959
  }
6084
5960
  // Oggetto datasource (dropped-component-list, sync)
6085
- if (v && typeof v === 'object' && v.uniqueName) {
6086
- parts.push(`${key}=${v.uniqueName}`);
5961
+ if (v && typeof v === 'object' && (v).uniqueName) {
5962
+ parts.push(`${key}=${(v).uniqueName}`);
6087
5963
  continue;
6088
5964
  }
6089
5965
  // Primitivi: includi solo se DIVERSI dal default del template
@@ -6290,7 +6166,7 @@ class DesignerComponent {
6290
6166
  if (template.inputs) {
6291
6167
  // Rimuovi le chiavi che node.inputs aveva aggiunto e non c'erano nel backup
6292
6168
  for (const k of Object.keys(template.inputs)) {
6293
- if (!Object.prototype.hasOwnProperty.call(inputsBackup, k)) {
6169
+ if (!Object.hasOwn(inputsBackup, k)) {
6294
6170
  delete template.inputs[k];
6295
6171
  }
6296
6172
  }
@@ -6320,7 +6196,7 @@ class DesignerComponent {
6320
6196
  const rowPct = `${Math.floor(10000 / childCount) / 100}%`;
6321
6197
  for (const tr of justInjected.nestedComponents) {
6322
6198
  if (tr?.inputs)
6323
- tr.inputs['height'] = rowPct;
6199
+ (tr.inputs)['height'] = rowPct;
6324
6200
  }
6325
6201
  }
6326
6202
  else if (toolName === 'SPLITTER') {
@@ -6328,7 +6204,7 @@ class DesignerComponent {
6328
6204
  const sizePct = Math.floor(10000 / childCount) / 100;
6329
6205
  for (const area of justInjected.nestedComponents) {
6330
6206
  if (area?.inputs)
6331
- area.inputs['size'] = sizePct;
6207
+ (area.inputs)['size'] = sizePct;
6332
6208
  }
6333
6209
  }
6334
6210
  }
@@ -6347,7 +6223,7 @@ class DesignerComponent {
6347
6223
  // 2. il target referenziato (es. DATASOURCE_15) deve esistere gia'
6348
6224
  // in flattenedDashboardElements (= iniettato in nodo precedente
6349
6225
  // del layout o gia' nel canvas).
6350
- if (justInjected && justInjected.inputs && droppedBindingKeys.length > 0 && node.inputs) {
6226
+ if (justInjected?.inputs && droppedBindingKeys.length > 0 && node.inputs) {
6351
6227
  for (const key of droppedBindingKeys) {
6352
6228
  const propDef = template.inputProps?.[key];
6353
6229
  if (!propDef)
@@ -6358,7 +6234,7 @@ class DesignerComponent {
6358
6234
  // Se gia' oggetto (LLM mandasse direttamente {uniqueName,component})
6359
6235
  // o BehaviorSubject -> pass-through. Solo stringhe vengono risolte.
6360
6236
  if (typeof raw !== 'string') {
6361
- justInjected.inputs[key] = raw;
6237
+ (justInjected.inputs)[key] = raw;
6362
6238
  continue;
6363
6239
  }
6364
6240
  const resolved = (raw.startsWith('<') && raw.endsWith('>'))
@@ -6425,7 +6301,7 @@ class DesignerComponent {
6425
6301
  }
6426
6302
  catch { /* subs collection non disponibile, sub continuera' a vivere col designer */ }
6427
6303
  }
6428
- justInjected.inputs[key] = {
6304
+ (justInjected.inputs)[key] = {
6429
6305
  uniqueName: refElement.uniqueName,
6430
6306
  [asyncPath]: compBs
6431
6307
  };
@@ -6439,8 +6315,8 @@ class DesignerComponent {
6439
6315
  // non sa quali colonne mostrare e la grid resta vuota anche con
6440
6316
  // datasource bindato correttamente.
6441
6317
  if (justInjected && toolName === 'DATAREPEATER' && justInjected.inputs) {
6442
- const ds = justInjected.inputs['datasource'];
6443
- const action = this.getRepeaterAction(justInjected) || justInjected.inputs['action'] || 'list';
6318
+ const ds = (justInjected.inputs)['datasource'];
6319
+ const action = this.getRepeaterAction(justInjected) || (justInjected.inputs)['action'] || 'list';
6444
6320
  if (ds) {
6445
6321
  try {
6446
6322
  this.propertyTreeBuilder(action, justInjected.inputs);
@@ -6487,7 +6363,10 @@ class DesignerComponent {
6487
6363
  let childParent = injectedUniqueName;
6488
6364
  const declared = (ch && typeof ch.parent_unique_name === 'string') ? ch.parent_unique_name.trim() : '';
6489
6365
  if (declared) {
6490
- if (declared.startsWith('<') && declared.endsWith('>')) {
6366
+ if (this.isRootPlaceholder(declared)) {
6367
+ childParent = null; // alias esplicito del ROOT anche in ricorsione
6368
+ }
6369
+ else if (declared.startsWith('<') && declared.endsWith('>')) {
6491
6370
  // Placeholder semantico: risolvi dentro justInjected
6492
6371
  const resolved = this.resolveLayoutPlaceholder(declared, justInjected);
6493
6372
  if (resolved)
@@ -6523,10 +6402,24 @@ class DesignerComponent {
6523
6402
  * Ritorna l'uniqueName del nodo risolto, o `null` se il pattern non matcha
6524
6403
  * o l'index e' out-of-bounds (es. <TD-3> in tabella 2x2).
6525
6404
  */
6405
+ /**
6406
+ * `<ROOT>` e' l'alias ESPLICITO del caso 3 ("null/missing: va al ROOT"), non un
6407
+ * placeholder container-relative. Senza questo riconoscimento finiva nel ramo
6408
+ * angle-bracket e `resolveLayoutPlaceholder` lo scartava (`'ROOT'.split('-')`
6409
+ * da un solo elemento -> `null`), quindi era IRRISOLVIBILE anche con un
6410
+ * container iniettato prima: un `<ROOT>` faceva abortire l'intero inject.
6411
+ * Caso reale: "aggiungi un bottone Esporta nel canvas" su canvas vuoto.
6412
+ * Nota: se il token arrivasse fino a `drop()` il nodo verrebbe piazzato
6413
+ * correttamente al root (destination = dashboardElements), quindi non e' un
6414
+ * vincolo del canvas — era solo questo ramo a trasformarlo in un rifiuto.
6415
+ */
6416
+ isRootPlaceholder(declared) {
6417
+ return /^<\s*ROOT\s*>$/i.test((declared || '').trim());
6418
+ }
6526
6419
  resolveLayoutPlaceholder(placeholder, parentNode) {
6527
6420
  if (!placeholder || !parentNode)
6528
6421
  return null;
6529
- const inner = placeholder.replace(/^<|>$/g, '').trim();
6422
+ const inner = placeholder.replaceAll(/^<|>$/g, '').trim();
6530
6423
  const parts = inner.split('-');
6531
6424
  if (parts.length < 2)
6532
6425
  return null;
@@ -6535,7 +6428,7 @@ class DesignerComponent {
6535
6428
  if (tag === 'TD') {
6536
6429
  // <TD-N> singolo index OR <TD-R-C> riga/colonna
6537
6430
  if (parts.length === 2) {
6538
- const n = parseInt(parts[1], 10);
6431
+ const n = Number.parseInt(parts[1], 10);
6539
6432
  if (!Number.isFinite(n))
6540
6433
  return null;
6541
6434
  // Row-major lookup: TR[i].TD[j]
@@ -6550,8 +6443,8 @@ class DesignerComponent {
6550
6443
  return null;
6551
6444
  }
6552
6445
  if (parts.length === 3) {
6553
- const r = parseInt(parts[1], 10);
6554
- const c = parseInt(parts[2], 10);
6446
+ const r = Number.parseInt(parts[1], 10);
6447
+ const c = Number.parseInt(parts[2], 10);
6555
6448
  if (!Number.isFinite(r) || !Number.isFinite(c))
6556
6449
  return null;
6557
6450
  const tr = nested[r];
@@ -6563,25 +6456,25 @@ class DesignerComponent {
6563
6456
  return null;
6564
6457
  }
6565
6458
  if (tag === 'TR') {
6566
- const n = parseInt(parts[1], 10);
6459
+ const n = Number.parseInt(parts[1], 10);
6567
6460
  if (!Number.isFinite(n))
6568
6461
  return null;
6569
6462
  return nested[n]?.uniqueName || null;
6570
6463
  }
6571
6464
  if (tag === 'SPLITTER' && parts[1].toUpperCase() === 'AREA') {
6572
- const n = parseInt(parts[2], 10);
6465
+ const n = Number.parseInt(parts[2], 10);
6573
6466
  if (!Number.isFinite(n))
6574
6467
  return null;
6575
6468
  return nested[n]?.uniqueName || null;
6576
6469
  }
6577
6470
  if (tag === 'ACCORDION' && parts[1].toUpperCase() === 'AREA') {
6578
- const n = parseInt(parts[2], 10);
6471
+ const n = Number.parseInt(parts[2], 10);
6579
6472
  if (!Number.isFinite(n))
6580
6473
  return null;
6581
6474
  return nested[n]?.uniqueName || null;
6582
6475
  }
6583
6476
  if (tag === 'TABPANEL') {
6584
- const n = parseInt(parts[1], 10);
6477
+ const n = Number.parseInt(parts[1], 10);
6585
6478
  if (!Number.isFinite(n))
6586
6479
  return null;
6587
6480
  return nested[n]?.uniqueName || null;
@@ -6623,12 +6516,12 @@ class DesignerComponent {
6623
6516
  const trim = placeholder.trim();
6624
6517
  if (!trim.startsWith('<') || !trim.endsWith('>'))
6625
6518
  return null;
6626
- const inner = trim.replace(/^<|>$/g, '').trim();
6627
- const m = inner.match(/^([A-Za-z][A-Za-z0-9_-]*)-(\d+)$/);
6519
+ const inner = trim.replaceAll(/^<|>$/g, '').trim();
6520
+ const m = /^([A-Za-z][A-Za-z0-9_-]*)-(\d+)$/.exec(inner);
6628
6521
  if (!m)
6629
6522
  return null;
6630
6523
  const targetName = m[1].toUpperCase();
6631
- const targetIdx = parseInt(m[2], 10);
6524
+ const targetIdx = Number.parseInt(m[2], 10);
6632
6525
  if (!Number.isFinite(targetIdx) || targetIdx < 0)
6633
6526
  return null;
6634
6527
  const matching = (this.flattenedDashboardElements || [])
@@ -6668,7 +6561,7 @@ class DesignerComponent {
6668
6561
  */
6669
6562
  _designerGestureMouseUp;
6670
6563
  async onWindowHashChange() {
6671
- const nextHash = String(window?.location?.hash || '');
6564
+ const nextHash = String(globalThis?.location?.hash || '');
6672
6565
  const previousHash = this.lastKnownHashRoute;
6673
6566
  if (this.suppressNextHashGuard) {
6674
6567
  this.lastKnownHashRoute = nextHash;
@@ -6687,10 +6580,10 @@ class DesignerComponent {
6687
6580
  return;
6688
6581
  }
6689
6582
  this.suppressNextHashGuard = true;
6690
- window.location.hash = previousHash || '#/';
6583
+ globalThis.location.hash = previousHash || '#/';
6691
6584
  setTimeout(() => {
6692
6585
  this.suppressNextHashGuard = false;
6693
- this.lastKnownHashRoute = String(window?.location?.hash || '');
6586
+ this.lastKnownHashRoute = String(globalThis?.location?.hash || '');
6694
6587
  }, 0);
6695
6588
  }
6696
6589
  onWindowBeforeUnload(event) {
@@ -6801,14 +6694,14 @@ class DesignerComponent {
6801
6694
  }
6802
6695
  try {
6803
6696
  const urlObj = new URL(href, document.baseURI);
6804
- const cleanedPath = String(urlObj.pathname || '').replace(/\\/g, '/');
6697
+ const cleanedPath = String(urlObj.pathname || '').replaceAll('\\', '/');
6805
6698
  const assetsIdx = cleanedPath.toLowerCase().indexOf('/assets/');
6806
6699
  if (assetsIdx >= 0) {
6807
6700
  // Keep relative assets path (e.g. assets/my-dash/file.css) to avoid collisions.
6808
6701
  return cleanedPath.substring(assetsIdx + 1);
6809
6702
  }
6810
6703
  const parts = cleanedPath.split('/');
6811
- return parts[parts.length - 1] || cleanedPath;
6704
+ return parts.at(-1) || cleanedPath;
6812
6705
  }
6813
6706
  catch {
6814
6707
  return href;
@@ -7123,7 +7016,7 @@ class DesignerComponent {
7123
7016
  * Normalizza un path CSS in formato slash `/` e trim.
7124
7017
  */
7125
7018
  normalizeSheetPath(path) {
7126
- return String(path || '').trim().replace(/\\/g, '/');
7019
+ return String(path || '').trim().replaceAll('\\', '/');
7127
7020
  }
7128
7021
  /**
7129
7022
  * Normalizza il payload foglio CSS (path, selector, class names, key/value style)
@@ -7185,7 +7078,7 @@ class DesignerComponent {
7185
7078
  return WtoolboxService.appSettings?.file_path;
7186
7079
  }
7187
7080
  catch {
7188
- return window.location.origin;
7081
+ return globalThis.location.origin;
7189
7082
  }
7190
7083
  };
7191
7084
  const resolveBackendStaticBaseUrl = () => {
@@ -7194,7 +7087,7 @@ class DesignerComponent {
7194
7087
  if (!raw) {
7195
7088
  return '';
7196
7089
  }
7197
- const url = new URL(raw, window.location.origin);
7090
+ const url = new URL(raw, globalThis.location.origin);
7198
7091
  const apiIndex = url.pathname.toLowerCase().indexOf('/api/');
7199
7092
  let staticPath = apiIndex >= 0 ? url.pathname.substring(0, apiIndex) : url.pathname;
7200
7093
  if (!staticPath.endsWith('/')) {
@@ -7207,7 +7100,7 @@ class DesignerComponent {
7207
7100
  }
7208
7101
  };
7209
7102
  const buildCssHref = (baseUrl, relativePath) => {
7210
- const baseUrlObj = new URL(baseUrl || window.location.origin, window.location.origin);
7103
+ const baseUrlObj = new URL(baseUrl || globalThis.location.origin, globalThis.location.origin);
7211
7104
  const basePath = baseUrlObj.pathname.toLowerCase();
7212
7105
  let resolvedRelativePath = relativePath;
7213
7106
  if (basePath.endsWith('/assets/') && resolvedRelativePath.toLowerCase().startsWith('assets/')) {
@@ -7419,6 +7312,8 @@ class DesignerComponent {
7419
7312
  this.applyHistorySnapshot(target, false);
7420
7313
  }
7421
7314
  catch (err) {
7315
+ // Snapshot apply failed — best-effort: keep the designer alive, the
7316
+ // history stacks are already consistent (target popped, previous pushed).
7422
7317
  }
7423
7318
  }
7424
7319
  /**
@@ -7567,8 +7462,8 @@ class DesignerComponent {
7567
7462
  }
7568
7463
  if (key === 'c') {
7569
7464
  // Non intercettare Ctrl+C se l'utente sta copiando una selezione di testo.
7570
- const textSelection = (typeof window !== 'undefined' && window.getSelection)
7571
- ? String(window.getSelection() || '')
7465
+ const textSelection = (globalThis.window !== undefined && globalThis.getSelection)
7466
+ ? String(globalThis.getSelection() || '')
7572
7467
  : '';
7573
7468
  if (textSelection) {
7574
7469
  return;
@@ -7610,9 +7505,7 @@ class DesignerComponent {
7610
7505
  * via touch su designer.
7611
7506
  */
7612
7507
  onWindowTouchend() {
7613
- if (!this.finalizePendingColorHistory()) {
7614
- this.commitHistoryAfterDesignerGestureIfNeeded();
7615
- }
7508
+ this.onWindowMouseup();
7616
7509
  }
7617
7510
  /**
7618
7511
  * Se l'utente ha appena terminato un drag/resize di un elemento del designer
@@ -7885,9 +7778,11 @@ class DesignerComponent {
7885
7778
  */
7886
7779
  getDropPositionRelativeTo(event, refEl) {
7887
7780
  const rect = refEl ? refEl.getBoundingClientRect() : null;
7888
- const oe = (event && event.originalEvent) ? event.originalEvent : event;
7889
- const cx = (typeof oe?.clientX === 'number') ? oe.clientX : (typeof event?.clientX === 'number' ? event.clientX : null);
7890
- const cy = (typeof oe?.clientY === 'number') ? oe.clientY : (typeof event?.clientY === 'number' ? event.clientY : null);
7781
+ const oe = (event?.originalEvent) ? event.originalEvent : event;
7782
+ const fallbackCx = (typeof event?.clientX === 'number') ? event.clientX : null;
7783
+ const fallbackCy = (typeof event?.clientY === 'number') ? event.clientY : null;
7784
+ const cx = (typeof oe?.clientX === 'number') ? oe.clientX : fallbackCx;
7785
+ const cy = (typeof oe?.clientY === 'number') ? oe.clientY : fallbackCy;
7891
7786
  if (!rect || cx === null || cy === null) {
7892
7787
  return { left: 0, top: 0 };
7893
7788
  }
@@ -7957,8 +7852,8 @@ class DesignerComponent {
7957
7852
  let sx = 1, sy = 0, kx = 0, ky = 1, tx = 0, ty = 0;
7958
7853
  const m = String(tool.inputs['transform'] || '').match(/matrix\(([^)]+)\)/);
7959
7854
  if (m) {
7960
- const p = m[1].split(',').map((x) => parseFloat(x));
7961
- if (p.length >= 6 && p.every((n) => !isNaN(n))) {
7855
+ const p = m[1].split(',').map((x) => Number.parseFloat(x));
7856
+ if (p.length >= 6 && p.every((n) => !Number.isNaN(Number(n)))) {
7962
7857
  [sx, sy, kx, ky, tx, ty] = p;
7963
7858
  }
7964
7859
  }
@@ -7981,10 +7876,10 @@ class DesignerComponent {
7981
7876
  }
7982
7877
  let scaleX = 1, skewY = 0, skewX = 0, scaleY = 1, tx = 0, ty = 0;
7983
7878
  const cur = String(el.inputs['transform'] || '');
7984
- const m = cur.match(/matrix\(([^)]+)\)/);
7879
+ const m = /matrix\(([^)]+)\)/.exec(cur);
7985
7880
  if (m) {
7986
- const parts = m[1].split(',').map((x) => parseFloat(x));
7987
- if (parts.length >= 6 && parts.every((n) => !isNaN(n))) {
7881
+ const parts = m[1].split(',').map((x) => Number.parseFloat(x));
7882
+ if (parts.length >= 6 && parts.every((n) => !Number.isNaN(Number(n)))) {
7988
7883
  [scaleX, skewY, skewX, scaleY, tx, ty] = parts;
7989
7884
  }
7990
7885
  }
@@ -8141,7 +8036,7 @@ class DesignerComponent {
8141
8036
  return undefined;
8142
8037
  };
8143
8038
  const res = walk(this.dashboardElements || []);
8144
- return res === undefined ? null : res;
8039
+ return res ?? null;
8145
8040
  }
8146
8041
  /**
8147
8042
  * Copia l'elemento selezionato (o `ctxElement`) nel clipboard interno.
@@ -8248,8 +8143,8 @@ class DesignerComponent {
8248
8143
  }
8249
8144
  catch { /* keep raw */ }
8250
8145
  const routeSlug = String(this.currentDashboardRoute || 'dashboard')
8251
- .replace(/[^a-zA-Z0-9._-]+/g, '_')
8252
- .replace(/^_+|_+$/g, '') || 'dashboard';
8146
+ .replaceAll(/[^a-zA-Z0-9._-]+/g, '_')
8147
+ .replaceAll(/^_+|_+$/g, '') || 'dashboard';
8253
8148
  const fileName = `${routeSlug}.dashboard.json`;
8254
8149
  const blob = new Blob([pretty], { type: 'application/json' });
8255
8150
  const url = URL.createObjectURL(blob);
@@ -8258,7 +8153,7 @@ class DesignerComponent {
8258
8153
  anchor.download = fileName;
8259
8154
  document.body.appendChild(anchor);
8260
8155
  anchor.click();
8261
- document.body.removeChild(anchor);
8156
+ anchor.remove();
8262
8157
  setTimeout(() => URL.revokeObjectURL(url), 0);
8263
8158
  WtoolboxService.messageNotificationService.add({
8264
8159
  severity: 'success',
@@ -8285,8 +8180,8 @@ class DesignerComponent {
8285
8180
  input.accept = 'application/json,.json';
8286
8181
  input.style.display = 'none';
8287
8182
  input.addEventListener('change', () => {
8288
- const file = input.files && input.files[0];
8289
- document.body.removeChild(input);
8183
+ const file = input.files?.[0];
8184
+ input.remove();
8290
8185
  if (!file) {
8291
8186
  return;
8292
8187
  }
@@ -8325,11 +8220,9 @@ class DesignerComponent {
8325
8220
  return;
8326
8221
  }
8327
8222
  // Accetta sia l'array di elementi top-level sia il wrapper {elements|dashboardElements}
8328
- const elements = Array.isArray(parsed)
8329
- ? parsed
8330
- : (Array.isArray(parsed?.elements)
8331
- ? parsed.elements
8332
- : (Array.isArray(parsed?.dashboardElements) ? parsed.dashboardElements : null));
8223
+ const dashboardElements = Array.isArray(parsed?.dashboardElements) ? parsed.dashboardElements : null;
8224
+ const wrappedElements = Array.isArray(parsed?.elements) ? parsed.elements : dashboardElements;
8225
+ const elements = Array.isArray(parsed) ? parsed : wrappedElements;
8333
8226
  if (!elements) {
8334
8227
  WtoolboxService.messageNotificationService.add({
8335
8228
  severity: 'error',
@@ -8436,8 +8329,8 @@ class DesignerComponent {
8436
8329
  this.rubber = { startClientX: event.clientX, startClientY: event.clientY };
8437
8330
  this.rubberBandVisible = true;
8438
8331
  this.updateRubberBandStyle(event.clientX, event.clientY);
8439
- window.addEventListener('mousemove', this.boundRubberMove);
8440
- window.addEventListener('mouseup', this.boundRubberUp);
8332
+ globalThis.addEventListener('mousemove', this.boundRubberMove);
8333
+ globalThis.addEventListener('mouseup', this.boundRubberUp);
8441
8334
  this.cd.detectChanges();
8442
8335
  }
8443
8336
  /** true se il target risale fino al canvas senza attraversare un elemento designer (id con '__'). */
@@ -8445,7 +8338,7 @@ class DesignerComponent {
8445
8338
  let node = target;
8446
8339
  while (node && node !== canvasEl) {
8447
8340
  const id = node.getAttribute ? (node.getAttribute('id') || '') : '';
8448
- if (id.indexOf('__') > -1) {
8341
+ if (id.includes('__')) {
8449
8342
  return false;
8450
8343
  }
8451
8344
  node = node.parentElement;
@@ -8477,8 +8370,8 @@ class DesignerComponent {
8477
8370
  };
8478
8371
  }
8479
8372
  onRubberUp(event) {
8480
- window.removeEventListener('mousemove', this.boundRubberMove);
8481
- window.removeEventListener('mouseup', this.boundRubberUp);
8373
+ globalThis.removeEventListener('mousemove', this.boundRubberMove);
8374
+ globalThis.removeEventListener('mouseup', this.boundRubberUp);
8482
8375
  const rubber = this.rubber;
8483
8376
  this.rubber = null;
8484
8377
  this.rubberBandVisible = false;
@@ -8542,8 +8435,8 @@ class DesignerComponent {
8542
8435
  let scaleX = 1, skewY = 0, skewX = 0, scaleY = 1, tx = 0, ty = 0;
8543
8436
  const m = String(el.inputs['transform'] || '').match(/matrix\(([^)]+)\)/);
8544
8437
  if (m) {
8545
- const p = m[1].split(',').map((x) => parseFloat(x));
8546
- if (p.length >= 6 && p.every((n) => !isNaN(n))) {
8438
+ const p = m[1].split(',').map((x) => Number.parseFloat(x));
8439
+ if (p.length >= 6 && p.every((n) => !Number.isNaN(Number(n)))) {
8547
8440
  [scaleX, skewY, skewX, scaleY, tx, ty] = p;
8548
8441
  }
8549
8442
  }
@@ -8816,7 +8709,9 @@ class DesignerComponent {
8816
8709
  let boardcontent = null;
8817
8710
  try {
8818
8711
  const result = await this.dataSrv.loadDashboard({ user_id: this.userInfo.getuserInfo().user_id, dashRoute: route });
8819
- const rows = Array.isArray(result) ? result : (Array.isArray(result?.results) ? result.results : (result ? [result] : []));
8712
+ const fallbackRows = result ? [result] : [];
8713
+ const resultRows = Array.isArray(result?.results) ? result.results : fallbackRows;
8714
+ const rows = Array.isArray(result) ? result : resultRows;
8820
8715
  boardcontent = rows?.[0]?.boardcontent ?? null;
8821
8716
  }
8822
8717
  catch {
@@ -8861,8 +8756,15 @@ class DesignerComponent {
8861
8756
  imported = null;
8862
8757
  }
8863
8758
  if (!Array.isArray(imported)) {
8864
- imported = Array.isArray(imported?.dashboardElements) ? imported.dashboardElements
8865
- : Array.isArray(imported?.elements) ? imported.elements : [];
8759
+ if (Array.isArray(imported?.dashboardElements)) {
8760
+ imported = imported.dashboardElements;
8761
+ }
8762
+ else if (Array.isArray(imported?.elements)) {
8763
+ imported = imported.elements;
8764
+ }
8765
+ else {
8766
+ imported = [];
8767
+ }
8866
8768
  }
8867
8769
  if (!imported.length) {
8868
8770
  WtoolboxService.messageNotificationService.add({ severity: 'warn', summary: this.t('designer.import.title', 'Import'), detail: this.t('designer.import.empty', 'Contenuto vuoto o non valido') });
@@ -8891,7 +8793,7 @@ class DesignerComponent {
8891
8793
  if (oldName) {
8892
8794
  nameMap.set(oldName, newName);
8893
8795
  }
8894
- if (!isNaN(oldId)) {
8796
+ if (!Number.isNaN(Number(oldId))) {
8895
8797
  idMap.set(oldId, newId);
8896
8798
  }
8897
8799
  el.componentId = newId;
@@ -9285,7 +9187,7 @@ class DesignerComponent {
9285
9187
  if (value instanceof BehaviorSubject) {
9286
9188
  return unwrapEntry(value.value);
9287
9189
  }
9288
- if (value && typeof value === 'object' && Object.prototype.hasOwnProperty.call(value, 'value')) {
9190
+ if (value && typeof value === 'object' && Object.hasOwn(value, 'value')) {
9289
9191
  return unwrapEntry(value.value);
9290
9192
  }
9291
9193
  if (Array.isArray(value)) {
@@ -9349,7 +9251,7 @@ class DesignerComponent {
9349
9251
  if (idValue === undefined || idValue === null || idValue === '') {
9350
9252
  if (!isDeleted && allowMissingIdInsert) {
9351
9253
  const temporaryId = nextTemporaryNumericId(nextList, idKey);
9352
- const rowWithId = Object.assign({}, originalRow || {}, row, { [idKey]: temporaryId });
9254
+ const rowWithId = { ...originalRow, ...row, [idKey]: temporaryId };
9353
9255
  nextList.push(rowWithId);
9354
9256
  }
9355
9257
  return nextList;
@@ -9362,10 +9264,10 @@ class DesignerComponent {
9362
9264
  return nextList;
9363
9265
  }
9364
9266
  if (idx >= 0) {
9365
- nextList[idx] = Object.assign({}, nextList[idx], row);
9267
+ nextList[idx] = { ...nextList[idx], ...row };
9366
9268
  }
9367
9269
  else {
9368
- nextList.push(Object.assign({}, originalRow || {}, row));
9270
+ nextList.push({ ...originalRow, ...row });
9369
9271
  }
9370
9272
  return nextList;
9371
9273
  };
@@ -9397,7 +9299,7 @@ class DesignerComponent {
9397
9299
  else if (normalizedEditorKey === 'CG_Id') {
9398
9300
  const tableMetadata = hostDatasource?.metaInfo?.tableMetadata;
9399
9301
  if (tableMetadata) {
9400
- const normalizedConditionGroup = Object.assign({}, normalizedOriginal || {}, normalizedData || {});
9302
+ const normalizedConditionGroup = { ...normalizedOriginal, ...normalizedData };
9401
9303
  if (normalizedConditionGroup.CG_Id === undefined || normalizedConditionGroup.CG_Id === null || normalizedConditionGroup.CG_Id === '') {
9402
9304
  const fallbackGroupId = normalizedConditionGroup.__guid ?? normalizedOriginal?.__guid;
9403
9305
  if (fallbackGroupId !== undefined && fallbackGroupId !== null && String(fallbackGroupId) !== '') {
@@ -9422,7 +9324,11 @@ class DesignerComponent {
9422
9324
  const linkedGroup = hasGroupId
9423
9325
  ? conditionGroups.find((row) => String(row?.CG_Id ?? row?.FK_CG_Id ?? row?.__guid ?? '') === String(rawGroupId))
9424
9326
  : null;
9425
- const normalizedConditionItem = Object.assign({}, linkedGroup || {}, normalizedOriginal || {}, normalizedData || {});
9327
+ const normalizedConditionItem = {
9328
+ ...(linkedGroup || {}),
9329
+ ...(normalizedOriginal || {}),
9330
+ ...(normalizedData || {})
9331
+ };
9426
9332
  if (hasGroupId) {
9427
9333
  normalizedConditionItem.CG_Id = rawGroupId;
9428
9334
  }
@@ -9450,7 +9356,7 @@ class DesignerComponent {
9450
9356
  WtoolboxService.errorHandler?.handleError(new Error('FK_CG_Id obbligatorio: impossibile salvare Condition Action Group senza gruppo condizione.'));
9451
9357
  return;
9452
9358
  }
9453
- const normalizedActionGroup = Object.assign({}, normalizedOriginal || {}, normalizedData || {});
9359
+ const normalizedActionGroup = { ...normalizedOriginal, ...normalizedData };
9454
9360
  if (hasGroupId) {
9455
9361
  normalizedActionGroup.FK_CG_Id = rawGroupId;
9456
9362
  }
@@ -9490,7 +9396,7 @@ class DesignerComponent {
9490
9396
  WtoolboxService.errorHandler?.handleError(new Error('FK_CAG_Id obbligatorio: impossibile salvare Condition Action Item senza gruppo azione condizione.'));
9491
9397
  return;
9492
9398
  }
9493
- const normalizedActionItem = Object.assign({}, normalizedOriginal || {}, normalizedData || {});
9399
+ const normalizedActionItem = { ...normalizedOriginal, ...normalizedData };
9494
9400
  if (hasActionGroupId) {
9495
9401
  normalizedActionItem.FK_CAG_Id = rawActionGroupId;
9496
9402
  if (normalizedActionItem.CAG_Id === undefined || normalizedActionItem.CAG_Id === null || normalizedActionItem.CAG_Id === '') {
@@ -9553,7 +9459,7 @@ class DesignerComponent {
9553
9459
  publishDatasource(this['datasourceTabelle']);
9554
9460
  if (hostDatasource?.resultInfo?.current) {
9555
9461
  Object.keys(hostDatasource.resultInfo.current).forEach((field) => {
9556
- if (hostTableMetadata && Object.prototype.hasOwnProperty.call(hostTableMetadata, field) && hostDatasource.resultInfo.current[field]?.next) {
9462
+ if (hostTableMetadata && Object.hasOwn(hostTableMetadata, field) && hostDatasource.resultInfo.current[field]?.next) {
9557
9463
  hostDatasource.resultInfo.current[field].next(hostTableMetadata[field]);
9558
9464
  }
9559
9465
  });
@@ -9770,18 +9676,21 @@ class DesignerComponent {
9770
9676
  if (!fieldEditorHost) {
9771
9677
  return null;
9772
9678
  }
9773
- const normalize = (v) => String(v || '')
9774
- .replace('*', '')
9775
- .replace(/\s+/g, ' ')
9776
- .trim()
9777
- .toLowerCase();
9778
9679
  return {
9779
9680
  dataFieldId: Number(fieldEditorHost.getAttribute('data-field-id') || 0),
9780
9681
  dataFieldName: String(fieldEditorHost.getAttribute('data-field-name') || '').trim(),
9781
9682
  forAttr: String(fieldEditorHost.querySelector('label.caption')?.getAttribute('for') || '').trim(),
9782
- labelText: normalize(fieldEditorHost.querySelector('label.caption')?.textContent || '')
9683
+ labelText: this.normalizeFieldEditorLabel(fieldEditorHost.querySelector('label.caption')?.textContent || '')
9783
9684
  };
9784
9685
  }
9686
+ /** Normalizzazione condivisa delle label field-editor (no asterisco, spazi collassati, lowercase). */
9687
+ normalizeFieldEditorLabel(v) {
9688
+ return String(v || '')
9689
+ .replace('*', '')
9690
+ .replaceAll(/\s+/g, ' ')
9691
+ .trim()
9692
+ .toLowerCase();
9693
+ }
9785
9694
  matchContextFieldColumn(cols, hints) {
9786
9695
  if (!Array.isArray(cols) || !hints) {
9787
9696
  return null;
@@ -9807,12 +9716,7 @@ class DesignerComponent {
9807
9716
  }
9808
9717
  }
9809
9718
  if (hints.labelText) {
9810
- const normalize = (v) => String(v || '')
9811
- .replace('*', '')
9812
- .replace(/\s+/g, ' ')
9813
- .trim()
9814
- .toLowerCase();
9815
- const byLabel = cols.find((c) => normalize(c?.mc_display_string_in_edit) === hints.labelText);
9719
+ const byLabel = cols.find((c) => this.normalizeFieldEditorLabel(c?.mc_display_string_in_edit) === hints.labelText);
9816
9720
  if (byLabel) {
9817
9721
  return byLabel;
9818
9722
  }
@@ -10507,9 +10411,9 @@ class DesignerComponent {
10507
10411
  // righe gruppo). Il modello/configuratore emette il campo grezzo come dataField + l'aggregato in
10508
10412
  // `aggregates`: qui colleghiamo i due riscrivendo il dataField dei datasets sul nome aggregato,
10509
10413
  // cosi' il chart plotta i valori per gruppo (suffix uppercase, coerente con _Metadati_methods).
10510
- if (Array.isArray(nextConfig.aggregates) && nextConfig.aggregates.length && nextConfig.dataOptions?.datasets) {
10511
- for (const dset of nextConfig.dataOptions.datasets) {
10512
- const agg = nextConfig.aggregates.find((a) => a?.field === dset?.dataField);
10414
+ if (Array.isArray((nextConfig).aggregates) && (nextConfig).aggregates.length && (nextConfig).dataOptions?.datasets) {
10415
+ for (const dset of (nextConfig).dataOptions.datasets) {
10416
+ const agg = (nextConfig).aggregates.find((a) => a?.field === dset?.dataField);
10513
10417
  const sfx = agg?.aggregate ? '_' + String(agg.aggregate).toUpperCase() : '';
10514
10418
  if (sfx && dset?.dataField && !String(dset.dataField).toUpperCase().endsWith(sfx)) {
10515
10419
  dset.dataField = dset.dataField + sfx;
@@ -10523,15 +10427,15 @@ class DesignerComponent {
10523
10427
  const extraProps = this.ensureMergedExtraProps(metaInfo);
10524
10428
  extraProps.archetypes = extraProps.archetypes || {};
10525
10429
  const currentArchetype = extraProps.archetypes[action] || {};
10526
- extraProps.archetypes[action] = Object.assign({}, currentArchetype, nextConfig);
10430
+ extraProps.archetypes[action] = { ...currentArchetype, ...nextConfig };
10527
10431
  // AGGREGAZIONE chart: groupInfo/aggregates sono config DATASOURCE-level (extraProps
10528
10432
  // top-level, lette in data-source.component initMetadata:1914), non archetype-level. Se
10529
10433
  // l'archetype_config li porta (es. chart 'popolazione media per provincia'), sollevali a
10530
10434
  // extraProps top-level cosi' il datasource raggruppa/aggrega lato server nel fetch.
10531
- if (Array.isArray(nextConfig.groupInfo))
10532
- extraProps.groupInfo = nextConfig.groupInfo;
10533
- if (Array.isArray(nextConfig.aggregates))
10534
- extraProps.aggregates = nextConfig.aggregates;
10435
+ if (Array.isArray((nextConfig).groupInfo))
10436
+ extraProps.groupInfo = (nextConfig).groupInfo;
10437
+ if (Array.isArray((nextConfig).aggregates))
10438
+ extraProps.aggregates = (nextConfig).aggregates;
10535
10439
  metaInfo.tableMetadata.extraProps = extraProps;
10536
10440
  metaInfo.tableMetadata.md_props_bag = JSON.stringify(extraProps);
10537
10441
  }
@@ -10540,11 +10444,11 @@ class DesignerComponent {
10540
10444
  // applicato a runtime dall'injection/configuratore) li settiamo a mano sull'istanza PRIMA
10541
10445
  // del fetch, cosi' la fetchData successiva raggruppa/aggrega lato server (un punto per gruppo).
10542
10446
  if (ds) {
10543
- if (Array.isArray(nextConfig.groupInfo)) {
10544
- ds.groupInfo = nextConfig.groupInfo.map((x) => ({ field: x?.field, groupFormula: x?.groupFormula, dir: x?.dir, groupCount: x?.groupCount }));
10447
+ if (Array.isArray((nextConfig).groupInfo)) {
10448
+ ds.groupInfo = (nextConfig).groupInfo.map((x) => ({ field: x?.field, groupFormula: x?.groupFormula, dir: x?.dir, groupCount: x?.groupCount }));
10545
10449
  }
10546
- if (Array.isArray(nextConfig.aggregates)) {
10547
- ds.aggregationInfo = nextConfig.aggregates.map((x) => ({ field: x?.field, aggregate: x?.aggregate }));
10450
+ if (Array.isArray((nextConfig).aggregates)) {
10451
+ ds.aggregationInfo = (nextConfig).aggregates.map((x) => ({ field: x?.field, aggregate: x?.aggregate }));
10548
10452
  }
10549
10453
  }
10550
10454
  if (ds?.fetchData) {
@@ -10613,7 +10517,7 @@ class DesignerComponent {
10613
10517
  if (!raw) {
10614
10518
  return null;
10615
10519
  }
10616
- const rgbaMatch = raw.match(/^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*([0-9]*\.?[0-9]+)\s*\)$/i);
10520
+ const rgbaMatch = /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d*\.?\d+)\s*\)$/i.exec(raw);
10617
10521
  if (rgbaMatch) {
10618
10522
  return {
10619
10523
  r: this.clampRgbChannel(rgbaMatch[1]),
@@ -10622,7 +10526,7 @@ class DesignerComponent {
10622
10526
  a: this.clampColorAlpha(rgbaMatch[4])
10623
10527
  };
10624
10528
  }
10625
- const rgbMatch = raw.match(/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i);
10529
+ const rgbMatch = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(raw);
10626
10530
  if (rgbMatch) {
10627
10531
  return {
10628
10532
  r: this.clampRgbChannel(rgbMatch[1]),
@@ -10634,26 +10538,26 @@ class DesignerComponent {
10634
10538
  const hex = raw.replace('#', '');
10635
10539
  if (/^[0-9a-f]{3}$/i.test(hex)) {
10636
10540
  return {
10637
- r: parseInt(hex[0] + hex[0], 16),
10638
- g: parseInt(hex[1] + hex[1], 16),
10639
- b: parseInt(hex[2] + hex[2], 16),
10541
+ r: Number.parseInt(hex[0] + hex[0], 16),
10542
+ g: Number.parseInt(hex[1] + hex[1], 16),
10543
+ b: Number.parseInt(hex[2] + hex[2], 16),
10640
10544
  a: 1
10641
10545
  };
10642
10546
  }
10643
10547
  if (/^[0-9a-f]{6}$/i.test(hex)) {
10644
10548
  return {
10645
- r: parseInt(hex.slice(0, 2), 16),
10646
- g: parseInt(hex.slice(2, 4), 16),
10647
- b: parseInt(hex.slice(4, 6), 16),
10549
+ r: Number.parseInt(hex.slice(0, 2), 16),
10550
+ g: Number.parseInt(hex.slice(2, 4), 16),
10551
+ b: Number.parseInt(hex.slice(4, 6), 16),
10648
10552
  a: 1
10649
10553
  };
10650
10554
  }
10651
10555
  if (/^[0-9a-f]{8}$/i.test(hex)) {
10652
10556
  return {
10653
- r: parseInt(hex.slice(0, 2), 16),
10654
- g: parseInt(hex.slice(2, 4), 16),
10655
- b: parseInt(hex.slice(4, 6), 16),
10656
- a: this.clampColorAlpha(parseInt(hex.slice(6, 8), 16) / 255)
10557
+ r: Number.parseInt(hex.slice(0, 2), 16),
10558
+ g: Number.parseInt(hex.slice(2, 4), 16),
10559
+ b: Number.parseInt(hex.slice(4, 6), 16),
10560
+ a: this.clampColorAlpha(Number.parseInt(hex.slice(6, 8), 16) / 255)
10657
10561
  };
10658
10562
  }
10659
10563
  return null;
@@ -10664,14 +10568,14 @@ class DesignerComponent {
10664
10568
  let g = 255;
10665
10569
  let b = 255;
10666
10570
  if (/^[0-9a-f]{3}$/i.test(hex)) {
10667
- r = parseInt(hex[0] + hex[0], 16);
10668
- g = parseInt(hex[1] + hex[1], 16);
10669
- b = parseInt(hex[2] + hex[2], 16);
10571
+ r = Number.parseInt(hex[0] + hex[0], 16);
10572
+ g = Number.parseInt(hex[1] + hex[1], 16);
10573
+ b = Number.parseInt(hex[2] + hex[2], 16);
10670
10574
  }
10671
10575
  else if (/^[0-9a-f]{6}$/i.test(hex)) {
10672
- r = parseInt(hex.slice(0, 2), 16);
10673
- g = parseInt(hex.slice(2, 4), 16);
10674
- b = parseInt(hex.slice(4, 6), 16);
10576
+ r = Number.parseInt(hex.slice(0, 2), 16);
10577
+ g = Number.parseInt(hex.slice(2, 4), 16);
10578
+ b = Number.parseInt(hex.slice(4, 6), 16);
10675
10579
  }
10676
10580
  const alpha = this.clampColorAlpha(alphaRaw);
10677
10581
  return `rgba(${r}, ${g}, ${b}, ${Number(alpha.toFixed(2))})`;
@@ -10764,7 +10668,6 @@ class DesignerComponent {
10764
10668
  }
10765
10669
  if (!prevAction) {
10766
10670
  prevAction = createAction(prevActionCaption, prevActionCallback, prevActiondisableCallback, 'wizard-prev-btn', 1);
10767
- needPublish = true;
10768
10671
  }
10769
10672
  else {
10770
10673
  prevAction.button_image = 'wizard-prev-btn';
@@ -10772,20 +10675,25 @@ class DesignerComponent {
10772
10675
  }
10773
10676
  if (!nextAction) {
10774
10677
  nextAction = createAction(nextActionCaption, nextActionCallback, nextActiondisableCallback, 'wizard-next-btn', 3);
10775
- needPublish = true;
10776
10678
  }
10777
10679
  else {
10778
10680
  nextAction.button_image = 'wizard-next-btn';
10779
10681
  nextAction.ordine = 3;
10780
10682
  }
10781
- // if (needPublish) {
10782
10683
  this.publishDesignerDatasourceState(hostDatasource);
10783
10684
  this.commitHistoryIfChanged();
10784
10685
  // }
10785
10686
  if (!nextAction) {
10786
10687
  return;
10787
10688
  }
10788
- await this.openTableActionEditorDialog(target === 'end' ? completeAction : target === 'prev' ? prevAction : nextAction, hostDatasource);
10689
+ let actionToEdit = nextAction;
10690
+ if (target === 'end') {
10691
+ actionToEdit = completeAction;
10692
+ }
10693
+ else if (target === 'prev') {
10694
+ actionToEdit = prevAction;
10695
+ }
10696
+ await this.openTableActionEditorDialog(actionToEdit, hostDatasource);
10789
10697
  }
10790
10698
  /**
10791
10699
  * Restituisce un Id temporaneo negativo non usato per nuove table action in-memory.
@@ -10959,7 +10867,7 @@ class DesignerComponent {
10959
10867
  async openLabelDisplayFormulaEditor(inputs, tool) {
10960
10868
  const displayField = String(inputs?.displayField || '').trim();
10961
10869
  const defaultFormula = displayField
10962
- ? `return dataItem?.['${displayField.replace(/'/g, "\\'")}'] ?? '';`
10870
+ ? `return dataItem?.['${displayField.replaceAll('\'', "\\'")}'] ?? '';`
10963
10871
  : "return dataItem?.[inputs?.displayField] ?? '';";
10964
10872
  await this.openSelectDisplayFormulaEditor(inputs, tool, defaultFormula);
10965
10873
  }
@@ -11015,11 +10923,10 @@ class DesignerComponent {
11015
10923
  const masterRoute = this.getDatasourceRouteName(masterDatasource || {});
11016
10924
  const detailRoute = this.getDatasourceRouteName(detailDatasource || {});
11017
10925
  const masterPrimaryKey = this.getDatasourcePrimaryKey(masterDatasource || {});
11018
- const masterPkValueExpression = masterPrimaryKey
11019
- ? (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(masterPrimaryKey)
11020
- ? `dataItem?.${masterPrimaryKey}`
11021
- : 'dataItem?.id')
10926
+ const masterPkExpression = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(masterPrimaryKey || '')
10927
+ ? `dataItem?.${masterPrimaryKey}`
11022
10928
  : 'dataItem?.id';
10929
+ const masterPkValueExpression = masterPrimaryKey ? masterPkExpression : 'dataItem?.id';
11023
10930
  const propsBag = {
11024
10931
  customEditorConfig: {
11025
10932
  editorOptions: {
@@ -11049,7 +10956,7 @@ class DesignerComponent {
11049
10956
  : null;
11050
10957
  const detailFkField = fkFromLookup || fkFromNameMatch || (detailColumns.length ? detailColumns[0] : '');
11051
10958
  const defaultFormula = detailFkField
11052
- ? `// Detail columns (use one as first argument of setFilter):\n${detailColumnsHint}\nsetFilter('${detailFkField.replace(/'/g, "\\'")}', ${masterPkValueExpression}, 'eq');`
10959
+ ? `// Detail columns (use one as first argument of setFilter):\n${detailColumnsHint}\nsetFilter('${detailFkField.replaceAll('\'', "\\'")}', ${masterPkValueExpression}, 'eq');`
11053
10960
  : `// Detail columns (use one as first argument of setFilter):\n${detailColumnsHint}\n// Example:\n// setFilter('detail_fk', ${masterPkValueExpression}, 'eq');`;
11054
10961
  const result = await WtoolboxService.promptDialog('Master-Detail Filter Formula', [
11055
10962
  {
@@ -11086,7 +10993,7 @@ class DesignerComponent {
11086
10993
  if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(col)) {
11087
10994
  return ` ${col}: any;`;
11088
10995
  }
11089
- return ` '${col.replace(/'/g, "\\'")}': any;`;
10996
+ return ` '${col.replaceAll('\'', "\\'")}': any;`;
11090
10997
  }).join('\n');
11091
10998
  };
11092
10999
  const detailCommentRows = detailColumns.length
@@ -11134,7 +11041,7 @@ ${detailCommentRows}
11134
11041
  if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
11135
11042
  return ` ${key}: any;`;
11136
11043
  }
11137
- return ` '${key.replace(/'/g, "\\'")}': any;`;
11044
+ return ` '${key.replaceAll('\'', "\\'")}': any;`;
11138
11045
  }).join('\n')
11139
11046
  : ' [key: string]: any;';
11140
11047
  const routeComment = routeName ? `route: ${routeName}` : 'route: n/a';
@@ -11226,8 +11133,8 @@ Display formula context:
11226
11133
  propsFromBag = {};
11227
11134
  }
11228
11135
  const current = metaInfo?.tableMetadata?.extraProps || {};
11229
- const merged = Object.assign({}, propsFromBag, current);
11230
- merged.archetypes = Object.assign({}, propsFromBag?.archetypes || {}, current?.archetypes || {});
11136
+ const merged = { ...propsFromBag, ...current };
11137
+ merged.archetypes = { ...propsFromBag?.archetypes, ...current?.archetypes };
11231
11138
  return merged;
11232
11139
  }
11233
11140
  /**
@@ -11263,8 +11170,8 @@ Display formula context:
11263
11170
  propsFromBag = {};
11264
11171
  }
11265
11172
  const current = tableMetadata.extraProps || {};
11266
- const merged = Object.assign({}, propsFromBag, current);
11267
- merged.archetypes = Object.assign({}, propsFromBag?.archetypes || {}, current?.archetypes || {});
11173
+ const merged = { ...propsFromBag, ...current };
11174
+ merged.archetypes = { ...propsFromBag?.archetypes, ...current?.archetypes };
11268
11175
  tableMetadata.extraProps = merged;
11269
11176
  }
11270
11177
  /**
@@ -11279,8 +11186,8 @@ Display formula context:
11279
11186
  const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
11280
11187
  const normalizeDynamicScript = (source) => String(source || '')
11281
11188
  .replace(/^\uFEFF/, '')
11282
- .replace(/\u0000/g, '')
11283
- .replace(/\u2028|\u2029/g, '\n');
11189
+ .replaceAll(/\u0000/g, '')
11190
+ .replaceAll(/[\u2028\u2029]/g, '\n');
11284
11191
  actions.forEach((action) => {
11285
11192
  if (!action || typeof action !== 'object') {
11286
11193
  return;
@@ -11290,7 +11197,7 @@ Display formula context:
11290
11197
  try {
11291
11198
  const body = WtoolboxService.buildAsyncBody(actionScript);
11292
11199
  action.action_callback__fn = actionScript
11293
- ? new AsyncFunction('datasource, metaInfo, record, event, wtoolbox', body)
11200
+ ? (new AsyncFunction('datasource, metaInfo, record, event, wtoolbox', body))
11294
11201
  : async () => { };
11295
11202
  }
11296
11203
  catch {
@@ -11433,10 +11340,6 @@ Display formula context:
11433
11340
  }
11434
11341
  }
11435
11342
  else if (deltaRows < 0) {
11436
- for (let i = tool.nestedComponents.length; i >= Math.abs(deltaRows); i--) {
11437
- let trTool = tool.nestedComponents[i - 1];
11438
- // trTool.nestedComponents = [];
11439
- }
11440
11343
  tool.nestedComponents.splice(deltaRows, Math.abs(deltaRows));
11441
11344
  }
11442
11345
  else if (deltaCols > 0) {
@@ -11495,14 +11398,10 @@ Display formula context:
11495
11398
  }
11496
11399
  }
11497
11400
  else if (deltaAreas < 0) {
11498
- for (let i = tool.nestedComponents.length; i >= Math.abs(deltaAreas); i--) {
11499
- let trTool = tool.nestedComponents[i - 1];
11500
- // trTool.nestedComponents = [];
11501
- }
11502
11401
  tool.nestedComponents.splice(deltaAreas, Math.abs(deltaAreas));
11503
11402
  }
11504
- for (let i = 0; i < tool.nestedComponents.length; i++) {
11505
- tool.nestedComponents[i].inputs['size'] = 100 / tool.nestedComponents.length;
11403
+ for (const nestedComponent of tool.nestedComponents) {
11404
+ nestedComponent.inputs['size'] = 100 / tool.nestedComponents.length;
11506
11405
  }
11507
11406
  this.flattenedDashboardElements = this.flattenComponentTree(this.dashboardElements);
11508
11407
  obj[prop] = newValue;
@@ -11532,14 +11431,10 @@ Display formula context:
11532
11431
  }
11533
11432
  }
11534
11433
  else if (deltaItems < 0) {
11535
- for (let i = tool.nestedComponents.length; i >= Math.abs(deltaItems); i--) {
11536
- let trTool = tool.nestedComponents[i - 1];
11537
- // trTool.nestedComponents = [];
11538
- }
11539
11434
  tool.nestedComponents.splice(deltaItems, Math.abs(deltaItems));
11540
11435
  }
11541
- for (let i = 0; i < tool.nestedComponents.length; i++) {
11542
- tool.nestedComponents[i].inputs['size'] = 100 / tool.nestedComponents.length;
11436
+ for (const nestedComponent of tool.nestedComponents) {
11437
+ nestedComponent.inputs['size'] = 100 / tool.nestedComponents.length;
11543
11438
  }
11544
11439
  this.flattenedDashboardElements = this.flattenComponentTree(this.dashboardElements);
11545
11440
  obj[prop] = newValue;
@@ -11553,7 +11448,8 @@ Display formula context:
11553
11448
  if (currentTool.name == 'TABLE') {
11554
11449
  let tr = this.availableTools.find(x => x.name == 'TR');
11555
11450
  let td = this.availableTools.find(x => x.name == 'TD');
11556
- let table = this.availableTools.find(x => x.name == 'TABLE');
11451
+ let table;
11452
+ this.availableTools.find(x => x.name == 'TABLE');
11557
11453
  for (let i = 1; i <= currentTool.inputs['rows']; i++) {
11558
11454
  let tr1 = JSON.parse(JSON.stringify(tr));
11559
11455
  tr1.inputs.width = undefined;
@@ -11701,16 +11597,14 @@ Display formula context:
11701
11597
  }
11702
11598
  });
11703
11599
  }
11600
+ else if (currentTool.inputProps[prop].type == 'dropped-component') {
11601
+ currentTool.inputs[prop] = { component: new BehaviorSubject(currentTool.inputs[prop]), id: currentTool.componentId, name: currentTool.name, uniqueName: currentTool.uniqueName };
11602
+ }
11603
+ else if (currentTool.inputProps[prop].type == 'function') {
11604
+ currentTool.inputs[prop] = this.draggedPayload.inputs[prop].bind(currentTool.inputs);
11605
+ }
11704
11606
  else {
11705
- if (currentTool.inputProps[prop].type == 'dropped-component') {
11706
- currentTool.inputs[prop] = { component: new BehaviorSubject(currentTool.inputs[prop]), id: currentTool.componentId, name: currentTool.name, uniqueName: currentTool.uniqueName };
11707
- }
11708
- else if (currentTool.inputProps[prop].type == 'function') {
11709
- currentTool.inputs[prop] = this.draggedPayload.inputs[prop].bind(currentTool.inputs);
11710
- }
11711
- else {
11712
- currentTool.inputs[prop] = currentTool.inputs[prop];
11713
- }
11607
+ currentTool.inputs[prop] = currentTool.inputs[prop];
11714
11608
  }
11715
11609
  if (this.draggedPayload.inputProps[prop].conditional) {
11716
11610
  currentTool.inputProps[prop].conditional = this.draggedPayload.inputProps[prop].conditional;
@@ -11748,10 +11642,9 @@ Display formula context:
11748
11642
  id = parentEl.getAttribute("id");
11749
11643
  parentEl = parentEl.parentElement;
11750
11644
  }
11751
- if (id && id.indexOf("__") > -1) {
11752
- let componentId = parseInt(id.split("__")[1]);
11645
+ if (id?.includes("__")) {
11646
+ let componentId = Number.parseInt(id.split("__")[1]);
11753
11647
  let match = null;
11754
- // let parent = this.dashboardElements;
11755
11648
  match = (this.flattenedDashboardElements || []).find(x => x.componentId == componentId);
11756
11649
  if (match) {
11757
11650
  if (!match.allowedChildren || match.allowedChildren.includes(currentTool.name)) {
@@ -11887,12 +11780,15 @@ Display formula context:
11887
11780
  const savedState = this.propertySectionStateByTool[toolKey] || {};
11888
11781
  return sectionOrder
11889
11782
  .filter((key) => grouped[key].length > 0)
11890
- .map((key) => ({
11891
- key: key,
11892
- label: labels[key],
11893
- open: (propFilter && propFilter.length >= 3 && grouped[key].length) ? true : (savedState[key] !== undefined ? !!savedState[key] : openByDefault[key]),
11894
- props: grouped[key]
11895
- }));
11783
+ .map((key) => {
11784
+ const savedOpen = savedState[key] !== undefined ? !!savedState[key] : openByDefault[key];
11785
+ return {
11786
+ key: key,
11787
+ label: labels[key],
11788
+ open: (propFilter && propFilter.length >= 3 && grouped[key].length) ? true : savedOpen,
11789
+ props: grouped[key]
11790
+ };
11791
+ });
11896
11792
  }
11897
11793
  clearPropFilter() {
11898
11794
  this.propFilter = "";
@@ -11935,7 +11831,7 @@ Display formula context:
11935
11831
  return this.getRepeaterAction(tool) !== 'wizard';
11936
11832
  }
11937
11833
  if (propFilter && propFilter.length >= 3) {
11938
- return toolProp.key.toLocaleLowerCase().indexOf(propFilter.toLocaleLowerCase()) < 0;
11834
+ return !toolProp.key.toLocaleLowerCase().includes(propFilter.toLocaleLowerCase());
11939
11835
  }
11940
11836
  return false;
11941
11837
  }
@@ -12051,7 +11947,7 @@ Display formula context:
12051
11947
  return value;
12052
11948
  }
12053
11949
  mergeToolPropDefinition(baseDef, currentDef) {
12054
- const merged = { ...(baseDef || {}), ...(currentDef || {}) };
11950
+ const merged = { ...(baseDef), ...(currentDef) };
12055
11951
  if (!merged.converter && baseDef?.converter) {
12056
11952
  merged.converter = baseDef.converter;
12057
11953
  }
@@ -12077,7 +11973,7 @@ Display formula context:
12077
11973
  if (template?.inputProps) {
12078
11974
  Object.keys(template.inputProps).forEach((key) => {
12079
11975
  element.inputProps[key] = this.mergeToolPropDefinition(template.inputProps[key], element.inputProps[key]);
12080
- if (element.inputs[key] === undefined && template.inputs && template.inputs[key] !== undefined) {
11976
+ if (element.inputs[key] === undefined && template.inputs?.[key] !== undefined) {
12081
11977
  element.inputs[key] = this.cloneInputDefaultValue(template.inputs[key]);
12082
11978
  }
12083
11979
  });
@@ -12328,9 +12224,9 @@ Display formula context:
12328
12224
  dashRoute: dashRoute
12329
12225
  };
12330
12226
  result = await this.dataSrv.loadDashboard(payload);
12331
- resultRows = Array.isArray(result)
12332
- ? result
12333
- : (Array.isArray(result?.results) ? result.results : (result ? [result] : []));
12227
+ const singleRows = result ? [result] : [];
12228
+ const wrappedRows = Array.isArray((result)?.results) ? (result).results : singleRows;
12229
+ resultRows = Array.isArray(result) ? result : wrappedRows;
12334
12230
  }
12335
12231
  if (!insertTarget) {
12336
12232
  this.currentDashboardDescription = String(dashboard?.board_des ??
@@ -12352,11 +12248,24 @@ Display formula context:
12352
12248
  loadedDashboard = [];
12353
12249
  }
12354
12250
  if (!Array.isArray(loadedDashboard)) {
12355
- loadedDashboard = Array.isArray(loadedDashboard?.dashboardElements)
12356
- ? loadedDashboard.dashboardElements
12357
- : Array.isArray(loadedDashboard?.elements)
12358
- ? loadedDashboard.elements
12359
- : [];
12251
+ // Forma wrapper-object: puo' trasportare flag board-level come
12252
+ // `widgetChrome` (chrome card dei widget, vedi <wuic-dashboard>).
12253
+ if (!insertTarget) {
12254
+ const chrome = loadedDashboard?.widgetChrome;
12255
+ this.dashboardWidgetChrome = chrome === true || String(chrome ?? '').trim().toLowerCase() === 'true' || String(chrome ?? '').trim() === '1';
12256
+ }
12257
+ if (Array.isArray(loadedDashboard?.dashboardElements)) {
12258
+ loadedDashboard = loadedDashboard.dashboardElements;
12259
+ }
12260
+ else if (Array.isArray(loadedDashboard?.elements)) {
12261
+ loadedDashboard = loadedDashboard.elements;
12262
+ }
12263
+ else {
12264
+ loadedDashboard = [];
12265
+ }
12266
+ }
12267
+ else if (!insertTarget) {
12268
+ this.dashboardWidgetChrome = false;
12360
12269
  }
12361
12270
  this.mergeMissingToolPropsRecursive(loadedDashboard);
12362
12271
  if (!insertTarget) {
@@ -12414,18 +12323,16 @@ Display formula context:
12414
12323
  uniqueName: element.uniqueName
12415
12324
  });
12416
12325
  }
12326
+ else if (element.inputProps[prop].asyncPath) {
12327
+ const path = element.inputProps[prop].asyncPath;
12328
+ const rawValue = element.inputs[prop] ?? {};
12329
+ element.inputs[prop] = new BehaviorSubject({
12330
+ ...rawValue,
12331
+ [path]: new BehaviorSubject(rawValue?.[path] ?? null)
12332
+ });
12333
+ }
12417
12334
  else {
12418
- if (element.inputProps[prop].asyncPath) {
12419
- const path = element.inputProps[prop].asyncPath;
12420
- const rawValue = element.inputs[prop] ?? {};
12421
- element.inputs[prop] = new BehaviorSubject({
12422
- ...rawValue,
12423
- [path]: new BehaviorSubject(rawValue?.[path] ?? null)
12424
- });
12425
- }
12426
- else {
12427
- element.inputs[prop] = new BehaviorSubject(element.inputs[prop]);
12428
- }
12335
+ element.inputs[prop] = new BehaviorSubject(element.inputs[prop]);
12429
12336
  }
12430
12337
  element.inputs[prop].subscribe((v) => {
12431
12338
  if (v?.component) {
@@ -12459,7 +12366,7 @@ Display formula context:
12459
12366
  }
12460
12367
  }
12461
12368
  }
12462
- if (!dsElements.find(x => x.uniqueName == v.uniqueName)) {
12369
+ if (!dsElements.some(x => x.uniqueName == v.uniqueName)) {
12463
12370
  dsSubs.push(v.component.fetchInfo$);
12464
12371
  dsElements.push(dsElement);
12465
12372
  if (dsElements.length == dsElementCount) {
@@ -12644,11 +12551,15 @@ Display formula context:
12644
12551
  loadedDashboard = [];
12645
12552
  }
12646
12553
  if (!Array.isArray(loadedDashboard)) {
12647
- loadedDashboard = Array.isArray(loadedDashboard?.dashboardElements)
12648
- ? loadedDashboard.dashboardElements
12649
- : Array.isArray(loadedDashboard?.elements)
12650
- ? loadedDashboard.elements
12651
- : [];
12554
+ if (Array.isArray(loadedDashboard?.dashboardElements)) {
12555
+ loadedDashboard = loadedDashboard.dashboardElements;
12556
+ }
12557
+ else if (Array.isArray(loadedDashboard?.elements)) {
12558
+ loadedDashboard = loadedDashboard.elements;
12559
+ }
12560
+ else {
12561
+ loadedDashboard = [];
12562
+ }
12652
12563
  }
12653
12564
  this.mergeMissingToolPropsRecursive(loadedDashboard);
12654
12565
  this.dashboardComponents = [];
@@ -12703,7 +12614,14 @@ Display formula context:
12703
12614
  if (!propDef.async && propDef.asyncPath && (propDef.type === 'dropped-component-list' || propDef.type === 'dropped-component')) {
12704
12615
  const path = propDef.asyncPath;
12705
12616
  const rawValue = element.inputs[prop];
12706
- console.log(`[HYDRATE-v9] ${element.name}.${prop}: rawValue=${rawValue === null ? 'NULL' : rawValue === undefined ? 'UNDEF' : 'object'} uniqueName=${rawValue?.uniqueName} keys=${rawValue ? Object.keys(rawValue) : '[]'}`);
12617
+ let rawValueKind = 'object';
12618
+ if (rawValue === null) {
12619
+ rawValueKind = 'NULL';
12620
+ }
12621
+ else if (rawValue === undefined) {
12622
+ rawValueKind = 'UNDEF';
12623
+ }
12624
+ console.log(`[HYDRATE-v9] ${element.name}.${prop}: rawValue=${rawValueKind} uniqueName=${rawValue?.uniqueName} keys=${rawValue ? Object.keys(rawValue) : '[]'}`);
12707
12625
  if (rawValue && typeof rawValue === 'object' && !(rawValue instanceof BehaviorSubject)) {
12708
12626
  // Only hydrate the component BS — do NOT invent a uniqueName if the
12709
12627
  // snapshot didn't have one. That would create a false binding on undo.
@@ -12766,7 +12684,7 @@ Display formula context:
12766
12684
  }
12767
12685
  }
12768
12686
  }
12769
- if (!dsElements.find(de => de.uniqueName == v.uniqueName)) {
12687
+ if (!dsElements.some(de => de.uniqueName == v.uniqueName)) {
12770
12688
  dsSubs.push(v.component.fetchInfo$);
12771
12689
  dsElements.push(dsElement);
12772
12690
  if (dsElements.length == dsElementCount) {
@@ -13267,10 +13185,10 @@ Display formula context:
13267
13185
  */
13268
13186
  openCurrentDashboardInNewTab() {
13269
13187
  const route = String(this.currentDashboardRoute || '').trim();
13270
- if (!route || typeof window === 'undefined') {
13188
+ if (!route || globalThis.window === undefined) {
13271
13189
  return;
13272
13190
  }
13273
- const base = window.location.href.split('#')[0];
13191
+ const base = globalThis.location.href.split('#')[0];
13274
13192
  const url = `${base}#/${encodeURIComponent(route)}/dashboard`;
13275
13193
  window.open(url, '_blank');
13276
13194
  }
@@ -13290,11 +13208,11 @@ Display formula context:
13290
13208
  // return customProps;
13291
13209
  }
13292
13210
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DesignerComponent, deps: [{ token: i1$1.ActivatedRoute }, { token: DataProviderService }, { token: MetadataProviderService }, { token: UserInfoService }, { token: i0.ChangeDetectorRef }, { token: TranslationManagerService }, { token: MetadataEditorService }, { token: ChatbotHostRegistryService }, { token: WorkflowRuntimeMetadataService }], target: i0.ɵɵFactoryTarget.Component });
13293
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DesignerComponent, isStandalone: true, selector: "wuic-designer", host: { listeners: { "window:hashchange": "onWindowHashChange()", "window:beforeunload": "onWindowBeforeUnload($event)", "window:keydown": "onWindowKeydown($event)", "window:mouseup": "onWindowMouseup()", "window:touchend": "onWindowTouchend()", "window:keyup": "onWindowKeyup()", "window:change": "onWindowChange()" } }, providers: [TreeDragDropService], viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true }], ngImport: i0, template: "<!-- <button pButton type=\"button\" (click)=\"loadDashboard()\" class=\"mr-2\">{{'load' | translate}}</button> -->\n@if (!noEdit) {\n<div class=\"designer-layout\">\n <div class=\"designer-toolbar\">\n <div class=\"designer-current-dashboard\">{{ currentDashboardTitle }}</div>\n\n <div class=\"designer-toolbar-spacer\"></div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"undo()\" [disabled]=\"!canUndo\">{{ 'designer.undo' | translate }}</button>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"redo()\" [disabled]=\"!canRedo\">{{ 'designer.redo' | translate }}</button>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" data-testid=\"designer-actions-menu-btn\" (click)=\"refreshGraphActionsMenuItems(); graphActionsMenu.toggle($event)\">{{ 'designer.actions_menu' | translate }}</button>\n <p-menu #graphActionsMenu [popup]=\"true\" [model]=\"graphActionsMenuItems\" appendTo=\"body\"></p-menu>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"openCurrentDashboardInNewTab()\" [disabled]=\"!currentDashboardRoute\">{{\n 'designer.open_current_dashboard' | translate }}</button>\n </div>\n </div>\n <div class=\"designer-main\">\n <p-splitter [style]=\"{ height: '100%' }\" [panelSizes]=\"[15, 85]\" styleClass=\"designer-main-splitter\">\n <ng-template pTemplate>\n <p-splitter layout=\"vertical\" [style]=\"{ height: '100%', width: '100%' }\" [panelSizes]=\"[35, 65]\"\n [minSizes]=\"[20, 30]\" styleClass=\"designer-left-splitter\">\n <ng-template pTemplate>\n <div class=\"col flex designer-toolbox palette-panel\">\n <ul class=\"tool-groups\">\n @for (toolGroup of availableToolGroups; track toolGroup.group) {\n <li class=\"tool-group-item\">\n <div class=\"tool-group-title\">{{ toolGroup.group }}</div>\n <ul class=\"tool-group-list\">\n @for (tool of toolGroup.tools; track tool) {\n <li pDraggable (onDragStart)=\"dragStart(tool)\" (onDragEnd)=\"dragEnd()\" (onDrag)=\"onDrag($event)\"\n (dblclick)=\"dropToolAtRoot(tool)\">\n <i [ngClass]=\"tool.icon\" [title]=\"tool.name\"></i>\n </li>\n }\n </ul>\n </li>\n }\n </ul>\n </div>\n </ng-template>\n <ng-template pTemplate>\n <p-splitter layout=\"vertical\" [style]=\"{ height: '100%', width: '100%' }\" [panelSizes]=\"[68, 32]\"\n [minSizes]=\"[35, 20]\" styleClass=\"designer-left-bottom-splitter\">\n <ng-template pTemplate>\n <div class=\"properties-panel\">\n <p-select [style]=\"{width: '100%'}\" [options]=\"flattenedDashboardElements\" [(ngModel)]=\"tool\"\n optionLabel=\"uniqueName\" dataKey=\"componentId\" appendTo=\"body\" />\n <div class=\"designer-toolbox\">\n\n <span style=\"width: 100%;\">\n <input type=\"text\" style=\"width: calc(100% - 30px);\" [(ngModel)]=\"propFilter\"\n [placeholder]=\"'prop.filter' | translate\" />\n <button style=\"width: 25px\" (click)=\"clearPropFilter()\">X</button>\n </span>\n\n @for (section of getToolPropertySections(tool, propFilter); track section.key) {\n <details class=\"prop-section\" [open]=\"section.open\"\n (toggle)=\"onPropertySectionToggle(tool, section.key, $event)\">\n <summary class=\"prop-section-title\">{{ section.label }}</summary>\n <ul class=\"props\">\n @for (toolProp of section.props; track toolProp.key) {\n <li>\n @if (!toolProp.value.hideCaption) {\n <span>{{ toolProp.value?.propertyCaption ||\n toolProp.key[0].toUpperCase() + toolProp.key.slice(1)\n }}</span>\n }\n <br />\n @if (toolProp.value.type == 'button') {\n <p-button (click)=\"toolProp.value.callback(tool.inputs, toolProp.key, null, tool)\"\n class=\"k-button\" [style]=\"{width: '100%'}\">\n {{toolProp.value.propertyCaption}}\n </p-button>\n }\n @if (toolProp.value.type == 'metaEditor' &&\n tool.inputs['componentRef']?.value?.component) {\n <wuic-metadata-editor [hardcodedDatasource]=\"tool.inputs['componentRef']?.value?.component\"\n [saveCallback]=\"metaEditorSave\"></wuic-metadata-editor>\n }\n @if (toolProp.value.type == 'boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"tool.inputs[toolProp.key]\" />\n }\n @if (toolProp.value.type == 'numberToArray') {\n <input style=\"width: 100%;\" type=\"number\" pInputText [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'txt_area') {\n <textarea style=\"width: 100%;\" [(ngModel)]=\"tool.inputs[toolProp.key]\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\"></textarea>\n }\n @if (toolProp.value.type == 'string') {\n <input style=\"width: 100%;\" type=\"text\" pInputText [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'color') {\n <p-colorPicker [ngModel]=\"getDesignerColorPickerHex(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorPickerHexChange($event, tool, toolProp)\" appendTo=\"body\" />\n <div class=\"designer-color-alpha-row\">\n <span class=\"designer-color-alpha-label\">{{ 'designer.alpha' | translate }}</span>\n <input type=\"range\" min=\"0\" max=\"1\" step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n <input type=\"number\" min=\"0\" max=\"1\" step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n </div>\n <input type=\"text\" pInputText [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'dictionary' && !toolProp.value.async) {\n @if (toolProp.key == 'cssFile') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"availableProjectCssFiles\"\n [ngModel]=\"tool.inputs[toolProp.key]\" (ngModelChange)=\"onCssFileChanged($event, tool)\" />\n } @else if (toolProp.key == 'cssClass') {\n <p-multiSelect [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getCssClassOptionsForTool(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"onCssClassChanged($event, tool)\" [filter]=\"true\" [virtualScroll]=\"true\"\n [virtualScrollItemSize]=\"38\" scrollHeight=\"260px\" [showToggleAll]=\"false\" display=\"chip\"\n [maxSelectedLabels]=\"3\" [selectedItemsLabel]=\"'{0} selected'\">\n </p-multiSelect>\n } @else if ((tool.name == 'SELECT' || tool.name == 'MULTISELECT' || tool.name == 'UL') &&\n (toolProp.key == 'valueField' || toolProp.key == 'textField')) {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getDatasourceColumnOptions(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n } @else if (tool.name == 'LABEL' && toolProp.key == 'displayField') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getDatasourceColumnOptions(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n } @else {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"toolProp.value.values\"\n [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n }\n @if (toolProp.value.type == 'dictionary' && toolProp.value.async) {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"toolProp.value.values\"\n [ngModel]=\"tool.inputs[toolProp.key] | async\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (tool.name == 'DATAREPEATER' && toolProp.key == 'action' &&\n canOpenArchetypeConfigurator(tool)) {\n <button style=\"margin-top: 8px;\" (click)=\"openArchetypeConfigurator(tool)\">\n {{ 'designer.configure' | translate }} {{ (tool.inputs['action'] | async) || '' }}\n </button>\n }\n @if (toolProp.value.type == 'dropped-component-list') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [placeholder]=\"'select.component' | translate\" [options]=\"elementFilter(toolProp)\"\n [ngModel]=\"getDroppedComponentListModel(tool, toolProp)\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" optionLabel=\"uniqueName\"\n dataKey=\"uniqueName\" />\n }\n @if (toolProp.value.type == 'autocomplete') {\n <p-autoComplete [style]=\"{width: '100%'}\" appendTo=\"body\"\n [ngModel]=\"tool.inputs[toolProp.key] | async\" [forceSelection]=\"true\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" [suggestions]=\"tool.suggestions\"\n [optionLabel]=\"toolProp.value.displayField\" [optionValue]=\"toolProp.value.valueField\"\n (completeMethod)=\"search($event, tool, toolProp)\" [dropdown]=\"true\" dropdownMode=\"current\"\n [multiple]=\"toolProp.value.multiple\" />\n }\n @if (toolProp.value.type == 'propertyTree' && shouldShowPropertyTree(tool)) {\n <ul>\n @for (item of $any(tool.inputs[toolProp.key] | async); track item) {\n <li style=\"padding: 0; margin: 0;\">\n @if (item.col && tool.inputs['customProps_' + (tool.inputs['action'] | async)])\n {\n <wuic-field-editor [field]=\"item.col\"\n [record]=\"tool.inputs['customProps_' + (tool.inputs['action'] | async)]\"\n [metaInfo]=\"tool.inputs['datasource']?.component?.value?.metaInfo\"\n [triggerProp]=\"tool.inputs['action']\"></wuic-field-editor>\n }\n </li>\n }\n </ul>\n }\n </li>\n }\n </ul>\n </details>\n }\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate>\n <div class=\"hierarchy-panel\">\n <div class=\"hierarchy-panel-title\">{{ 'designer.canvas_hierarchy' | translate }}</div>\n <div class=\"hierarchy-tree-wrap\">\n <p-tree [value]=\"hierarchyTreeNodes\" [draggableNodes]=\"true\" [droppableNodes]=\"true\"\n selectionMode=\"single\" [(selection)]=\"hierarchySelection\"\n (onNodeSelect)=\"onHierarchyNodeSelect($event)\" draggableScope=\"designer-hierarchy\"\n droppableScope=\"designer-hierarchy\" (onNodeDrop)=\"onHierarchyNodeDrop($event)\">\n <ng-template let-node pTemplate=\"default\">\n <span class=\"hierarchy-node-label\" [class.active]=\"isHierarchyNodeSelected(node)\"\n (mouseenter)=\"onHierarchyNodeMouseEnter(node)\" (mouseleave)=\"onHierarchyNodeMouseLeave()\"\n (contextmenu)=\"showHierarchyNodeContextMenu($event, node, hierarchyCtxMenu)\">\n {{ node.label }}\n </span>\n </ng-template>\n </p-tree>\n </div>\n <p-contextMenu #hierarchyCtxMenu [model]=\"hierarchyCtxItems\" appendTo=\"body\" />\n </div>\n </ng-template>\n </p-splitter>\n </ng-template>\n </p-splitter>\n </ng-template>\n <ng-template pTemplate>\n <div class=\"col dashboard-design\" [class.designer-hide-datasources]=\"hideDatasourcesInCanvas\"\n [class.designer-snap-grid]=\"snapToGridEnabled\" [style.--wuic-grid-size.px]=\"gridSize\" pDroppable\n (onDrop)=\"drop($event)\" #canvas (mousedown)=\"onCanvasMouseDown($event)\"\n (contextmenu)=\"showCtx($event, this)\">\n <wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\n @if (rubberBandVisible) {\n <div class=\"designer-selection-rect\" [style.left]=\"rubberBandStyle.left\" [style.top]=\"rubberBandStyle.top\"\n [style.width]=\"rubberBandStyle.width\" [style.height]=\"rubberBandStyle.height\"></div>\n }\n <p-contextMenu [target]=\"canvas\" [model]=\"ctxItems | async\" appendTo=\"body\" />\n </div>\n </ng-template>\n </p-splitter>\n </div>\n <div class=\"designer-footer\">\n <div class=\"designer-footer-label\">{{ 'designer.items' | translate }}:</div>\n <div class=\"designer-footer-list\">\n @for (item of droppedDashboardItems; track item.uniqueName) {\n <button type=\"button\" class=\"designer-footer-item\" [class.active]=\"tool?.uniqueName === item?.uniqueName\"\n [attr.data-designer-unique-name]=\"item?.uniqueName\" (mouseenter)=\"setFooterHoverHighlight(item)\"\n (mouseleave)=\"clearFooterHoverHighlight()\" (click)=\"selectDashboardItem(item)\"\n (contextmenu)=\"showFooterContextMenu($event, item, footerCtxMenu)\">\n {{ getDroppedDashboardItemLabel(item) }}\n </button>\n }\n </div>\n <p-contextMenu #footerCtxMenu [model]=\"footerCtxItems\" appendTo=\"body\" />\n </div>\n</div>\n}\n\n@if (noEdit) {\n<wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\n}\n\n<wuic-archetype-configurator [visible]=\"showArchetypeConfigurator\"\n (visibleChange)=\"onArchetypeConfigVisibleChange($event)\" [archetype]=\"getActiveArchetypeConfig()\"\n [metaInfo]=\"getArchetypeConfigMetaInfoForTool(archetypeConfigTool)\"\n [value]=\"getArchetypeConfigValueForTool(archetypeConfigTool)\" (applyConfig)=\"onArchetypeConfigApply($event)\">\n</wuic-archetype-configurator>\n\n<wuic-css-sheet-editor [visible]=\"showCssSheetEditor\" (visibleChange)=\"onCssSheetEditorVisibleChange($event)\"\n [sheets]=\"dashboardCssSheets\" [selectedSheetPath]=\"selectedCssEditorSheetPath\" [assetsFolder]=\"currentDashboardRoute\"\n [styleProps]=\"getCssEditorStyleProps()\" (applyEditor)=\"onCssSheetEditorApply($event)\">\n</wuic-css-sheet-editor>\n\n<p-dialog [header]=\"'designer.reopen_dashboard' | translate\" [(visible)]=\"reopenDashboardDialogVisible\" [modal]=\"true\"\n [closable]=\"true\" [draggable]=\"false\" [resizable]=\"false\" [appendTo]=\"'body'\" [style]=\"{ width: '34rem' }\"\n (onHide)=\"cancelReopenDashboardDialog()\">\n <div class=\"route-popup-form\">\n <label for=\"designer-reopen-select\">{{ 'designer.existing_dashboards' | translate }}</label>\n <p-select inputId=\"designer-reopen-select\" [options]=\"savedDashboardOptions\" optionLabel=\"label\" optionValue=\"value\"\n [(ngModel)]=\"reopenDialogSelectedDashboardRoute\" [filter]=\"true\" [showClear]=\"true\" [style]=\"{ width: '100%' }\"\n appendTo=\"body\" />\n\n <div class=\"route-popup-actions\">\n <button type=\"button\" class=\"route-popup-btn\" (click)=\"cancelReopenDashboardDialog()\">{{ 'cancel' | translate\n }}</button>\n <button type=\"button\" class=\"route-popup-btn route-popup-btn-primary\" (click)=\"confirmReopenDashboardDialog()\"\n [disabled]=\"!reopenDialogSelectedDashboardRoute\">{{ 'designer.reopen' | translate }}</button>\n </div>\n </div>\n</p-dialog>", styles: [":host{display:block;width:100%;height:100%;min-width:0}.designer-layout{display:grid;grid-template-rows:auto minmax(0,1fr) auto;height:100%;min-height:0;width:100%;min-width:0}.designer-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:8px;border:1px solid inherit;border-radius:10px;background:transparent;padding:10px 12px;margin-bottom:8px}.designer-current-dashboard{min-width:220px;font-size:.86rem;font-weight:700;color:inherit}.designer-toolbar-spacer{flex:1 1 auto;min-width:16px}.designer-toolbar-menu-group{display:inline-flex}.designer-toolbar-menu-group button{height:32px;border:1px solid #2f67d8;border-radius:6px;background:#2f67d8;color:#fff;padding:0 10px;font-size:.82rem;cursor:pointer}.designer-toolbar-menu-group button[disabled]{opacity:.6;cursor:not-allowed}.designer-main{min-height:0;min-width:0;width:100%;overflow:hidden;direction:ltr}.designer-main-splitter{height:100%;width:100%;min-width:0;direction:ltr}.designer-toolbox{font-size:3rem}.designer-toolbox ul{list-style-type:none;padding:0;margin:0;width:100%}.designer-toolbox li{float:left;margin-left:5px;margin-top:5px}.designer-toolbox .tool-groups{display:block}.designer-toolbox .tool-group-item{float:none;margin-left:0;margin-top:10px;clear:both}.designer-toolbox .tool-group-title{font-size:.8rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;opacity:.7;margin:0 0 4px 6px}.designer-toolbox .tool-group-list{display:flex;flex-wrap:wrap;align-items:flex-start;gap:4px}.designer-toolbox .tool-group-list li{float:none;margin-left:0;margin-top:0}.designer-toolbox .props{font-size:1rem}.designer-toolbox .props li{float:none;padding-bottom:15px}.designer-toolbox .prop-section{width:100%;border:1px solid inherit;border-radius:6px;margin-top:8px;background:transparent;padding:6px 8px 2px}.designer-toolbox .prop-section-title{font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;cursor:pointer;color:inherit;margin-bottom:6px}.palette-panel{height:100%;overflow:auto;width:100%}.designer-color-alpha-row{display:flex;align-items:center;gap:8px;margin-top:6px;margin-bottom:6px}.designer-color-alpha-label{font-size:.8rem;min-width:40px}.designer-color-alpha-row input[type=range]{flex:1 1 auto;min-width:90px}.designer-color-alpha-row input[type=number]{width:72px}.properties-panel{height:100%;overflow:hidden;width:100%;display:flex;flex-direction:column;min-height:0;padding-right:10px;padding-left:10px;padding-top:10px}.properties-panel>.designer-toolbox{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:stable}:host ::ng-deep .designer-left-bottom-splitter .p-splitterpanel{min-height:0!important;overflow:hidden!important}.hierarchy-panel{height:100%;width:100%;min-height:0;display:flex;flex-direction:column;overflow:hidden;padding:6px}.hierarchy-panel-title{font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#4b5563;margin:0 0 6px}.hierarchy-tree-wrap{flex:1 1 auto;min-height:0;border:1px solid inherit;border-radius:6px;background:transparent;overflow:auto;padding:4px}:host ::ng-deep .hierarchy-tree-wrap .p-tree{border:none;padding:0;height:100%;background:transparent}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content{border:1px solid transparent;border-radius:4px;background:transparent!important;color:inherit!important;padding:0!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content.p-highlight{border-color:transparent!important;background:transparent!important;color:inherit!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content:hover{background:transparent!important;color:inherit!important}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label{display:inline-block;border:1px solid inherit;background:transparent;color:inherit;border-radius:4px;padding:2px 8px;font-size:.8rem;line-height:1.25rem;cursor:pointer}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label:hover{border-color:#94a3b8}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label.active{border-color:#3b82f6!important;background:#eff6ff!important;color:#1d4ed8!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content.p-highlight .hierarchy-node-label{border-color:#3b82f6!important;background:#eff6ff!important;color:#1d4ed8!important}.designer-hierarchy-node{cursor:pointer;border:1px solid transparent;border-radius:4px;padding:2px 6px;font-size:.82rem;line-height:1.25rem}.designer-hierarchy-node-label{cursor:pointer;display:inline-block;width:100%}.designer-hierarchy-node.active{border-color:#3b82f6;background:#eff6ff;color:#1d4ed8}.designer-footer-item.designer-tree-hover-target{border-color:#3b82f6!important;outline:1px solid #3b82f6!important;outline-offset:-1px}.dashboard-design{height:100%;min-height:0;min-width:0;width:100%;overflow:auto;direction:ltr;position:relative}.designer-selection-rect{position:absolute;border:1px dashed #3b82f6;background:#3b82f61f;pointer-events:none;z-index:10000}:host ::ng-deep .designer-multi-selected{outline:2px solid #3b82f6!important;outline-offset:1px}:host ::ng-deep .dashboard-design.designer-hide-datasources .datasource-descriptor{display:none!important}.current-dashboard-title{font-weight:600;margin-right:12px}.designer-footer{display:flex;align-items:center;gap:8px;padding:6px 8px;border-top:1px solid inherit;background:transparent;min-height:36px;flex:0 0 auto;width:100%;overflow:auto}.designer-footer-label{font-size:.85rem;font-weight:600;color:inherit;white-space:nowrap}.designer-footer-list{display:flex;align-items:center;gap:6px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;width:100%}.designer-footer-item{border:1px solid inherit;background:transparent;color:inherit;border-radius:4px;padding:2px 8px;font-size:.8rem;line-height:1.25rem;cursor:pointer;white-space:nowrap}.designer-footer-item.active{border-color:#3b82f6;background:transparent;color:#1d4ed8}:host ::ng-deep .designer-footer-hover-target{border-color:#3b82f6!important;outline:1px solid #3b82f6!important;outline-offset:-1px;box-shadow:inset 0 0 0 1px #3b82f6!important}.route-popup-form{display:flex;flex-direction:column;gap:8px}.route-popup-form label{font-size:.85rem;font-weight:600;color:#2f3f58}.route-popup-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.route-popup-btn{border:1px solid inherit;background:transparent;color:inherit;border-radius:6px;padding:7px 12px;font-size:.85rem;cursor:pointer}.route-popup-btn-primary{border-color:#2f67d8;background:#2f67d8;color:#fff}.p-colorpicker{border:1px solid black;border-radius:4px}.dashboard-design.designer-snap-grid{background-image:linear-gradient(to right,rgba(128,128,128,.16) 1px,transparent 1px),linear-gradient(to bottom,rgba(128,128,128,.16) 1px,transparent 1px);background-size:var(--wuic-grid-size, 10px) var(--wuic-grid-size, 10px)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SplitterModule }, { kind: "component", type: i10.Splitter, selector: "p-splitter", inputs: ["styleClass", "panelStyleClass", "panelStyle", "stateStorage", "stateKey", "layout", "gutterSize", "step", "minSizes", "panelSizes"], outputs: ["onResizeEnd", "onResizeStart"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i12.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i12.Droppable, selector: "[pDroppable]", inputs: ["pDroppable", "pDroppableDisabled", "dropEffect"], outputs: ["onDragEnter", "onDragLeave", "onDrop"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i6.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ColorPickerModule }, { kind: "component", type: i2$1.ColorPicker, selector: "p-colorPicker, p-colorpicker, p-color-picker", inputs: ["styleClass", "showTransitionOptions", "hideTransitionOptions", "inline", "format", "tabindex", "inputId", "autoZIndex", "autofocus", "defaultColor", "appendTo", "overlayOptions", "motionOptions"], outputs: ["onChange", "onShow", "onHide"] }, { kind: "ngmodule", type: AutoCompleteModule }, { kind: "component", type: i2$2.AutoComplete, selector: "p-autoComplete, p-autocomplete, p-auto-complete", inputs: ["minLength", "minQueryLength", "delay", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "addOnTab", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "typeahead", "addOnBlur", "separator", "appendTo", "motionOptions"], outputs: ["completeMethod", "onSelect", "onUnselect", "onAdd", "onFocus", "onBlur", "onDropdownClick", "onClear", "onInputKeydown", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "component", type: DashboardComponent, selector: "wuic-dashboard", inputs: ["dashboardElements"] }, { kind: "component", type: FieldEditorComponent, selector: "wuic-field-editor", inputs: ["datasource", "record", "field", "metaInfo", "readOnly", "isFilter", "hideLabel", "forceShowLabel", "operator", "nestedIndex", "triggerProp", "tabIndex", "onInlineCellValueChange"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i10$1.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: MetadataEditorComponent, selector: "wuic-metadata-editor", inputs: ["datasource", "hardcodedDatasource", "saveCallback", "hideReports", "hideRelatedTableActions", "hideRelatedColumnActions"] }, { kind: "ngmodule", type: MenubarModule }, { kind: "component", type: ArchetypeConfiguratorComponent, selector: "wuic-archetype-configurator", inputs: ["visible", "archetype", "metaInfo", "value"], outputs: ["visibleChange", "applyConfig"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i18.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "component", type: CssSheetEditorComponent, selector: "wuic-css-sheet-editor", inputs: ["visible", "sheets", "selectedSheetPath", "styleProps", "assetsFolder"], outputs: ["visibleChange", "applyEditor"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i7.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex", "appendTo", "motionOptions"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: TreeModule }, { kind: "component", type: i4$1.Tree, selector: "p-tree", inputs: ["value", "selectionMode", "loadingMode", "selection", "styleClass", "contextMenu", "contextMenuSelectionMode", "contextMenuSelection", "draggableScope", "droppableScope", "draggableNodes", "droppableNodes", "metaKeySelection", "propagateSelectionUp", "propagateSelectionDown", "loading", "loadingIcon", "emptyMessage", "ariaLabel", "togglerAriaLabel", "ariaLabelledBy", "validateDrop", "filter", "filterInputAutoFocus", "filterBy", "filterMode", "filterOptions", "filterPlaceholder", "filteredNodes", "filterLocale", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "indentation", "_templateMap", "trackBy", "highlightOnSelect"], outputs: ["selectionChange", "contextMenuSelectionChange", "onNodeSelect", "onNodeUnselect", "onNodeExpand", "onNodeCollapse", "onNodeContextMenuSelect", "onNodeDoubleClick", "onNodeDrop", "onLazyLoad", "onScroll", "onScrollIndexChange", "onFilter"] }, { kind: "pipe", type: i2$3.TranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
13211
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DesignerComponent, isStandalone: true, selector: "wuic-designer", host: { listeners: { "window:hashchange": "onWindowHashChange()", "window:beforeunload": "onWindowBeforeUnload($event)", "window:keydown": "onWindowKeydown($event)", "window:mouseup": "onWindowMouseup()", "window:touchend": "onWindowTouchend()", "window:keyup": "onWindowKeyup()", "window:change": "onWindowChange()" } }, providers: [TreeDragDropService], viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true }], ngImport: i0, template: "@if (!noEdit) {\n<div class=\"designer-layout\">\n <div class=\"designer-toolbar\">\n <div class=\"designer-current-dashboard\">{{ currentDashboardTitle }}</div>\n\n <div class=\"designer-toolbar-spacer\"></div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"undo()\" [disabled]=\"!canUndo\">{{ 'designer.undo' | translate }}</button>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"redo()\" [disabled]=\"!canRedo\">{{ 'designer.redo' | translate }}</button>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" data-testid=\"designer-actions-menu-btn\" (click)=\"refreshGraphActionsMenuItems(); graphActionsMenu.toggle($event)\">{{ 'designer.actions_menu' | translate }}</button>\n <p-menu #graphActionsMenu [popup]=\"true\" [model]=\"graphActionsMenuItems\" appendTo=\"body\"></p-menu>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"openCurrentDashboardInNewTab()\" [disabled]=\"!currentDashboardRoute\">{{\n 'designer.open_current_dashboard' | translate }}</button>\n </div>\n </div>\n <div class=\"designer-main\">\n <p-splitter [style]=\"{ height: '100%' }\" [panelSizes]=\"[15, 85]\" styleClass=\"designer-main-splitter\">\n <ng-template pTemplate>\n <p-splitter layout=\"vertical\" [style]=\"{ height: '100%', width: '100%' }\" [panelSizes]=\"[35, 65]\"\n [minSizes]=\"[20, 30]\" styleClass=\"designer-left-splitter\">\n <ng-template pTemplate>\n <div class=\"col flex designer-toolbox palette-panel\">\n <ul class=\"tool-groups\">\n @for (toolGroup of availableToolGroups; track toolGroup.group) {\n <li class=\"tool-group-item\">\n <div class=\"tool-group-title\">{{ toolGroup.group }}</div>\n <ul class=\"tool-group-list\">\n @for (tool of toolGroup.tools; track tool) {\n <li pDraggable (onDragStart)=\"dragStart(tool)\" (onDragEnd)=\"dragEnd()\" (onDrag)=\"onDrag($event)\"\n (dblclick)=\"dropToolAtRoot(tool)\">\n <i [ngClass]=\"tool.icon\" [title]=\"tool.name\"></i>\n </li>\n }\n </ul>\n </li>\n }\n </ul>\n </div>\n </ng-template>\n <ng-template pTemplate>\n <p-splitter layout=\"vertical\" [style]=\"{ height: '100%', width: '100%' }\" [panelSizes]=\"[68, 32]\"\n [minSizes]=\"[35, 20]\" styleClass=\"designer-left-bottom-splitter\">\n <ng-template pTemplate>\n <div class=\"properties-panel\">\n <p-select [style]=\"{width: '100%'}\" [options]=\"flattenedDashboardElements\" [(ngModel)]=\"tool\"\n optionLabel=\"uniqueName\" dataKey=\"componentId\" appendTo=\"body\" />\n <div class=\"designer-toolbox\">\n\n <span style=\"width: 100%;\">\n <input type=\"text\" style=\"width: calc(100% - 30px);\" [(ngModel)]=\"propFilter\"\n [placeholder]=\"'prop.filter' | translate\" />\n <button style=\"width: 25px\" (click)=\"clearPropFilter()\">X</button>\n </span>\n\n @for (section of getToolPropertySections(tool, propFilter); track section.key) {\n <details class=\"prop-section\" [open]=\"section.open\"\n (toggle)=\"onPropertySectionToggle(tool, section.key, $event)\">\n <summary class=\"prop-section-title\">{{ section.label }}</summary>\n <ul class=\"props\">\n @for (toolProp of section.props; track toolProp.key) {\n <li>\n @if (!toolProp.value.hideCaption) {\n <span>{{ toolProp.value?.propertyCaption ||\n toolProp.key[0].toUpperCase() + toolProp.key.slice(1)\n }}</span>\n }\n <br />\n @if (toolProp.value.type == 'button') {\n <p-button (click)=\"toolProp.value.callback(tool.inputs, toolProp.key, null, tool)\"\n class=\"k-button\" [style]=\"{width: '100%'}\">\n {{toolProp.value.propertyCaption}}\n </p-button>\n }\n @if (toolProp.value.type == 'metaEditor' &&\n tool.inputs['componentRef']?.value?.component) {\n <wuic-metadata-editor [hardcodedDatasource]=\"tool.inputs['componentRef']?.value?.component\"\n [saveCallback]=\"metaEditorSave\"></wuic-metadata-editor>\n }\n @if (toolProp.value.type == 'boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"tool.inputs[toolProp.key]\" />\n }\n @if (toolProp.value.type == 'numberToArray') {\n <input style=\"width: 100%;\" type=\"number\" pInputText [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'txt_area') {\n <textarea style=\"width: 100%;\" [(ngModel)]=\"tool.inputs[toolProp.key]\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\"></textarea>\n }\n @if (toolProp.value.type == 'string') {\n <!-- updateOn:blur come il txt_area sopra: senza, setValue() scatta\n A OGNI CARATTERE e buildSerializedDashboardElements ri-serializza\n l'intero tree (history da centinaia di KB per tasto, P-D1). -->\n <input style=\"width: 100%;\" type=\"text\" pInputText [(ngModel)]=\"tool.inputs[toolProp.key]\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'color') {\n <p-colorPicker [ngModel]=\"getDesignerColorPickerHex(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorPickerHexChange($event, tool, toolProp)\" appendTo=\"body\" />\n <div class=\"designer-color-alpha-row\">\n <span class=\"designer-color-alpha-label\">{{ 'designer.alpha' | translate }}</span>\n <input type=\"range\" min=\"0\" max=\"1\" step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n <input type=\"number\" min=\"0\" max=\"1\" step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n </div>\n <input type=\"text\" pInputText [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'dictionary' && !toolProp.value.async) {\n @if (toolProp.key == 'cssFile') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"availableProjectCssFiles\"\n [ngModel]=\"tool.inputs[toolProp.key]\" (ngModelChange)=\"onCssFileChanged($event, tool)\" />\n } @else if (toolProp.key == 'cssClass') {\n <p-multiSelect [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getCssClassOptionsForTool(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"onCssClassChanged($event, tool)\" [filter]=\"true\" [virtualScroll]=\"true\"\n [virtualScrollItemSize]=\"38\" scrollHeight=\"260px\" [showToggleAll]=\"false\" display=\"chip\"\n [maxSelectedLabels]=\"3\" [selectedItemsLabel]=\"'{0} selected'\">\n </p-multiSelect>\n } @else if ((tool.name == 'SELECT' || tool.name == 'MULTISELECT' || tool.name == 'UL') &&\n (toolProp.key == 'valueField' || toolProp.key == 'textField')) {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getDatasourceColumnOptions(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n } @else if (tool.name == 'LABEL' && toolProp.key == 'displayField') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getDatasourceColumnOptions(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n } @else {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"toolProp.value.values\"\n [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n }\n @if (toolProp.value.type == 'dictionary' && toolProp.value.async) {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"toolProp.value.values\"\n [ngModel]=\"tool.inputs[toolProp.key] | async\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (tool.name == 'DATAREPEATER' && toolProp.key == 'action' &&\n canOpenArchetypeConfigurator(tool)) {\n <button style=\"margin-top: 8px;\" (click)=\"openArchetypeConfigurator(tool)\">\n {{ 'designer.configure' | translate }} {{ (tool.inputs['action'] | async) || '' }}\n </button>\n }\n @if (toolProp.value.type == 'dropped-component-list') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [placeholder]=\"'select.component' | translate\" [options]=\"elementFilter(toolProp)\"\n [ngModel]=\"getDroppedComponentListModel(tool, toolProp)\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" optionLabel=\"uniqueName\"\n dataKey=\"uniqueName\" />\n }\n @if (toolProp.value.type == 'autocomplete') {\n <p-autoComplete [style]=\"{width: '100%'}\" appendTo=\"body\"\n [ngModel]=\"tool.inputs[toolProp.key] | async\" [forceSelection]=\"true\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" [suggestions]=\"tool.suggestions\"\n [optionLabel]=\"toolProp.value.displayField\" [optionValue]=\"toolProp.value.valueField\"\n (completeMethod)=\"search($event, tool, toolProp)\" [dropdown]=\"true\" dropdownMode=\"current\"\n [multiple]=\"toolProp.value.multiple\" />\n }\n @if (toolProp.value.type == 'propertyTree' && shouldShowPropertyTree(tool)) {\n <ul>\n @for (item of $any(tool.inputs[toolProp.key] | async); track item) {\n <li style=\"padding: 0; margin: 0;\">\n @if (item.col && tool.inputs['customProps_' + (tool.inputs['action'] | async)])\n {\n <wuic-field-editor [field]=\"item.col\"\n [record]=\"tool.inputs['customProps_' + (tool.inputs['action'] | async)]\"\n [metaInfo]=\"tool.inputs['datasource']?.component?.value?.metaInfo\"\n [triggerProp]=\"tool.inputs['action']\"></wuic-field-editor>\n }\n </li>\n }\n </ul>\n }\n </li>\n }\n </ul>\n </details>\n }\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate>\n <div class=\"hierarchy-panel\">\n <div class=\"hierarchy-panel-title\">{{ 'designer.canvas_hierarchy' | translate }}</div>\n <div class=\"hierarchy-tree-wrap\">\n <p-tree [value]=\"hierarchyTreeNodes\" [draggableNodes]=\"true\" [droppableNodes]=\"true\"\n selectionMode=\"single\" [(selection)]=\"hierarchySelection\"\n (onNodeSelect)=\"onHierarchyNodeSelect($event)\" draggableScope=\"designer-hierarchy\"\n droppableScope=\"designer-hierarchy\" (onNodeDrop)=\"onHierarchyNodeDrop($event)\">\n <ng-template let-node pTemplate=\"default\">\n <span class=\"hierarchy-node-label\" [class.active]=\"isHierarchyNodeSelected(node)\"\n (mouseenter)=\"onHierarchyNodeMouseEnter(node)\" (mouseleave)=\"onHierarchyNodeMouseLeave()\"\n (contextmenu)=\"showHierarchyNodeContextMenu($event, node, hierarchyCtxMenu)\">\n {{ node.label }}\n </span>\n </ng-template>\n </p-tree>\n </div>\n <p-contextMenu #hierarchyCtxMenu [model]=\"hierarchyCtxItems\" appendTo=\"body\" />\n </div>\n </ng-template>\n </p-splitter>\n </ng-template>\n </p-splitter>\n </ng-template>\n <ng-template pTemplate>\n <div class=\"col dashboard-design\" [class.designer-hide-datasources]=\"hideDatasourcesInCanvas\"\n [class.designer-snap-grid]=\"snapToGridEnabled\" [style.--wuic-grid-size.px]=\"gridSize\" pDroppable\n (onDrop)=\"drop($event)\" #canvas (mousedown)=\"onCanvasMouseDown($event)\"\n (contextmenu)=\"showCtx($event, this)\">\n <wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\n @if (rubberBandVisible) {\n <div class=\"designer-selection-rect\" [style.left]=\"rubberBandStyle.left\" [style.top]=\"rubberBandStyle.top\"\n [style.width]=\"rubberBandStyle.width\" [style.height]=\"rubberBandStyle.height\"></div>\n }\n <p-contextMenu [target]=\"canvas\" [model]=\"ctxItems | async\" appendTo=\"body\" />\n </div>\n </ng-template>\n </p-splitter>\n </div>\n <div class=\"designer-footer\">\n <div class=\"designer-footer-label\">{{ 'designer.items' | translate }}:</div>\n <div class=\"designer-footer-list\">\n @for (item of droppedDashboardItems; track item.uniqueName) {\n <button type=\"button\" class=\"designer-footer-item\" [class.active]=\"tool?.uniqueName === item?.uniqueName\"\n [attr.data-designer-unique-name]=\"item?.uniqueName\" (mouseenter)=\"setFooterHoverHighlight(item)\"\n (mouseleave)=\"clearFooterHoverHighlight()\" (click)=\"selectDashboardItem(item)\"\n (contextmenu)=\"showFooterContextMenu($event, item, footerCtxMenu)\">\n {{ getDroppedDashboardItemLabel(item) }}\n </button>\n }\n </div>\n <p-contextMenu #footerCtxMenu [model]=\"footerCtxItems\" appendTo=\"body\" />\n </div>\n</div>\n}\n\n@if (noEdit) {\n<wuic-dashboard [dashboardElements]=\"dashboardElements\" [widgetChrome]=\"dashboardWidgetChrome\"></wuic-dashboard>\n}\n\n<wuic-archetype-configurator [visible]=\"showArchetypeConfigurator\"\n (visibleChange)=\"onArchetypeConfigVisibleChange($event)\" [archetype]=\"getActiveArchetypeConfig()\"\n [metaInfo]=\"getArchetypeConfigMetaInfoForTool(archetypeConfigTool)\"\n [value]=\"getArchetypeConfigValueForTool(archetypeConfigTool)\" (applyConfig)=\"onArchetypeConfigApply($event)\">\n</wuic-archetype-configurator>\n\n<wuic-css-sheet-editor [visible]=\"showCssSheetEditor\" (visibleChange)=\"onCssSheetEditorVisibleChange($event)\"\n [sheets]=\"dashboardCssSheets\" [selectedSheetPath]=\"selectedCssEditorSheetPath\" [assetsFolder]=\"currentDashboardRoute\"\n [styleProps]=\"getCssEditorStyleProps()\" (applyEditor)=\"onCssSheetEditorApply($event)\">\n</wuic-css-sheet-editor>\n\n<p-dialog [header]=\"'designer.reopen_dashboard' | translate\" [(visible)]=\"reopenDashboardDialogVisible\" [modal]=\"true\"\n [closable]=\"true\" [draggable]=\"false\" [resizable]=\"false\" [appendTo]=\"'body'\" [style]=\"{ width: '34rem' }\"\n (onHide)=\"cancelReopenDashboardDialog()\">\n <div class=\"route-popup-form\">\n <label for=\"designer-reopen-select\">{{ 'designer.existing_dashboards' | translate }}</label>\n <p-select inputId=\"designer-reopen-select\" [options]=\"savedDashboardOptions\" optionLabel=\"label\" optionValue=\"value\"\n [(ngModel)]=\"reopenDialogSelectedDashboardRoute\" [filter]=\"true\" [showClear]=\"true\" [style]=\"{ width: '100%' }\"\n appendTo=\"body\" />\n\n <div class=\"route-popup-actions\">\n <button type=\"button\" class=\"route-popup-btn\" (click)=\"cancelReopenDashboardDialog()\">{{ 'cancel' | translate\n }}</button>\n <button type=\"button\" class=\"route-popup-btn route-popup-btn-primary\" (click)=\"confirmReopenDashboardDialog()\"\n [disabled]=\"!reopenDialogSelectedDashboardRoute\">{{ 'designer.reopen' | translate }}</button>\n </div>\n </div>\n</p-dialog>", styles: [":host{display:block;width:100%;height:100%;min-width:0}.designer-layout{display:grid;grid-template-rows:auto minmax(0,1fr) auto;height:100%;min-height:0;width:100%;min-width:0}.designer-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:8px;border:1px solid inherit;border-radius:10px;background:transparent;padding:10px 12px;margin-bottom:8px}.designer-current-dashboard{min-width:220px;font-size:.86rem;font-weight:700;color:inherit}.designer-toolbar-spacer{flex:1 1 auto;min-width:16px}.designer-toolbar-menu-group{display:inline-flex}.designer-toolbar-menu-group button{height:32px;border:1px solid #2f67d8;border-radius:6px;background:#2f67d8;color:#fff;padding:0 10px;font-size:.82rem;cursor:pointer}.designer-toolbar-menu-group button[disabled]{opacity:.6;cursor:not-allowed}.designer-main{min-height:0;min-width:0;width:100%;overflow:hidden;direction:ltr}.designer-main-splitter{height:100%;width:100%;min-width:0;direction:ltr}.designer-toolbox{font-size:3rem}.designer-toolbox ul{list-style-type:none;padding:0;margin:0;width:100%}.designer-toolbox li{float:left;margin-left:5px;margin-top:5px}.designer-toolbox .tool-groups{display:block}.designer-toolbox .tool-group-item{float:none;margin-left:0;margin-top:10px;clear:both}.designer-toolbox .tool-group-title{font-size:.8rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;opacity:.7;margin:0 0 4px 6px}.designer-toolbox .tool-group-list{display:flex;flex-wrap:wrap;align-items:flex-start;gap:4px}.designer-toolbox .tool-group-list li{float:none;margin-left:0;margin-top:0}.designer-toolbox .props{font-size:1rem}.designer-toolbox .props li{float:none;padding-bottom:15px}.designer-toolbox .prop-section{width:100%;border:1px solid inherit;border-radius:6px;margin-top:8px;background:transparent;padding:6px 8px 2px}.designer-toolbox .prop-section-title{font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;cursor:pointer;color:inherit;margin-bottom:6px}.palette-panel{height:100%;overflow:auto;width:100%}.designer-color-alpha-row{display:flex;align-items:center;gap:8px;margin-top:6px;margin-bottom:6px}.designer-color-alpha-label{font-size:.8rem;min-width:40px}.designer-color-alpha-row input[type=range]{flex:1 1 auto;min-width:90px}.designer-color-alpha-row input[type=number]{width:72px}.properties-panel{height:100%;overflow:hidden;width:100%;display:flex;flex-direction:column;min-height:0;padding-right:10px;padding-left:10px;padding-top:10px}.properties-panel>.designer-toolbox{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:stable}:host ::ng-deep .designer-left-bottom-splitter .p-splitterpanel{min-height:0!important;overflow:hidden!important}.hierarchy-panel{height:100%;width:100%;min-height:0;display:flex;flex-direction:column;overflow:hidden;padding:6px}.hierarchy-panel-title{font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#4b5563;margin:0 0 6px}.hierarchy-tree-wrap{flex:1 1 auto;min-height:0;border:1px solid inherit;border-radius:6px;background:transparent;overflow:auto;padding:4px}:host ::ng-deep .hierarchy-tree-wrap .p-tree{border:none;padding:0;height:100%;background:transparent}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content{border:1px solid transparent;border-radius:4px;background:transparent!important;color:inherit!important;padding:0!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content.p-highlight{border-color:transparent!important;background:transparent!important;color:inherit!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content:hover{background:transparent!important;color:inherit!important}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label{display:inline-block;border:1px solid inherit;background:transparent;color:inherit;border-radius:4px;padding:2px 8px;font-size:.8rem;line-height:1.25rem;cursor:pointer}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label:hover{border-color:#94a3b8}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label.active{border-color:#3b82f6!important;background:#eff6ff!important;color:#1d4ed8!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content.p-highlight .hierarchy-node-label{border-color:#3b82f6!important;background:#eff6ff!important;color:#1d4ed8!important}.designer-hierarchy-node{cursor:pointer;border:1px solid transparent;border-radius:4px;padding:2px 6px;font-size:.82rem;line-height:1.25rem}.designer-hierarchy-node-label{cursor:pointer;display:inline-block;width:100%}.designer-hierarchy-node.active{border-color:#3b82f6;background:#eff6ff;color:#1d4ed8}.designer-footer-item.designer-tree-hover-target{border-color:#3b82f6!important;outline:1px solid #3b82f6!important;outline-offset:-1px}.dashboard-design{height:100%;min-height:0;min-width:0;width:100%;overflow:auto;direction:ltr;position:relative}.designer-selection-rect{position:absolute;border:1px dashed #3b82f6;background:#3b82f61f;pointer-events:none;z-index:10000}:host ::ng-deep .designer-multi-selected{outline:2px solid #3b82f6!important;outline-offset:1px}:host ::ng-deep .dashboard-design.designer-hide-datasources .datasource-descriptor{display:none!important}.current-dashboard-title{font-weight:600;margin-right:12px}.designer-footer{display:flex;align-items:center;gap:8px;padding:6px 8px;border-top:1px solid inherit;background:transparent;min-height:36px;flex:0 0 auto;width:100%;overflow:auto}.designer-footer-label{font-size:.85rem;font-weight:600;color:inherit;white-space:nowrap}.designer-footer-list{display:flex;align-items:center;gap:6px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;width:100%}.designer-footer-item{border:1px solid inherit;background:transparent;color:inherit;border-radius:4px;padding:2px 8px;font-size:.8rem;line-height:1.25rem;cursor:pointer;white-space:nowrap}.designer-footer-item.active{border-color:#3b82f6;background:transparent;color:#1d4ed8}:host ::ng-deep .designer-footer-hover-target{border-color:#3b82f6!important;outline:1px solid #3b82f6!important;outline-offset:-1px;box-shadow:inset 0 0 0 1px #3b82f6!important}.route-popup-form{display:flex;flex-direction:column;gap:8px}.route-popup-form label{font-size:.85rem;font-weight:600;color:#2f3f58}.route-popup-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.route-popup-btn{border:1px solid inherit;background:transparent;color:inherit;border-radius:6px;padding:7px 12px;font-size:.85rem;cursor:pointer}.route-popup-btn-primary{border-color:#2f67d8;background:#2f67d8;color:#fff}.p-colorpicker{border:1px solid black;border-radius:4px}.dashboard-design.designer-snap-grid{background-image:linear-gradient(to right,rgba(128,128,128,.16) 1px,transparent 1px),linear-gradient(to bottom,rgba(128,128,128,.16) 1px,transparent 1px);background-size:var(--wuic-grid-size, 10px) var(--wuic-grid-size, 10px)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: SplitterModule }, { kind: "component", type: i10.Splitter, selector: "p-splitter", inputs: ["styleClass", "panelStyleClass", "panelStyle", "stateStorage", "stateKey", "layout", "gutterSize", "step", "minSizes", "panelSizes"], outputs: ["onResizeEnd", "onResizeStart"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i12.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i12.Droppable, selector: "[pDroppable]", inputs: ["pDroppable", "pDroppableDisabled", "dropEffect"], outputs: ["onDragEnter", "onDragLeave", "onDrop"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: ColorPickerModule }, { kind: "component", type: i6.ColorPicker, selector: "p-colorPicker, p-colorpicker, p-color-picker", inputs: ["styleClass", "showTransitionOptions", "hideTransitionOptions", "inline", "format", "tabindex", "inputId", "autoZIndex", "autofocus", "defaultColor", "appendTo", "overlayOptions", "motionOptions"], outputs: ["onChange", "onShow", "onHide"] }, { kind: "ngmodule", type: AutoCompleteModule }, { kind: "component", type: i2$1.AutoComplete, selector: "p-autoComplete, p-autocomplete, p-auto-complete", inputs: ["minLength", "minQueryLength", "delay", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "addOnTab", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "typeahead", "addOnBlur", "separator", "appendTo", "motionOptions"], outputs: ["completeMethod", "onSelect", "onUnselect", "onAdd", "onFocus", "onBlur", "onDropdownClick", "onClear", "onInputKeydown", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "component", type: DashboardComponent, selector: "wuic-dashboard", inputs: ["dashboardElements", "widgetChrome"] }, { kind: "component", type: FieldEditorComponent, selector: "wuic-field-editor", inputs: ["datasource", "record", "field", "metaInfo", "readOnly", "isFilter", "hideLabel", "forceShowLabel", "operator", "nestedIndex", "triggerProp", "tabIndex", "onInlineCellValueChange"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i14.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: MetadataEditorComponent, selector: "wuic-metadata-editor", inputs: ["datasource", "hardcodedDatasource", "saveCallback", "hideReports", "hideRelatedTableActions", "hideRelatedColumnActions"] }, { kind: "ngmodule", type: MenubarModule }, { kind: "component", type: ArchetypeConfiguratorComponent, selector: "wuic-archetype-configurator", inputs: ["visible", "archetype", "metaInfo", "value"], outputs: ["visibleChange", "applyConfig"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i18.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "component", type: CssSheetEditorComponent, selector: "wuic-css-sheet-editor", inputs: ["visible", "sheets", "selectedSheetPath", "styleProps", "assetsFolder"], outputs: ["visibleChange", "applyEditor"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i7.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "ariaLabel", "ariaLabelledBy", "id", "tabindex", "appendTo", "motionOptions"], outputs: ["onShow", "onHide", "onBlur", "onFocus"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i2.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: TreeModule }, { kind: "component", type: i4$1.Tree, selector: "p-tree", inputs: ["value", "selectionMode", "loadingMode", "selection", "styleClass", "contextMenu", "contextMenuSelectionMode", "contextMenuSelection", "draggableScope", "droppableScope", "draggableNodes", "droppableNodes", "metaKeySelection", "propagateSelectionUp", "propagateSelectionDown", "loading", "loadingIcon", "emptyMessage", "ariaLabel", "togglerAriaLabel", "ariaLabelledBy", "validateDrop", "filter", "filterInputAutoFocus", "filterBy", "filterMode", "filterOptions", "filterPlaceholder", "filteredNodes", "filterLocale", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "indentation", "_templateMap", "trackBy", "highlightOnSelect"], outputs: ["selectionChange", "contextMenuSelectionChange", "onNodeSelect", "onNodeUnselect", "onNodeExpand", "onNodeCollapse", "onNodeContextMenuSelect", "onNodeDoubleClick", "onNodeDrop", "onLazyLoad", "onScroll", "onScrollIndexChange", "onFilter"] }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }] });
13294
13212
  }
13295
13213
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DesignerComponent, decorators: [{
13296
13214
  type: Component,
13297
- args: [{ selector: 'wuic-designer', imports: [NgClass, TranslateModule, AsyncPipe, FormsModule, SplitterModule, DragDropModule, SelectModule, ColorPickerModule, AutoCompleteModule, DashboardComponent, FieldEditorComponent, ContextMenuModule, MetadataEditorComponent, MenubarModule, ArchetypeConfiguratorComponent, ButtonModule, MultiSelectModule, CssSheetEditorComponent, MenuModule, DialogModule, TreeModule], providers: [TreeDragDropService], template: "<!-- <button pButton type=\"button\" (click)=\"loadDashboard()\" class=\"mr-2\">{{'load' | translate}}</button> -->\n@if (!noEdit) {\n<div class=\"designer-layout\">\n <div class=\"designer-toolbar\">\n <div class=\"designer-current-dashboard\">{{ currentDashboardTitle }}</div>\n\n <div class=\"designer-toolbar-spacer\"></div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"undo()\" [disabled]=\"!canUndo\">{{ 'designer.undo' | translate }}</button>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"redo()\" [disabled]=\"!canRedo\">{{ 'designer.redo' | translate }}</button>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" data-testid=\"designer-actions-menu-btn\" (click)=\"refreshGraphActionsMenuItems(); graphActionsMenu.toggle($event)\">{{ 'designer.actions_menu' | translate }}</button>\n <p-menu #graphActionsMenu [popup]=\"true\" [model]=\"graphActionsMenuItems\" appendTo=\"body\"></p-menu>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"openCurrentDashboardInNewTab()\" [disabled]=\"!currentDashboardRoute\">{{\n 'designer.open_current_dashboard' | translate }}</button>\n </div>\n </div>\n <div class=\"designer-main\">\n <p-splitter [style]=\"{ height: '100%' }\" [panelSizes]=\"[15, 85]\" styleClass=\"designer-main-splitter\">\n <ng-template pTemplate>\n <p-splitter layout=\"vertical\" [style]=\"{ height: '100%', width: '100%' }\" [panelSizes]=\"[35, 65]\"\n [minSizes]=\"[20, 30]\" styleClass=\"designer-left-splitter\">\n <ng-template pTemplate>\n <div class=\"col flex designer-toolbox palette-panel\">\n <ul class=\"tool-groups\">\n @for (toolGroup of availableToolGroups; track toolGroup.group) {\n <li class=\"tool-group-item\">\n <div class=\"tool-group-title\">{{ toolGroup.group }}</div>\n <ul class=\"tool-group-list\">\n @for (tool of toolGroup.tools; track tool) {\n <li pDraggable (onDragStart)=\"dragStart(tool)\" (onDragEnd)=\"dragEnd()\" (onDrag)=\"onDrag($event)\"\n (dblclick)=\"dropToolAtRoot(tool)\">\n <i [ngClass]=\"tool.icon\" [title]=\"tool.name\"></i>\n </li>\n }\n </ul>\n </li>\n }\n </ul>\n </div>\n </ng-template>\n <ng-template pTemplate>\n <p-splitter layout=\"vertical\" [style]=\"{ height: '100%', width: '100%' }\" [panelSizes]=\"[68, 32]\"\n [minSizes]=\"[35, 20]\" styleClass=\"designer-left-bottom-splitter\">\n <ng-template pTemplate>\n <div class=\"properties-panel\">\n <p-select [style]=\"{width: '100%'}\" [options]=\"flattenedDashboardElements\" [(ngModel)]=\"tool\"\n optionLabel=\"uniqueName\" dataKey=\"componentId\" appendTo=\"body\" />\n <div class=\"designer-toolbox\">\n\n <span style=\"width: 100%;\">\n <input type=\"text\" style=\"width: calc(100% - 30px);\" [(ngModel)]=\"propFilter\"\n [placeholder]=\"'prop.filter' | translate\" />\n <button style=\"width: 25px\" (click)=\"clearPropFilter()\">X</button>\n </span>\n\n @for (section of getToolPropertySections(tool, propFilter); track section.key) {\n <details class=\"prop-section\" [open]=\"section.open\"\n (toggle)=\"onPropertySectionToggle(tool, section.key, $event)\">\n <summary class=\"prop-section-title\">{{ section.label }}</summary>\n <ul class=\"props\">\n @for (toolProp of section.props; track toolProp.key) {\n <li>\n @if (!toolProp.value.hideCaption) {\n <span>{{ toolProp.value?.propertyCaption ||\n toolProp.key[0].toUpperCase() + toolProp.key.slice(1)\n }}</span>\n }\n <br />\n @if (toolProp.value.type == 'button') {\n <p-button (click)=\"toolProp.value.callback(tool.inputs, toolProp.key, null, tool)\"\n class=\"k-button\" [style]=\"{width: '100%'}\">\n {{toolProp.value.propertyCaption}}\n </p-button>\n }\n @if (toolProp.value.type == 'metaEditor' &&\n tool.inputs['componentRef']?.value?.component) {\n <wuic-metadata-editor [hardcodedDatasource]=\"tool.inputs['componentRef']?.value?.component\"\n [saveCallback]=\"metaEditorSave\"></wuic-metadata-editor>\n }\n @if (toolProp.value.type == 'boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"tool.inputs[toolProp.key]\" />\n }\n @if (toolProp.value.type == 'numberToArray') {\n <input style=\"width: 100%;\" type=\"number\" pInputText [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'txt_area') {\n <textarea style=\"width: 100%;\" [(ngModel)]=\"tool.inputs[toolProp.key]\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\"></textarea>\n }\n @if (toolProp.value.type == 'string') {\n <input style=\"width: 100%;\" type=\"text\" pInputText [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'color') {\n <p-colorPicker [ngModel]=\"getDesignerColorPickerHex(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorPickerHexChange($event, tool, toolProp)\" appendTo=\"body\" />\n <div class=\"designer-color-alpha-row\">\n <span class=\"designer-color-alpha-label\">{{ 'designer.alpha' | translate }}</span>\n <input type=\"range\" min=\"0\" max=\"1\" step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n <input type=\"number\" min=\"0\" max=\"1\" step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n </div>\n <input type=\"text\" pInputText [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'dictionary' && !toolProp.value.async) {\n @if (toolProp.key == 'cssFile') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"availableProjectCssFiles\"\n [ngModel]=\"tool.inputs[toolProp.key]\" (ngModelChange)=\"onCssFileChanged($event, tool)\" />\n } @else if (toolProp.key == 'cssClass') {\n <p-multiSelect [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getCssClassOptionsForTool(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"onCssClassChanged($event, tool)\" [filter]=\"true\" [virtualScroll]=\"true\"\n [virtualScrollItemSize]=\"38\" scrollHeight=\"260px\" [showToggleAll]=\"false\" display=\"chip\"\n [maxSelectedLabels]=\"3\" [selectedItemsLabel]=\"'{0} selected'\">\n </p-multiSelect>\n } @else if ((tool.name == 'SELECT' || tool.name == 'MULTISELECT' || tool.name == 'UL') &&\n (toolProp.key == 'valueField' || toolProp.key == 'textField')) {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getDatasourceColumnOptions(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n } @else if (tool.name == 'LABEL' && toolProp.key == 'displayField') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getDatasourceColumnOptions(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n } @else {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"toolProp.value.values\"\n [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n }\n @if (toolProp.value.type == 'dictionary' && toolProp.value.async) {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"toolProp.value.values\"\n [ngModel]=\"tool.inputs[toolProp.key] | async\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (tool.name == 'DATAREPEATER' && toolProp.key == 'action' &&\n canOpenArchetypeConfigurator(tool)) {\n <button style=\"margin-top: 8px;\" (click)=\"openArchetypeConfigurator(tool)\">\n {{ 'designer.configure' | translate }} {{ (tool.inputs['action'] | async) || '' }}\n </button>\n }\n @if (toolProp.value.type == 'dropped-component-list') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [placeholder]=\"'select.component' | translate\" [options]=\"elementFilter(toolProp)\"\n [ngModel]=\"getDroppedComponentListModel(tool, toolProp)\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" optionLabel=\"uniqueName\"\n dataKey=\"uniqueName\" />\n }\n @if (toolProp.value.type == 'autocomplete') {\n <p-autoComplete [style]=\"{width: '100%'}\" appendTo=\"body\"\n [ngModel]=\"tool.inputs[toolProp.key] | async\" [forceSelection]=\"true\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" [suggestions]=\"tool.suggestions\"\n [optionLabel]=\"toolProp.value.displayField\" [optionValue]=\"toolProp.value.valueField\"\n (completeMethod)=\"search($event, tool, toolProp)\" [dropdown]=\"true\" dropdownMode=\"current\"\n [multiple]=\"toolProp.value.multiple\" />\n }\n @if (toolProp.value.type == 'propertyTree' && shouldShowPropertyTree(tool)) {\n <ul>\n @for (item of $any(tool.inputs[toolProp.key] | async); track item) {\n <li style=\"padding: 0; margin: 0;\">\n @if (item.col && tool.inputs['customProps_' + (tool.inputs['action'] | async)])\n {\n <wuic-field-editor [field]=\"item.col\"\n [record]=\"tool.inputs['customProps_' + (tool.inputs['action'] | async)]\"\n [metaInfo]=\"tool.inputs['datasource']?.component?.value?.metaInfo\"\n [triggerProp]=\"tool.inputs['action']\"></wuic-field-editor>\n }\n </li>\n }\n </ul>\n }\n </li>\n }\n </ul>\n </details>\n }\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate>\n <div class=\"hierarchy-panel\">\n <div class=\"hierarchy-panel-title\">{{ 'designer.canvas_hierarchy' | translate }}</div>\n <div class=\"hierarchy-tree-wrap\">\n <p-tree [value]=\"hierarchyTreeNodes\" [draggableNodes]=\"true\" [droppableNodes]=\"true\"\n selectionMode=\"single\" [(selection)]=\"hierarchySelection\"\n (onNodeSelect)=\"onHierarchyNodeSelect($event)\" draggableScope=\"designer-hierarchy\"\n droppableScope=\"designer-hierarchy\" (onNodeDrop)=\"onHierarchyNodeDrop($event)\">\n <ng-template let-node pTemplate=\"default\">\n <span class=\"hierarchy-node-label\" [class.active]=\"isHierarchyNodeSelected(node)\"\n (mouseenter)=\"onHierarchyNodeMouseEnter(node)\" (mouseleave)=\"onHierarchyNodeMouseLeave()\"\n (contextmenu)=\"showHierarchyNodeContextMenu($event, node, hierarchyCtxMenu)\">\n {{ node.label }}\n </span>\n </ng-template>\n </p-tree>\n </div>\n <p-contextMenu #hierarchyCtxMenu [model]=\"hierarchyCtxItems\" appendTo=\"body\" />\n </div>\n </ng-template>\n </p-splitter>\n </ng-template>\n </p-splitter>\n </ng-template>\n <ng-template pTemplate>\n <div class=\"col dashboard-design\" [class.designer-hide-datasources]=\"hideDatasourcesInCanvas\"\n [class.designer-snap-grid]=\"snapToGridEnabled\" [style.--wuic-grid-size.px]=\"gridSize\" pDroppable\n (onDrop)=\"drop($event)\" #canvas (mousedown)=\"onCanvasMouseDown($event)\"\n (contextmenu)=\"showCtx($event, this)\">\n <wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\n @if (rubberBandVisible) {\n <div class=\"designer-selection-rect\" [style.left]=\"rubberBandStyle.left\" [style.top]=\"rubberBandStyle.top\"\n [style.width]=\"rubberBandStyle.width\" [style.height]=\"rubberBandStyle.height\"></div>\n }\n <p-contextMenu [target]=\"canvas\" [model]=\"ctxItems | async\" appendTo=\"body\" />\n </div>\n </ng-template>\n </p-splitter>\n </div>\n <div class=\"designer-footer\">\n <div class=\"designer-footer-label\">{{ 'designer.items' | translate }}:</div>\n <div class=\"designer-footer-list\">\n @for (item of droppedDashboardItems; track item.uniqueName) {\n <button type=\"button\" class=\"designer-footer-item\" [class.active]=\"tool?.uniqueName === item?.uniqueName\"\n [attr.data-designer-unique-name]=\"item?.uniqueName\" (mouseenter)=\"setFooterHoverHighlight(item)\"\n (mouseleave)=\"clearFooterHoverHighlight()\" (click)=\"selectDashboardItem(item)\"\n (contextmenu)=\"showFooterContextMenu($event, item, footerCtxMenu)\">\n {{ getDroppedDashboardItemLabel(item) }}\n </button>\n }\n </div>\n <p-contextMenu #footerCtxMenu [model]=\"footerCtxItems\" appendTo=\"body\" />\n </div>\n</div>\n}\n\n@if (noEdit) {\n<wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\n}\n\n<wuic-archetype-configurator [visible]=\"showArchetypeConfigurator\"\n (visibleChange)=\"onArchetypeConfigVisibleChange($event)\" [archetype]=\"getActiveArchetypeConfig()\"\n [metaInfo]=\"getArchetypeConfigMetaInfoForTool(archetypeConfigTool)\"\n [value]=\"getArchetypeConfigValueForTool(archetypeConfigTool)\" (applyConfig)=\"onArchetypeConfigApply($event)\">\n</wuic-archetype-configurator>\n\n<wuic-css-sheet-editor [visible]=\"showCssSheetEditor\" (visibleChange)=\"onCssSheetEditorVisibleChange($event)\"\n [sheets]=\"dashboardCssSheets\" [selectedSheetPath]=\"selectedCssEditorSheetPath\" [assetsFolder]=\"currentDashboardRoute\"\n [styleProps]=\"getCssEditorStyleProps()\" (applyEditor)=\"onCssSheetEditorApply($event)\">\n</wuic-css-sheet-editor>\n\n<p-dialog [header]=\"'designer.reopen_dashboard' | translate\" [(visible)]=\"reopenDashboardDialogVisible\" [modal]=\"true\"\n [closable]=\"true\" [draggable]=\"false\" [resizable]=\"false\" [appendTo]=\"'body'\" [style]=\"{ width: '34rem' }\"\n (onHide)=\"cancelReopenDashboardDialog()\">\n <div class=\"route-popup-form\">\n <label for=\"designer-reopen-select\">{{ 'designer.existing_dashboards' | translate }}</label>\n <p-select inputId=\"designer-reopen-select\" [options]=\"savedDashboardOptions\" optionLabel=\"label\" optionValue=\"value\"\n [(ngModel)]=\"reopenDialogSelectedDashboardRoute\" [filter]=\"true\" [showClear]=\"true\" [style]=\"{ width: '100%' }\"\n appendTo=\"body\" />\n\n <div class=\"route-popup-actions\">\n <button type=\"button\" class=\"route-popup-btn\" (click)=\"cancelReopenDashboardDialog()\">{{ 'cancel' | translate\n }}</button>\n <button type=\"button\" class=\"route-popup-btn route-popup-btn-primary\" (click)=\"confirmReopenDashboardDialog()\"\n [disabled]=\"!reopenDialogSelectedDashboardRoute\">{{ 'designer.reopen' | translate }}</button>\n </div>\n </div>\n</p-dialog>", styles: [":host{display:block;width:100%;height:100%;min-width:0}.designer-layout{display:grid;grid-template-rows:auto minmax(0,1fr) auto;height:100%;min-height:0;width:100%;min-width:0}.designer-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:8px;border:1px solid inherit;border-radius:10px;background:transparent;padding:10px 12px;margin-bottom:8px}.designer-current-dashboard{min-width:220px;font-size:.86rem;font-weight:700;color:inherit}.designer-toolbar-spacer{flex:1 1 auto;min-width:16px}.designer-toolbar-menu-group{display:inline-flex}.designer-toolbar-menu-group button{height:32px;border:1px solid #2f67d8;border-radius:6px;background:#2f67d8;color:#fff;padding:0 10px;font-size:.82rem;cursor:pointer}.designer-toolbar-menu-group button[disabled]{opacity:.6;cursor:not-allowed}.designer-main{min-height:0;min-width:0;width:100%;overflow:hidden;direction:ltr}.designer-main-splitter{height:100%;width:100%;min-width:0;direction:ltr}.designer-toolbox{font-size:3rem}.designer-toolbox ul{list-style-type:none;padding:0;margin:0;width:100%}.designer-toolbox li{float:left;margin-left:5px;margin-top:5px}.designer-toolbox .tool-groups{display:block}.designer-toolbox .tool-group-item{float:none;margin-left:0;margin-top:10px;clear:both}.designer-toolbox .tool-group-title{font-size:.8rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;opacity:.7;margin:0 0 4px 6px}.designer-toolbox .tool-group-list{display:flex;flex-wrap:wrap;align-items:flex-start;gap:4px}.designer-toolbox .tool-group-list li{float:none;margin-left:0;margin-top:0}.designer-toolbox .props{font-size:1rem}.designer-toolbox .props li{float:none;padding-bottom:15px}.designer-toolbox .prop-section{width:100%;border:1px solid inherit;border-radius:6px;margin-top:8px;background:transparent;padding:6px 8px 2px}.designer-toolbox .prop-section-title{font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;cursor:pointer;color:inherit;margin-bottom:6px}.palette-panel{height:100%;overflow:auto;width:100%}.designer-color-alpha-row{display:flex;align-items:center;gap:8px;margin-top:6px;margin-bottom:6px}.designer-color-alpha-label{font-size:.8rem;min-width:40px}.designer-color-alpha-row input[type=range]{flex:1 1 auto;min-width:90px}.designer-color-alpha-row input[type=number]{width:72px}.properties-panel{height:100%;overflow:hidden;width:100%;display:flex;flex-direction:column;min-height:0;padding-right:10px;padding-left:10px;padding-top:10px}.properties-panel>.designer-toolbox{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:stable}:host ::ng-deep .designer-left-bottom-splitter .p-splitterpanel{min-height:0!important;overflow:hidden!important}.hierarchy-panel{height:100%;width:100%;min-height:0;display:flex;flex-direction:column;overflow:hidden;padding:6px}.hierarchy-panel-title{font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#4b5563;margin:0 0 6px}.hierarchy-tree-wrap{flex:1 1 auto;min-height:0;border:1px solid inherit;border-radius:6px;background:transparent;overflow:auto;padding:4px}:host ::ng-deep .hierarchy-tree-wrap .p-tree{border:none;padding:0;height:100%;background:transparent}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content{border:1px solid transparent;border-radius:4px;background:transparent!important;color:inherit!important;padding:0!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content.p-highlight{border-color:transparent!important;background:transparent!important;color:inherit!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content:hover{background:transparent!important;color:inherit!important}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label{display:inline-block;border:1px solid inherit;background:transparent;color:inherit;border-radius:4px;padding:2px 8px;font-size:.8rem;line-height:1.25rem;cursor:pointer}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label:hover{border-color:#94a3b8}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label.active{border-color:#3b82f6!important;background:#eff6ff!important;color:#1d4ed8!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content.p-highlight .hierarchy-node-label{border-color:#3b82f6!important;background:#eff6ff!important;color:#1d4ed8!important}.designer-hierarchy-node{cursor:pointer;border:1px solid transparent;border-radius:4px;padding:2px 6px;font-size:.82rem;line-height:1.25rem}.designer-hierarchy-node-label{cursor:pointer;display:inline-block;width:100%}.designer-hierarchy-node.active{border-color:#3b82f6;background:#eff6ff;color:#1d4ed8}.designer-footer-item.designer-tree-hover-target{border-color:#3b82f6!important;outline:1px solid #3b82f6!important;outline-offset:-1px}.dashboard-design{height:100%;min-height:0;min-width:0;width:100%;overflow:auto;direction:ltr;position:relative}.designer-selection-rect{position:absolute;border:1px dashed #3b82f6;background:#3b82f61f;pointer-events:none;z-index:10000}:host ::ng-deep .designer-multi-selected{outline:2px solid #3b82f6!important;outline-offset:1px}:host ::ng-deep .dashboard-design.designer-hide-datasources .datasource-descriptor{display:none!important}.current-dashboard-title{font-weight:600;margin-right:12px}.designer-footer{display:flex;align-items:center;gap:8px;padding:6px 8px;border-top:1px solid inherit;background:transparent;min-height:36px;flex:0 0 auto;width:100%;overflow:auto}.designer-footer-label{font-size:.85rem;font-weight:600;color:inherit;white-space:nowrap}.designer-footer-list{display:flex;align-items:center;gap:6px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;width:100%}.designer-footer-item{border:1px solid inherit;background:transparent;color:inherit;border-radius:4px;padding:2px 8px;font-size:.8rem;line-height:1.25rem;cursor:pointer;white-space:nowrap}.designer-footer-item.active{border-color:#3b82f6;background:transparent;color:#1d4ed8}:host ::ng-deep .designer-footer-hover-target{border-color:#3b82f6!important;outline:1px solid #3b82f6!important;outline-offset:-1px;box-shadow:inset 0 0 0 1px #3b82f6!important}.route-popup-form{display:flex;flex-direction:column;gap:8px}.route-popup-form label{font-size:.85rem;font-weight:600;color:#2f3f58}.route-popup-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.route-popup-btn{border:1px solid inherit;background:transparent;color:inherit;border-radius:6px;padding:7px 12px;font-size:.85rem;cursor:pointer}.route-popup-btn-primary{border-color:#2f67d8;background:#2f67d8;color:#fff}.p-colorpicker{border:1px solid black;border-radius:4px}.dashboard-design.designer-snap-grid{background-image:linear-gradient(to right,rgba(128,128,128,.16) 1px,transparent 1px),linear-gradient(to bottom,rgba(128,128,128,.16) 1px,transparent 1px);background-size:var(--wuic-grid-size, 10px) var(--wuic-grid-size, 10px)}\n"] }]
13215
+ args: [{ selector: 'wuic-designer', imports: [NgClass, TranslateModule, AsyncPipe, FormsModule, SplitterModule, DragDropModule, SelectModule, ColorPickerModule, AutoCompleteModule, DashboardComponent, FieldEditorComponent, ContextMenuModule, MetadataEditorComponent, MenubarModule, ArchetypeConfiguratorComponent, ButtonModule, MultiSelectModule, CssSheetEditorComponent, MenuModule, DialogModule, TreeModule], providers: [TreeDragDropService], template: "@if (!noEdit) {\n<div class=\"designer-layout\">\n <div class=\"designer-toolbar\">\n <div class=\"designer-current-dashboard\">{{ currentDashboardTitle }}</div>\n\n <div class=\"designer-toolbar-spacer\"></div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"undo()\" [disabled]=\"!canUndo\">{{ 'designer.undo' | translate }}</button>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"redo()\" [disabled]=\"!canRedo\">{{ 'designer.redo' | translate }}</button>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" data-testid=\"designer-actions-menu-btn\" (click)=\"refreshGraphActionsMenuItems(); graphActionsMenu.toggle($event)\">{{ 'designer.actions_menu' | translate }}</button>\n <p-menu #graphActionsMenu [popup]=\"true\" [model]=\"graphActionsMenuItems\" appendTo=\"body\"></p-menu>\n </div>\n\n <div class=\"designer-toolbar-menu-group\">\n <button type=\"button\" (click)=\"openCurrentDashboardInNewTab()\" [disabled]=\"!currentDashboardRoute\">{{\n 'designer.open_current_dashboard' | translate }}</button>\n </div>\n </div>\n <div class=\"designer-main\">\n <p-splitter [style]=\"{ height: '100%' }\" [panelSizes]=\"[15, 85]\" styleClass=\"designer-main-splitter\">\n <ng-template pTemplate>\n <p-splitter layout=\"vertical\" [style]=\"{ height: '100%', width: '100%' }\" [panelSizes]=\"[35, 65]\"\n [minSizes]=\"[20, 30]\" styleClass=\"designer-left-splitter\">\n <ng-template pTemplate>\n <div class=\"col flex designer-toolbox palette-panel\">\n <ul class=\"tool-groups\">\n @for (toolGroup of availableToolGroups; track toolGroup.group) {\n <li class=\"tool-group-item\">\n <div class=\"tool-group-title\">{{ toolGroup.group }}</div>\n <ul class=\"tool-group-list\">\n @for (tool of toolGroup.tools; track tool) {\n <li pDraggable (onDragStart)=\"dragStart(tool)\" (onDragEnd)=\"dragEnd()\" (onDrag)=\"onDrag($event)\"\n (dblclick)=\"dropToolAtRoot(tool)\">\n <i [ngClass]=\"tool.icon\" [title]=\"tool.name\"></i>\n </li>\n }\n </ul>\n </li>\n }\n </ul>\n </div>\n </ng-template>\n <ng-template pTemplate>\n <p-splitter layout=\"vertical\" [style]=\"{ height: '100%', width: '100%' }\" [panelSizes]=\"[68, 32]\"\n [minSizes]=\"[35, 20]\" styleClass=\"designer-left-bottom-splitter\">\n <ng-template pTemplate>\n <div class=\"properties-panel\">\n <p-select [style]=\"{width: '100%'}\" [options]=\"flattenedDashboardElements\" [(ngModel)]=\"tool\"\n optionLabel=\"uniqueName\" dataKey=\"componentId\" appendTo=\"body\" />\n <div class=\"designer-toolbox\">\n\n <span style=\"width: 100%;\">\n <input type=\"text\" style=\"width: calc(100% - 30px);\" [(ngModel)]=\"propFilter\"\n [placeholder]=\"'prop.filter' | translate\" />\n <button style=\"width: 25px\" (click)=\"clearPropFilter()\">X</button>\n </span>\n\n @for (section of getToolPropertySections(tool, propFilter); track section.key) {\n <details class=\"prop-section\" [open]=\"section.open\"\n (toggle)=\"onPropertySectionToggle(tool, section.key, $event)\">\n <summary class=\"prop-section-title\">{{ section.label }}</summary>\n <ul class=\"props\">\n @for (toolProp of section.props; track toolProp.key) {\n <li>\n @if (!toolProp.value.hideCaption) {\n <span>{{ toolProp.value?.propertyCaption ||\n toolProp.key[0].toUpperCase() + toolProp.key.slice(1)\n }}</span>\n }\n <br />\n @if (toolProp.value.type == 'button') {\n <p-button (click)=\"toolProp.value.callback(tool.inputs, toolProp.key, null, tool)\"\n class=\"k-button\" [style]=\"{width: '100%'}\">\n {{toolProp.value.propertyCaption}}\n </p-button>\n }\n @if (toolProp.value.type == 'metaEditor' &&\n tool.inputs['componentRef']?.value?.component) {\n <wuic-metadata-editor [hardcodedDatasource]=\"tool.inputs['componentRef']?.value?.component\"\n [saveCallback]=\"metaEditorSave\"></wuic-metadata-editor>\n }\n @if (toolProp.value.type == 'boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"tool.inputs[toolProp.key]\" />\n }\n @if (toolProp.value.type == 'numberToArray') {\n <input style=\"width: 100%;\" type=\"number\" pInputText [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'txt_area') {\n <textarea style=\"width: 100%;\" [(ngModel)]=\"tool.inputs[toolProp.key]\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\"></textarea>\n }\n @if (toolProp.value.type == 'string') {\n <!-- updateOn:blur come il txt_area sopra: senza, setValue() scatta\n A OGNI CARATTERE e buildSerializedDashboardElements ri-serializza\n l'intero tree (history da centinaia di KB per tasto, P-D1). -->\n <input style=\"width: 100%;\" type=\"text\" pInputText [(ngModel)]=\"tool.inputs[toolProp.key]\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'color') {\n <p-colorPicker [ngModel]=\"getDesignerColorPickerHex(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorPickerHexChange($event, tool, toolProp)\" appendTo=\"body\" />\n <div class=\"designer-color-alpha-row\">\n <span class=\"designer-color-alpha-label\">{{ 'designer.alpha' | translate }}</span>\n <input type=\"range\" min=\"0\" max=\"1\" step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n <input type=\"number\" min=\"0\" max=\"1\" step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n </div>\n <input type=\"text\" pInputText [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (toolProp.value.type == 'dictionary' && !toolProp.value.async) {\n @if (toolProp.key == 'cssFile') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"availableProjectCssFiles\"\n [ngModel]=\"tool.inputs[toolProp.key]\" (ngModelChange)=\"onCssFileChanged($event, tool)\" />\n } @else if (toolProp.key == 'cssClass') {\n <p-multiSelect [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getCssClassOptionsForTool(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"onCssClassChanged($event, tool)\" [filter]=\"true\" [virtualScroll]=\"true\"\n [virtualScrollItemSize]=\"38\" scrollHeight=\"260px\" [showToggleAll]=\"false\" display=\"chip\"\n [maxSelectedLabels]=\"3\" [selectedItemsLabel]=\"'{0} selected'\">\n </p-multiSelect>\n } @else if ((tool.name == 'SELECT' || tool.name == 'MULTISELECT' || tool.name == 'UL') &&\n (toolProp.key == 'valueField' || toolProp.key == 'textField')) {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getDatasourceColumnOptions(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n } @else if (tool.name == 'LABEL' && toolProp.key == 'displayField') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [options]=\"getDatasourceColumnOptions(tool)\" [ngModel]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n } @else {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"toolProp.value.values\"\n [(ngModel)]=\"tool.inputs[toolProp.key]\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n }\n @if (toolProp.value.type == 'dictionary' && toolProp.value.async) {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\" [options]=\"toolProp.value.values\"\n [ngModel]=\"tool.inputs[toolProp.key] | async\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" />\n }\n @if (tool.name == 'DATAREPEATER' && toolProp.key == 'action' &&\n canOpenArchetypeConfigurator(tool)) {\n <button style=\"margin-top: 8px;\" (click)=\"openArchetypeConfigurator(tool)\">\n {{ 'designer.configure' | translate }} {{ (tool.inputs['action'] | async) || '' }}\n </button>\n }\n @if (toolProp.value.type == 'dropped-component-list') {\n <p-select [style]=\"{width: '100%'}\" appendTo=\"body\"\n [placeholder]=\"'select.component' | translate\" [options]=\"elementFilter(toolProp)\"\n [ngModel]=\"getDroppedComponentListModel(tool, toolProp)\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" optionLabel=\"uniqueName\"\n dataKey=\"uniqueName\" />\n }\n @if (toolProp.value.type == 'autocomplete') {\n <p-autoComplete [style]=\"{width: '100%'}\" appendTo=\"body\"\n [ngModel]=\"tool.inputs[toolProp.key] | async\" [forceSelection]=\"true\"\n (ngModelChange)=\"setValue($event, tool, toolProp)\" [suggestions]=\"tool.suggestions\"\n [optionLabel]=\"toolProp.value.displayField\" [optionValue]=\"toolProp.value.valueField\"\n (completeMethod)=\"search($event, tool, toolProp)\" [dropdown]=\"true\" dropdownMode=\"current\"\n [multiple]=\"toolProp.value.multiple\" />\n }\n @if (toolProp.value.type == 'propertyTree' && shouldShowPropertyTree(tool)) {\n <ul>\n @for (item of $any(tool.inputs[toolProp.key] | async); track item) {\n <li style=\"padding: 0; margin: 0;\">\n @if (item.col && tool.inputs['customProps_' + (tool.inputs['action'] | async)])\n {\n <wuic-field-editor [field]=\"item.col\"\n [record]=\"tool.inputs['customProps_' + (tool.inputs['action'] | async)]\"\n [metaInfo]=\"tool.inputs['datasource']?.component?.value?.metaInfo\"\n [triggerProp]=\"tool.inputs['action']\"></wuic-field-editor>\n }\n </li>\n }\n </ul>\n }\n </li>\n }\n </ul>\n </details>\n }\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate>\n <div class=\"hierarchy-panel\">\n <div class=\"hierarchy-panel-title\">{{ 'designer.canvas_hierarchy' | translate }}</div>\n <div class=\"hierarchy-tree-wrap\">\n <p-tree [value]=\"hierarchyTreeNodes\" [draggableNodes]=\"true\" [droppableNodes]=\"true\"\n selectionMode=\"single\" [(selection)]=\"hierarchySelection\"\n (onNodeSelect)=\"onHierarchyNodeSelect($event)\" draggableScope=\"designer-hierarchy\"\n droppableScope=\"designer-hierarchy\" (onNodeDrop)=\"onHierarchyNodeDrop($event)\">\n <ng-template let-node pTemplate=\"default\">\n <span class=\"hierarchy-node-label\" [class.active]=\"isHierarchyNodeSelected(node)\"\n (mouseenter)=\"onHierarchyNodeMouseEnter(node)\" (mouseleave)=\"onHierarchyNodeMouseLeave()\"\n (contextmenu)=\"showHierarchyNodeContextMenu($event, node, hierarchyCtxMenu)\">\n {{ node.label }}\n </span>\n </ng-template>\n </p-tree>\n </div>\n <p-contextMenu #hierarchyCtxMenu [model]=\"hierarchyCtxItems\" appendTo=\"body\" />\n </div>\n </ng-template>\n </p-splitter>\n </ng-template>\n </p-splitter>\n </ng-template>\n <ng-template pTemplate>\n <div class=\"col dashboard-design\" [class.designer-hide-datasources]=\"hideDatasourcesInCanvas\"\n [class.designer-snap-grid]=\"snapToGridEnabled\" [style.--wuic-grid-size.px]=\"gridSize\" pDroppable\n (onDrop)=\"drop($event)\" #canvas (mousedown)=\"onCanvasMouseDown($event)\"\n (contextmenu)=\"showCtx($event, this)\">\n <wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\n @if (rubberBandVisible) {\n <div class=\"designer-selection-rect\" [style.left]=\"rubberBandStyle.left\" [style.top]=\"rubberBandStyle.top\"\n [style.width]=\"rubberBandStyle.width\" [style.height]=\"rubberBandStyle.height\"></div>\n }\n <p-contextMenu [target]=\"canvas\" [model]=\"ctxItems | async\" appendTo=\"body\" />\n </div>\n </ng-template>\n </p-splitter>\n </div>\n <div class=\"designer-footer\">\n <div class=\"designer-footer-label\">{{ 'designer.items' | translate }}:</div>\n <div class=\"designer-footer-list\">\n @for (item of droppedDashboardItems; track item.uniqueName) {\n <button type=\"button\" class=\"designer-footer-item\" [class.active]=\"tool?.uniqueName === item?.uniqueName\"\n [attr.data-designer-unique-name]=\"item?.uniqueName\" (mouseenter)=\"setFooterHoverHighlight(item)\"\n (mouseleave)=\"clearFooterHoverHighlight()\" (click)=\"selectDashboardItem(item)\"\n (contextmenu)=\"showFooterContextMenu($event, item, footerCtxMenu)\">\n {{ getDroppedDashboardItemLabel(item) }}\n </button>\n }\n </div>\n <p-contextMenu #footerCtxMenu [model]=\"footerCtxItems\" appendTo=\"body\" />\n </div>\n</div>\n}\n\n@if (noEdit) {\n<wuic-dashboard [dashboardElements]=\"dashboardElements\" [widgetChrome]=\"dashboardWidgetChrome\"></wuic-dashboard>\n}\n\n<wuic-archetype-configurator [visible]=\"showArchetypeConfigurator\"\n (visibleChange)=\"onArchetypeConfigVisibleChange($event)\" [archetype]=\"getActiveArchetypeConfig()\"\n [metaInfo]=\"getArchetypeConfigMetaInfoForTool(archetypeConfigTool)\"\n [value]=\"getArchetypeConfigValueForTool(archetypeConfigTool)\" (applyConfig)=\"onArchetypeConfigApply($event)\">\n</wuic-archetype-configurator>\n\n<wuic-css-sheet-editor [visible]=\"showCssSheetEditor\" (visibleChange)=\"onCssSheetEditorVisibleChange($event)\"\n [sheets]=\"dashboardCssSheets\" [selectedSheetPath]=\"selectedCssEditorSheetPath\" [assetsFolder]=\"currentDashboardRoute\"\n [styleProps]=\"getCssEditorStyleProps()\" (applyEditor)=\"onCssSheetEditorApply($event)\">\n</wuic-css-sheet-editor>\n\n<p-dialog [header]=\"'designer.reopen_dashboard' | translate\" [(visible)]=\"reopenDashboardDialogVisible\" [modal]=\"true\"\n [closable]=\"true\" [draggable]=\"false\" [resizable]=\"false\" [appendTo]=\"'body'\" [style]=\"{ width: '34rem' }\"\n (onHide)=\"cancelReopenDashboardDialog()\">\n <div class=\"route-popup-form\">\n <label for=\"designer-reopen-select\">{{ 'designer.existing_dashboards' | translate }}</label>\n <p-select inputId=\"designer-reopen-select\" [options]=\"savedDashboardOptions\" optionLabel=\"label\" optionValue=\"value\"\n [(ngModel)]=\"reopenDialogSelectedDashboardRoute\" [filter]=\"true\" [showClear]=\"true\" [style]=\"{ width: '100%' }\"\n appendTo=\"body\" />\n\n <div class=\"route-popup-actions\">\n <button type=\"button\" class=\"route-popup-btn\" (click)=\"cancelReopenDashboardDialog()\">{{ 'cancel' | translate\n }}</button>\n <button type=\"button\" class=\"route-popup-btn route-popup-btn-primary\" (click)=\"confirmReopenDashboardDialog()\"\n [disabled]=\"!reopenDialogSelectedDashboardRoute\">{{ 'designer.reopen' | translate }}</button>\n </div>\n </div>\n</p-dialog>", styles: [":host{display:block;width:100%;height:100%;min-width:0}.designer-layout{display:grid;grid-template-rows:auto minmax(0,1fr) auto;height:100%;min-height:0;width:100%;min-width:0}.designer-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:8px;border:1px solid inherit;border-radius:10px;background:transparent;padding:10px 12px;margin-bottom:8px}.designer-current-dashboard{min-width:220px;font-size:.86rem;font-weight:700;color:inherit}.designer-toolbar-spacer{flex:1 1 auto;min-width:16px}.designer-toolbar-menu-group{display:inline-flex}.designer-toolbar-menu-group button{height:32px;border:1px solid #2f67d8;border-radius:6px;background:#2f67d8;color:#fff;padding:0 10px;font-size:.82rem;cursor:pointer}.designer-toolbar-menu-group button[disabled]{opacity:.6;cursor:not-allowed}.designer-main{min-height:0;min-width:0;width:100%;overflow:hidden;direction:ltr}.designer-main-splitter{height:100%;width:100%;min-width:0;direction:ltr}.designer-toolbox{font-size:3rem}.designer-toolbox ul{list-style-type:none;padding:0;margin:0;width:100%}.designer-toolbox li{float:left;margin-left:5px;margin-top:5px}.designer-toolbox .tool-groups{display:block}.designer-toolbox .tool-group-item{float:none;margin-left:0;margin-top:10px;clear:both}.designer-toolbox .tool-group-title{font-size:.8rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;opacity:.7;margin:0 0 4px 6px}.designer-toolbox .tool-group-list{display:flex;flex-wrap:wrap;align-items:flex-start;gap:4px}.designer-toolbox .tool-group-list li{float:none;margin-left:0;margin-top:0}.designer-toolbox .props{font-size:1rem}.designer-toolbox .props li{float:none;padding-bottom:15px}.designer-toolbox .prop-section{width:100%;border:1px solid inherit;border-radius:6px;margin-top:8px;background:transparent;padding:6px 8px 2px}.designer-toolbox .prop-section-title{font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;cursor:pointer;color:inherit;margin-bottom:6px}.palette-panel{height:100%;overflow:auto;width:100%}.designer-color-alpha-row{display:flex;align-items:center;gap:8px;margin-top:6px;margin-bottom:6px}.designer-color-alpha-label{font-size:.8rem;min-width:40px}.designer-color-alpha-row input[type=range]{flex:1 1 auto;min-width:90px}.designer-color-alpha-row input[type=number]{width:72px}.properties-panel{height:100%;overflow:hidden;width:100%;display:flex;flex-direction:column;min-height:0;padding-right:10px;padding-left:10px;padding-top:10px}.properties-panel>.designer-toolbox{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:stable}:host ::ng-deep .designer-left-bottom-splitter .p-splitterpanel{min-height:0!important;overflow:hidden!important}.hierarchy-panel{height:100%;width:100%;min-height:0;display:flex;flex-direction:column;overflow:hidden;padding:6px}.hierarchy-panel-title{font-size:.82rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#4b5563;margin:0 0 6px}.hierarchy-tree-wrap{flex:1 1 auto;min-height:0;border:1px solid inherit;border-radius:6px;background:transparent;overflow:auto;padding:4px}:host ::ng-deep .hierarchy-tree-wrap .p-tree{border:none;padding:0;height:100%;background:transparent}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content{border:1px solid transparent;border-radius:4px;background:transparent!important;color:inherit!important;padding:0!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content.p-highlight{border-color:transparent!important;background:transparent!important;color:inherit!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content:hover{background:transparent!important;color:inherit!important}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label{display:inline-block;border:1px solid inherit;background:transparent;color:inherit;border-radius:4px;padding:2px 8px;font-size:.8rem;line-height:1.25rem;cursor:pointer}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label:hover{border-color:#94a3b8}:host ::ng-deep .hierarchy-tree-wrap .hierarchy-node-label.active{border-color:#3b82f6!important;background:#eff6ff!important;color:#1d4ed8!important}:host ::ng-deep .hierarchy-tree-wrap .p-tree-node-content.p-highlight .hierarchy-node-label{border-color:#3b82f6!important;background:#eff6ff!important;color:#1d4ed8!important}.designer-hierarchy-node{cursor:pointer;border:1px solid transparent;border-radius:4px;padding:2px 6px;font-size:.82rem;line-height:1.25rem}.designer-hierarchy-node-label{cursor:pointer;display:inline-block;width:100%}.designer-hierarchy-node.active{border-color:#3b82f6;background:#eff6ff;color:#1d4ed8}.designer-footer-item.designer-tree-hover-target{border-color:#3b82f6!important;outline:1px solid #3b82f6!important;outline-offset:-1px}.dashboard-design{height:100%;min-height:0;min-width:0;width:100%;overflow:auto;direction:ltr;position:relative}.designer-selection-rect{position:absolute;border:1px dashed #3b82f6;background:#3b82f61f;pointer-events:none;z-index:10000}:host ::ng-deep .designer-multi-selected{outline:2px solid #3b82f6!important;outline-offset:1px}:host ::ng-deep .dashboard-design.designer-hide-datasources .datasource-descriptor{display:none!important}.current-dashboard-title{font-weight:600;margin-right:12px}.designer-footer{display:flex;align-items:center;gap:8px;padding:6px 8px;border-top:1px solid inherit;background:transparent;min-height:36px;flex:0 0 auto;width:100%;overflow:auto}.designer-footer-label{font-size:.85rem;font-weight:600;color:inherit;white-space:nowrap}.designer-footer-list{display:flex;align-items:center;gap:6px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;width:100%}.designer-footer-item{border:1px solid inherit;background:transparent;color:inherit;border-radius:4px;padding:2px 8px;font-size:.8rem;line-height:1.25rem;cursor:pointer;white-space:nowrap}.designer-footer-item.active{border-color:#3b82f6;background:transparent;color:#1d4ed8}:host ::ng-deep .designer-footer-hover-target{border-color:#3b82f6!important;outline:1px solid #3b82f6!important;outline-offset:-1px;box-shadow:inset 0 0 0 1px #3b82f6!important}.route-popup-form{display:flex;flex-direction:column;gap:8px}.route-popup-form label{font-size:.85rem;font-weight:600;color:#2f3f58}.route-popup-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.route-popup-btn{border:1px solid inherit;background:transparent;color:inherit;border-radius:6px;padding:7px 12px;font-size:.85rem;cursor:pointer}.route-popup-btn-primary{border-color:#2f67d8;background:#2f67d8;color:#fff}.p-colorpicker{border:1px solid black;border-radius:4px}.dashboard-design.designer-snap-grid{background-image:linear-gradient(to right,rgba(128,128,128,.16) 1px,transparent 1px),linear-gradient(to bottom,rgba(128,128,128,.16) 1px,transparent 1px);background-size:var(--wuic-grid-size, 10px) var(--wuic-grid-size, 10px)}\n"] }]
13298
13216
  }], ctorParameters: () => [{ type: i1$1.ActivatedRoute }, { type: DataProviderService }, { type: MetadataProviderService }, { type: UserInfoService }, { type: i0.ChangeDetectorRef }, { type: TranslationManagerService }, { type: MetadataEditorService }, { type: ChatbotHostRegistryService }, { type: WorkflowRuntimeMetadataService }], propDecorators: { onWindowHashChange: [{
13299
13217
  type: HostListener,
13300
13218
  args: ['window:hashchange']
@@ -13322,4 +13240,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
13322
13240
  }] } });
13323
13241
 
13324
13242
  export { DesignerComponent };
13325
- //# sourceMappingURL=wuic-framework-lib-designer.component-x10ZzUEy.mjs.map
13243
+ //# sourceMappingURL=wuic-framework-lib-designer.component-D6cbqNFg.mjs.map