wuic-framework-lib 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/fesm2022/wuic-framework-lib-code-editor.lazy.component-Bz--9_hc.mjs +70 -0
  2. package/fesm2022/wuic-framework-lib-core.mjs +1 -1
  3. package/fesm2022/{wuic-framework-lib-designer.component-B61jxcjI.mjs → wuic-framework-lib-designer.component-CJj2TAfG.mjs} +989 -360
  4. package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-CEdDCWJ0.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-Dvgs4lWp.mjs} +7 -7
  5. package/fesm2022/wuic-framework-lib-ui.mjs +1 -1
  6. package/fesm2022/wuic-framework-lib-wuic-framework-lib-CXZ0usmZ.mjs +102042 -0
  7. package/fesm2022/wuic-framework-lib.mjs +1 -1
  8. package/package.json +5 -2
  9. package/styles/styles.scss +35 -18
  10. package/types/wuic-framework-lib-core.d.ts +1 -1
  11. package/types/wuic-framework-lib-ui.d.ts +1 -1
  12. package/types/wuic-framework-lib.d.ts +4202 -433
  13. package/assets/wuic-framework-docs/screenshots/carousel-list__carousel-main__desktop.png +0 -0
  14. package/assets/wuic-framework-docs/screenshots/chart-list__chart-main__desktop.png +0 -0
  15. package/assets/wuic-framework-docs/screenshots/designer__designer-main__desktop.png +0 -0
  16. package/assets/wuic-framework-docs/screenshots/field-editor-widgets__field-editor-button-tab__desktop.png +0 -0
  17. package/assets/wuic-framework-docs/screenshots/field-editor-widgets__field-editor-lookup-tab__desktop.png +0 -0
  18. package/assets/wuic-framework-docs/screenshots/field-editor-widgets__field-editor-number-tab__desktop.png +0 -0
  19. package/assets/wuic-framework-docs/screenshots/field-editor-widgets__field-editor-upload-tab__desktop.png +0 -0
  20. package/assets/wuic-framework-docs/screenshots/field-widget-button__field-editor-button-tab__desktop.png +0 -0
  21. package/assets/wuic-framework-docs/screenshots/field-widget-lookup__field-editor-lookup-tab__desktop.png +0 -0
  22. package/assets/wuic-framework-docs/screenshots/field-widget-number__field-editor-number-tab__desktop.png +0 -0
  23. package/assets/wuic-framework-docs/screenshots/field-widget-upload__field-editor-upload-tab__desktop.png +0 -0
  24. package/assets/wuic-framework-docs/screenshots/index.json +0 -723
  25. package/assets/wuic-framework-docs/screenshots/list-grid__list-grid-main__desktop.png +0 -0
  26. package/assets/wuic-framework-docs/screenshots/manual__audit__01.png +0 -0
  27. package/assets/wuic-framework-docs/screenshots/manual__auth_login__01.png +0 -0
  28. package/assets/wuic-framework-docs/screenshots/manual__callback__01.png +0 -0
  29. package/assets/wuic-framework-docs/screenshots/manual__carousel__01.png +0 -0
  30. package/assets/wuic-framework-docs/screenshots/manual__custom_component__01.png +0 -0
  31. package/assets/wuic-framework-docs/screenshots/manual__designer__01.png +0 -0
  32. package/assets/wuic-framework-docs/screenshots/manual__grid__01.png +0 -0
  33. package/assets/wuic-framework-docs/screenshots/manual__grid__02.png +0 -0
  34. package/assets/wuic-framework-docs/screenshots/manual__grid_states__01.png +0 -0
  35. package/assets/wuic-framework-docs/screenshots/manual__grid_states__02.png +0 -0
  36. package/assets/wuic-framework-docs/screenshots/manual__in_memory_crud__01.png +0 -0
  37. package/assets/wuic-framework-docs/screenshots/manual__in_memory_crud__02.png +0 -0
  38. package/assets/wuic-framework-docs/screenshots/manual__install__01.png +0 -0
  39. package/assets/wuic-framework-docs/screenshots/manual__kanban__01.png +0 -0
  40. package/assets/wuic-framework-docs/screenshots/manual__manytomany__01.png +0 -0
  41. package/assets/wuic-framework-docs/screenshots/manual__manytomany__02.png +0 -0
  42. package/assets/wuic-framework-docs/screenshots/manual__map__01.png +0 -0
  43. package/assets/wuic-framework-docs/screenshots/manual__map__02.png +0 -0
  44. package/assets/wuic-framework-docs/screenshots/manual__menu__01.png +0 -0
  45. package/assets/wuic-framework-docs/screenshots/manual__menu__02.png +0 -0
  46. package/assets/wuic-framework-docs/screenshots/manual__menu__03.png +0 -0
  47. package/assets/wuic-framework-docs/screenshots/manual__metadata_context_editor__01.png +0 -0
  48. package/assets/wuic-framework-docs/screenshots/manual__metadata_context_editor__02.png +0 -0
  49. package/assets/wuic-framework-docs/screenshots/manual__notifications__01.png +0 -0
  50. package/assets/wuic-framework-docs/screenshots/manual__pivot_builder__01.png +0 -0
  51. package/assets/wuic-framework-docs/screenshots/manual__pivot_builder__02.png +0 -0
  52. package/assets/wuic-framework-docs/screenshots/manual__reporting__01.png +0 -0
  53. package/assets/wuic-framework-docs/screenshots/manual__reporting__02.png +0 -0
  54. package/assets/wuic-framework-docs/screenshots/manual__reporting__03.png +0 -0
  55. package/assets/wuic-framework-docs/screenshots/manual__reporting__04.png +0 -0
  56. package/assets/wuic-framework-docs/screenshots/manual__scheduler__01.png +0 -0
  57. package/assets/wuic-framework-docs/screenshots/manual__scheduler__02.png +0 -0
  58. package/assets/wuic-framework-docs/screenshots/manual__scheduler__03.png +0 -0
  59. package/assets/wuic-framework-docs/screenshots/manual__scheduling__01.png +0 -0
  60. package/assets/wuic-framework-docs/screenshots/manual__stili_colonna_edit__01.png +0 -0
  61. package/assets/wuic-framework-docs/screenshots/manual__templating__01.png +0 -0
  62. package/assets/wuic-framework-docs/screenshots/manual__templating__02.png +0 -0
  63. package/assets/wuic-framework-docs/screenshots/manual__templating__03.png +0 -0
  64. package/assets/wuic-framework-docs/screenshots/manual__tree__01.png +0 -0
  65. package/assets/wuic-framework-docs/screenshots/manual__validations__01.png +0 -0
  66. package/assets/wuic-framework-docs/screenshots/manual__validations__02.png +0 -0
  67. package/assets/wuic-framework-docs/screenshots/manual__validations__03.png +0 -0
  68. package/assets/wuic-framework-docs/screenshots/manual__workflow_designer__01.png +0 -0
  69. package/assets/wuic-framework-docs/screenshots/map-list__map-list-main__desktop.png +0 -0
  70. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-auth-column-edit-popup__desktop.png +0 -0
  71. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-auth-column__desktop.png +0 -0
  72. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-auth-table-edit-popup__desktop.png +0 -0
  73. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-auth-table__desktop.png +0 -0
  74. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-columns-edit-popup__desktop.png +0 -0
  75. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-columns__desktop.png +0 -0
  76. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-condition-groups-edit-popup__desktop.png +0 -0
  77. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-condition-groups__desktop.png +0 -0
  78. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-custom-actions-edit-popup__desktop.png +0 -0
  79. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-custom-actions__desktop.png +0 -0
  80. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-styles-column__desktop.png +0 -0
  81. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-styles-table-edit-popup__desktop.png +0 -0
  82. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-styles-table__desktop.png +0 -0
  83. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-table-edit-popup__desktop.png +0 -0
  84. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-editor-table__desktop.png +0 -0
  85. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-menu-management-edit-popup__desktop.png +0 -0
  86. package/assets/wuic-framework-docs/screenshots/metadata-integration__metadata-menu-management__desktop.png +0 -0
  87. package/assets/wuic-framework-docs/screenshots/parametric-dialog__parametric-dialog-edit-popup__desktop.png +0 -0
  88. package/assets/wuic-framework-docs/screenshots/scheduler-list__scheduler-main__desktop.png +0 -0
  89. package/assets/wuic-framework-docs/screenshots/spreadsheet-list__spreadsheet-main__desktop.png +0 -0
  90. package/assets/wuic-framework-docs/screenshots/themes__themes-aura-dark__desktop.png +0 -0
  91. package/assets/wuic-framework-docs/screenshots/themes__themes-aura-light__desktop.png +0 -0
  92. package/assets/wuic-framework-docs/screenshots/themes__themes-lara-light__desktop.png +0 -0
  93. package/assets/wuic-framework-docs/screenshots/translations-data__translations-data-main__desktop.png +0 -0
  94. package/assets/wuic-framework-docs/screenshots/translations-interface__translations-interface-main__desktop.png +0 -0
  95. package/assets/wuic-framework-docs/screenshots/wizard__wizard-main__desktop.png +0 -0
  96. package/assets/wuic-framework-docs/screenshots/workflow-designer__workflow-designer-main__desktop.png +0 -0
  97. package/assets/wuic-framework-docs/screenshots/workflow__workflow-main__desktop.png +0 -0
  98. package/fesm2022/wuic-framework-lib-wuic-framework-lib-CXpwV2Dc.mjs +0 -69742
@@ -1,41 +1,41 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Pipe, EventEmitter, ElementRef, Renderer2, ChangeDetectorRef, HostListener, Input, Output, Inject, Directive, Component, computed, signal, untracked, inject, NgZone, numberAttribute, DOCUMENT, input, output, isDevMode, InjectionToken, Injector, contentChildren, contentChild, booleanAttribute, effect, HostBinding, ChangeDetectionStrategy, ɵcompileComponent as _compileComponent } from '@angular/core';
3
- import * as i10 from 'primeng/splitter';
2
+ import { Pipe, EventEmitter, ElementRef, Renderer2, ChangeDetectorRef, HostListener, Input, Output, Inject, Directive, Component, computed, signal, untracked, inject, NgZone, numberAttribute, DOCUMENT, input, output, isDevMode, InjectionToken, Injector, contentChildren, contentChild, booleanAttribute, effect, HostBinding, ChangeDetectionStrategy } from '@angular/core';
3
+ import * as i11 from 'primeng/splitter';
4
4
  import { SplitterModule } from 'primeng/splitter';
5
- import * as i11 from 'primeng/dragdrop';
5
+ import * as i11$1 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 DataSourceComponent, b as DataRepeaterComponent, F as FilterBarComponent, L as LazyParametricDialogComponent, P as PagerComponent, M as MetadataProviderService, c as ParametricDialogComponent, d as MetadatiColonna, e as DataProviderService, U as UserInfoService, T as TranslationManagerService, f as MetadataEditorService, g as WorkflowRuntimeMetadataService, h as FieldEditorComponent, i as MetadataEditorComponent, A as ArchetypeConfiguratorComponent, C as CallbackPipe } from './wuic-framework-lib-wuic-framework-lib-CXpwV2Dc.mjs';
8
+ import { W as WtoolboxService, D as DynamicGenericTemplateComponent, b as DynamicCompilerService, c as DataSourceComponent, d as DataRepeaterComponent, F as FilterBarComponent, L as LazyParametricDialogComponent, P as PagerComponent, e as MetadataProviderService, f as ParametricDialogComponent, M as MetadatiColonna, g as DataProviderService, U as UserInfoService, T as TranslationManagerService, h as MetadataEditorService, i as WorkflowRuntimeMetadataService, j as FieldEditorComponent, k as MetadataEditorComponent, A as ArchetypeConfiguratorComponent } from './wuic-framework-lib-wuic-framework-lib-CXZ0usmZ.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 i5 from 'primeng/select';
12
+ import * as i6 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$2 from 'primeng/colorpicker';
16
+ import * as i2$1 from 'primeng/colorpicker';
17
17
  import { ColorPickerModule } from 'primeng/colorpicker';
18
- import * as i2$3 from 'primeng/autocomplete';
18
+ import * as i2$2 from 'primeng/autocomplete';
19
19
  import { AutoCompleteModule } from 'primeng/autocomplete';
20
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 i9 from 'primeng/contextmenu';
25
+ import * as i13 from 'primeng/contextmenu';
26
26
  import { ContextMenuModule } from 'primeng/contextmenu';
27
- import * as i2$1 from 'primeng/api';
27
+ import * as i2 from 'primeng/api';
28
28
  import { TreeDragDropService } from 'primeng/api';
29
29
  import { MenubarModule } from 'primeng/menubar';
30
30
  import * as i4 from 'primeng/button';
31
31
  import { ButtonModule } from 'primeng/button';
32
32
  import * as i17 from 'primeng/multiselect';
33
33
  import { MultiSelectModule } from 'primeng/multiselect';
34
- import * as i2 from 'primeng/dialog';
34
+ import * as i12 from 'primeng/dialog';
35
35
  import { DialogModule } from 'primeng/dialog';
36
- import * as i9$1 from 'primeng/menu';
36
+ import * as i9 from 'primeng/menu';
37
37
  import { MenuModule } from 'primeng/menu';
38
- import * as i3 from 'primeng/tree';
38
+ import * as i4$1 from 'primeng/tree';
39
39
  import { TreeModule } from 'primeng/tree';
40
40
 
41
41
  class PropConverterPipe {
@@ -52,10 +52,10 @@ class PropConverterPipe {
52
52
  }
53
53
  return null;
54
54
  }
55
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PropConverterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
56
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.5", ngImport: i0, type: PropConverterPipe, isStandalone: true, name: "propConverter" });
55
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropConverterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
56
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.8", ngImport: i0, type: PropConverterPipe, isStandalone: true, name: "propConverter" });
57
57
  }
58
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PropConverterPipe, decorators: [{
58
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropConverterPipe, decorators: [{
59
59
  type: Pipe,
60
60
  args: [{
61
61
  name: 'propConverter',
@@ -1226,10 +1226,10 @@ class NgxDraggableDomDirective {
1226
1226
  // return the bounds checking for this original pass
1227
1227
  return new NgxDraggableDomBoundsCheckEvent(isTopEdgeCollided, isRightEdgeCollided, isBottomEdgeCollided, isLeftEdgeCollided, constrainedElP0, translation, displaceX !== undefined || displaceY !== undefined);
1228
1228
  }
1229
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: NgxDraggableDomDirective, deps: [{ token: ElementRef }, { token: Renderer2 }, { token: ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
1230
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: NgxDraggableDomDirective, isStandalone: true, selector: "[ngxDraggableDom]", inputs: { bounds: "bounds", constrainByBounds: "constrainByBounds", handle: "handle", requireMouseOver: "requireMouseOver", requireMouseOverBounds: "requireMouseOverBounds", ignoreMultiTouchEvents: "ignoreMultiTouchEvents", ngxDraggableDom: "ngxDraggableDom" }, outputs: { started: "started", stopped: "stopped", moved: "moved", edge: "edge" }, host: { listeners: { "mousedown": "onMouseDown($event)", "mouseleave": "onMouseLeave($event)", "touchstart": "onTouchStart($event)" } }, ngImport: i0 });
1229
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NgxDraggableDomDirective, deps: [{ token: ElementRef }, { token: Renderer2 }, { token: ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
1230
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: NgxDraggableDomDirective, isStandalone: true, selector: "[ngxDraggableDom]", inputs: { bounds: "bounds", constrainByBounds: "constrainByBounds", handle: "handle", requireMouseOver: "requireMouseOver", requireMouseOverBounds: "requireMouseOverBounds", ignoreMultiTouchEvents: "ignoreMultiTouchEvents", ngxDraggableDom: "ngxDraggableDom" }, outputs: { started: "started", stopped: "stopped", moved: "moved", edge: "edge" }, host: { listeners: { "mousedown": "onMouseDown($event)", "mouseleave": "onMouseLeave($event)", "touchstart": "onTouchStart($event)" } }, ngImport: i0 });
1231
1231
  }
1232
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: NgxDraggableDomDirective, decorators: [{
1232
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NgxDraggableDomDirective, decorators: [{
1233
1233
  type: Directive,
1234
1234
  args: [{
1235
1235
  selector: '[ngxDraggableDom]',
@@ -2049,10 +2049,10 @@ class AngularResizableDirective {
2049
2049
  }
2050
2050
  }
2051
2051
  }
2052
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AngularResizableDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
2053
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: AngularResizableDirective, isStandalone: true, selector: "[ngResizable]", inputs: { ngResizable: "ngResizable", rzHandles: "rzHandles", rzHandleDoms: "rzHandleDoms", rzAspectRatio: "rzAspectRatio", rzContainment: "rzContainment", rzGrid: "rzGrid", rzMinWidth: "rzMinWidth", rzMinHeight: "rzMinHeight", rzMaxWidth: "rzMaxWidth", rzMaxHeight: "rzMaxHeight", rzScale: "rzScale", preventDefaultEvent: "preventDefaultEvent" }, outputs: { rzStart: "rzStart", rzResizing: "rzResizing", rzStop: "rzStop" }, usesOnChanges: true, ngImport: i0 });
2052
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: AngularResizableDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
2053
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: AngularResizableDirective, isStandalone: true, selector: "[ngResizable]", inputs: { ngResizable: "ngResizable", rzHandles: "rzHandles", rzHandleDoms: "rzHandleDoms", rzAspectRatio: "rzAspectRatio", rzContainment: "rzContainment", rzGrid: "rzGrid", rzMinWidth: "rzMinWidth", rzMinHeight: "rzMinHeight", rzMaxWidth: "rzMaxWidth", rzMaxHeight: "rzMaxHeight", rzScale: "rzScale", preventDefaultEvent: "preventDefaultEvent" }, outputs: { rzStart: "rzStart", rzResizing: "rzResizing", rzStop: "rzStop" }, usesOnChanges: true, ngImport: i0 });
2054
2054
  }
2055
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AngularResizableDirective, decorators: [{
2055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: AngularResizableDirective, decorators: [{
2056
2056
  type: Directive,
2057
2057
  args: [{
2058
2058
  selector: '[ngResizable]',
@@ -2138,10 +2138,10 @@ class DataBoundDirective {
2138
2138
  this.cd.detectChanges();
2139
2139
  }
2140
2140
  }
2141
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DataBoundDirective, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
2142
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: DataBoundDirective, isStandalone: true, selector: "[databound]", inputs: { databound: "databound", bindingFunction: "bindingFunction", clickCallback: "clickCallback", itemTemplate: "itemTemplate", inputs: "inputs" }, usesOnChanges: true, ngImport: i0 });
2141
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DataBoundDirective, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
2142
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: DataBoundDirective, isStandalone: true, selector: "[databound]", inputs: { databound: "databound", bindingFunction: "bindingFunction", clickCallback: "clickCallback", itemTemplate: "itemTemplate", inputs: "inputs" }, usesOnChanges: true, ngImport: i0 });
2143
2143
  }
2144
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DataBoundDirective, decorators: [{
2144
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DataBoundDirective, decorators: [{
2145
2145
  type: Directive,
2146
2146
  args: [{
2147
2147
  selector: '[databound]',
@@ -2164,10 +2164,10 @@ class TabPanelWrapperComponent {
2164
2164
  * Input dal componente padre per selected; usata nella configurazione e nel rendering del componente.
2165
2165
  */
2166
2166
  selected;
2167
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TabPanelWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2168
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: TabPanelWrapperComponent, isStandalone: true, selector: "p-tabPanel", inputs: { selected: "selected" }, providers: [], ngImport: i0, template: "<div role=\"tabpanel\" class=\"p-tabview-panel\" [attr.aria-hidden]=\"!selected\" data-pc-name=\"tabpanel\"\r\n [hidden]=\"!selected\">\r\n <ng-content></ng-content>\r\n</div>", styles: [".p-tabview-panel{height:100%;width:100%}\n"] });
2167
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TabPanelWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2168
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.8", type: TabPanelWrapperComponent, isStandalone: true, selector: "p-tabPanel", inputs: { selected: "selected" }, providers: [], ngImport: i0, template: "<div role=\"tabpanel\" class=\"p-tabview-panel\" [attr.aria-hidden]=\"!selected\" data-pc-name=\"tabpanel\"\r\n [hidden]=\"!selected\">\r\n <ng-content></ng-content>\r\n</div>", styles: [".p-tabview-panel{height:100%;width:100%}\n"] });
2169
2169
  }
2170
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TabPanelWrapperComponent, decorators: [{
2170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TabPanelWrapperComponent, decorators: [{
2171
2171
  type: Component,
2172
2172
  args: [{ selector: 'p-tabPanel', imports: [], providers: [], template: "<div role=\"tabpanel\" class=\"p-tabview-panel\" [attr.aria-hidden]=\"!selected\" data-pc-name=\"tabpanel\"\r\n [hidden]=\"!selected\">\r\n <ng-content></ng-content>\r\n</div>", styles: [".p-tabview-panel{height:100%;width:100%}\n"] }]
2173
2173
  }], propDecorators: { selected: [{
@@ -2198,10 +2198,10 @@ class TabViewWrapperComponent {
2198
2198
  }
2199
2199
  });
2200
2200
  }
2201
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TabViewWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2202
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: TabViewWrapperComponent, isStandalone: true, selector: "p-tabView", inputs: { tabs: "tabs", activeIndex: "activeIndex" }, ngImport: i0, template: "<div data-pc-name=\"tabview\" class=\"p-tabview p-component\">\n <div class=\"p-tabview-nav-container\">\n <div class=\"p-tabview-nav-content\" data-pc-section=\"navcontent\">\n <ul role=\"tablist\" class=\"p-tabview-nav\" data-pc-section=\"nav\">\n @for (tab of tabs; track tab; let i = $index) {\n <li role=\"presentation\" data-p-disabled=\"false\"\n [ngClass]=\"{'p-highlight': activeIndex == i}\">\n <a role=\"tab\" pripple=\"\" class=\"p-element p-ripple p-tabview-nav-link\" (click)=\"setIndex(i)\"\n [attr.aria-selected]=\"activeIndex == i\" [attr.tabindex]=\"i\" aria-disabled=\"false\"\n [attr.data-pc-index]=\"i\" data-pc-section=\"headeraction\">\n <span class=\"p-tabview-title\">\n {{tab.inputs.header}}\n </span>\n </a>\n </li>\n }\n </ul>\n </div>\n </div>\n <div class=\"p-tabview-panels\">\n <ng-content></ng-content>\n </div>\n</div>", styles: [".p-tabview.p-component{height:100%}.p-tabview .p-tabview-nav-content{scroll-padding-inline:3rem}.p-tabview-nav-content{overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scrollbar-width:none;overscroll-behavior:contain auto}.p-tabview-nav{display:inline-flex;min-width:100%;margin:0;padding:0;list-style-type:none;flex:1 1 auto}.p-tabview .p-tabview-nav li .p-tabview-nav-link{border-width:0 0 2px 0;padding:1.25rem;font-weight:700;border-top-right-radius:6px;border-top-left-radius:6px;transition:box-shadow .2s;margin:0 0 -2px}.p-tabview-nav-link{cursor:pointer;-webkit-user-select:none;user-select:none;display:flex;align-items:center;position:relative;text-decoration:none;overflow:hidden}.p-tabview .p-tabview-nav li.p-highlight .p-tabview-nav-link{border-color:#3b82f6;color:#3b82f6;background-color:transparent}.p-tabview-panels{height:calc(100% - 60px);overflow:auto}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
2201
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TabViewWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2202
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TabViewWrapperComponent, isStandalone: true, selector: "p-tabView", inputs: { tabs: "tabs", activeIndex: "activeIndex" }, ngImport: i0, template: "<div data-pc-name=\"tabview\" class=\"p-tabview p-component\">\n <div class=\"p-tabview-nav-container\">\n <div class=\"p-tabview-nav-content\" data-pc-section=\"navcontent\">\n <ul role=\"tablist\" class=\"p-tabview-nav\" data-pc-section=\"nav\">\n @for (tab of tabs; track tab; let i = $index) {\n <li role=\"presentation\" data-p-disabled=\"false\"\n [ngClass]=\"{'p-highlight': activeIndex == i}\">\n <a role=\"tab\" pripple=\"\" class=\"p-element p-ripple p-tabview-nav-link\" (click)=\"setIndex(i)\"\n [attr.aria-selected]=\"activeIndex == i\" [attr.tabindex]=\"i\" aria-disabled=\"false\"\n [attr.data-pc-index]=\"i\" data-pc-section=\"headeraction\">\n <span class=\"p-tabview-title\">\n {{tab.inputs.header}}\n </span>\n </a>\n </li>\n }\n </ul>\n </div>\n </div>\n <div class=\"p-tabview-panels\">\n <ng-content></ng-content>\n </div>\n</div>", styles: [".p-tabview.p-component{height:100%}.p-tabview .p-tabview-nav-content{scroll-padding-inline:3rem}.p-tabview-nav-content{overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scrollbar-width:none;overscroll-behavior:contain auto}.p-tabview-nav{display:inline-flex;min-width:100%;margin:0;padding:0;list-style-type:none;flex:1 1 auto}.p-tabview .p-tabview-nav li .p-tabview-nav-link{border-width:0 0 2px 0;padding:1.25rem;font-weight:700;border-top-right-radius:6px;border-top-left-radius:6px;transition:box-shadow .2s;margin:0 0 -2px}.p-tabview-nav-link{cursor:pointer;-webkit-user-select:none;user-select:none;display:flex;align-items:center;position:relative;text-decoration:none;overflow:hidden}.p-tabview .p-tabview-nav li.p-highlight .p-tabview-nav-link{border-color:#3b82f6;color:#3b82f6;background-color:transparent}.p-tabview-panels{height:calc(100% - 60px);overflow:auto}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
2203
2203
  }
2204
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: TabViewWrapperComponent, decorators: [{
2204
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TabViewWrapperComponent, decorators: [{
2205
2205
  type: Component,
2206
2206
  args: [{ selector: 'p-tabView', imports: [NgClass], template: "<div data-pc-name=\"tabview\" class=\"p-tabview p-component\">\n <div class=\"p-tabview-nav-container\">\n <div class=\"p-tabview-nav-content\" data-pc-section=\"navcontent\">\n <ul role=\"tablist\" class=\"p-tabview-nav\" data-pc-section=\"nav\">\n @for (tab of tabs; track tab; let i = $index) {\n <li role=\"presentation\" data-p-disabled=\"false\"\n [ngClass]=\"{'p-highlight': activeIndex == i}\">\n <a role=\"tab\" pripple=\"\" class=\"p-element p-ripple p-tabview-nav-link\" (click)=\"setIndex(i)\"\n [attr.aria-selected]=\"activeIndex == i\" [attr.tabindex]=\"i\" aria-disabled=\"false\"\n [attr.data-pc-index]=\"i\" data-pc-section=\"headeraction\">\n <span class=\"p-tabview-title\">\n {{tab.inputs.header}}\n </span>\n </a>\n </li>\n }\n </ul>\n </div>\n </div>\n <div class=\"p-tabview-panels\">\n <ng-content></ng-content>\n </div>\n</div>", styles: [".p-tabview.p-component{height:100%}.p-tabview .p-tabview-nav-content{scroll-padding-inline:3rem}.p-tabview-nav-content{overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scrollbar-width:none;overscroll-behavior:contain auto}.p-tabview-nav{display:inline-flex;min-width:100%;margin:0;padding:0;list-style-type:none;flex:1 1 auto}.p-tabview .p-tabview-nav li .p-tabview-nav-link{border-width:0 0 2px 0;padding:1.25rem;font-weight:700;border-top-right-radius:6px;border-top-left-radius:6px;transition:box-shadow .2s;margin:0 0 -2px}.p-tabview-nav-link{cursor:pointer;-webkit-user-select:none;user-select:none;display:flex;align-items:center;position:relative;text-decoration:none;overflow:hidden}.p-tabview .p-tabview-nav li.p-highlight .p-tabview-nav-link{border-color:#3b82f6;color:#3b82f6;background-color:transparent}.p-tabview-panels{height:calc(100% - 60px);overflow:auto}\n"] }]
2207
2207
  }], propDecorators: { tabs: [{
@@ -2347,10 +2347,10 @@ class SplitCustomEventsBehaviorDirective {
2347
2347
  }
2348
2348
  });
2349
2349
  }
2350
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitCustomEventsBehaviorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2351
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.5", type: SplitCustomEventsBehaviorDirective, isStandalone: true, selector: "[asSplitCustomEventsBehavior]", inputs: { multiClickThreshold: { classPropertyName: "multiClickThreshold", publicName: "asSplitCustomMultiClickThreshold", isSignal: true, isRequired: true, transformFunction: null }, deltaInPx: { classPropertyName: "deltaInPx", publicName: "asSplitCustomClickDeltaInPx", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { mouseDown: "asSplitCustomMouseDown", click: "asSplitCustomClick", dblClick: "asSplitCustomDblClick", keyDown: "asSplitCustomKeyDown" }, ngImport: i0 });
2350
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitCustomEventsBehaviorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2351
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.8", type: SplitCustomEventsBehaviorDirective, isStandalone: true, selector: "[asSplitCustomEventsBehavior]", inputs: { multiClickThreshold: { classPropertyName: "multiClickThreshold", publicName: "asSplitCustomMultiClickThreshold", isSignal: true, isRequired: true, transformFunction: null }, deltaInPx: { classPropertyName: "deltaInPx", publicName: "asSplitCustomClickDeltaInPx", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { mouseDown: "asSplitCustomMouseDown", click: "asSplitCustomClick", dblClick: "asSplitCustomDblClick", keyDown: "asSplitCustomKeyDown" }, ngImport: i0 });
2352
2352
  }
2353
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitCustomEventsBehaviorDirective, decorators: [{
2353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitCustomEventsBehaviorDirective, decorators: [{
2354
2354
  type: Directive,
2355
2355
  args: [{
2356
2356
  selector: '[asSplitCustomEventsBehavior]',
@@ -2472,10 +2472,10 @@ class SplitGutterDirective {
2472
2472
  static ngTemplateContextGuard(dir, ctx) {
2473
2473
  return true;
2474
2474
  }
2475
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitGutterDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
2476
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: SplitGutterDirective, isStandalone: true, selector: "[asSplitGutter]", ngImport: i0 });
2475
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitGutterDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
2476
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: SplitGutterDirective, isStandalone: true, selector: "[asSplitGutter]", ngImport: i0 });
2477
2477
  }
2478
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitGutterDirective, decorators: [{
2478
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitGutterDirective, decorators: [{
2479
2479
  type: Directive,
2480
2480
  args: [{
2481
2481
  selector: '[asSplitGutter]',
@@ -2517,10 +2517,10 @@ class SplitGutterDynamicInjectorDirective {
2517
2517
  static ngTemplateContextGuard(dir, ctx) {
2518
2518
  return true;
2519
2519
  }
2520
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitGutterDynamicInjectorDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
2521
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.5", type: SplitGutterDynamicInjectorDirective, isStandalone: true, selector: "[asSplitGutterDynamicInjector]", inputs: { gutterNum: ["asSplitGutterDynamicInjector", "gutterNum"] }, ngImport: i0 });
2520
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitGutterDynamicInjectorDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
2521
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: SplitGutterDynamicInjectorDirective, isStandalone: true, selector: "[asSplitGutterDynamicInjector]", inputs: { gutterNum: ["asSplitGutterDynamicInjector", "gutterNum"] }, ngImport: i0 });
2522
2522
  }
2523
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitGutterDynamicInjectorDirective, decorators: [{
2523
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitGutterDynamicInjectorDirective, decorators: [{
2524
2524
  type: Directive,
2525
2525
  args: [{
2526
2526
  selector: '[asSplitGutterDynamicInjector]',
@@ -3114,10 +3114,10 @@ class SplitComponent {
3114
3114
  });
3115
3115
  this.dragProgressSubject.next(this.createDragInteractionEvent(this.draggedGutterIndex()));
3116
3116
  }
3117
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3118
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", 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 });
3117
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3118
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", 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 });
3119
3119
  }
3120
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitComponent, decorators: [{
3120
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitComponent, decorators: [{
3121
3121
  type: Component,
3122
3122
  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"] }]
3123
3123
  }], 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: [{
@@ -3298,15 +3298,15 @@ class SplitAreaComponent {
3298
3298
  }
3299
3299
  return boundarySize;
3300
3300
  }
3301
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitAreaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3302
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: SplitAreaComponent, isStandalone: true, selector: "p-splitter-area", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, minSize: { classPropertyName: "minSize", publicName: "minSize", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, lockSize: { classPropertyName: "lockSize", publicName: "lockSize", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClassesBinding", "style.grid-column": "this.hostGridColumnStyleBinding", "style.grid-row": "this.hostGridRowStyleBinding", "style.position": "this.hostPositionStyleBinding" } }, providers: [
3301
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitAreaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3302
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: SplitAreaComponent, isStandalone: true, selector: "p-splitter-area", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, minSize: { classPropertyName: "minSize", publicName: "minSize", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, lockSize: { classPropertyName: "lockSize", publicName: "lockSize", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClassesBinding", "style.grid-column": "this.hostGridColumnStyleBinding", "style.grid-row": "this.hostGridRowStyleBinding", "style.position": "this.hostPositionStyleBinding" } }, providers: [
3303
3303
  {
3304
3304
  provide: SPLIT_AREA_CONTRACT,
3305
3305
  useExisting: SplitAreaComponent,
3306
3306
  },
3307
3307
  ], ngImport: i0, template: "<ng-content></ng-content>\n@if (split._isDragging()) {\n <div class=\"as-iframe-fix\"></div>\n}\n", styles: [":host{overflow-x:hidden;overflow-y:auto}.as-horizontal>:host{height:100%}.as-vertical>:host{width:100%}.as-iframe-fix{position:absolute;top:0;left:0;width:100%;height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3308
3308
  }
3309
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SplitAreaComponent, decorators: [{
3309
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SplitAreaComponent, decorators: [{
3310
3310
  type: Component,
3311
3311
  args: [{ selector: 'p-splitter-area', standalone: true, providers: [
3312
3312
  {
@@ -3329,6 +3329,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3329
3329
  }] } });
3330
3330
 
3331
3331
  class DynamicDashboardTemplateComponent {
3332
+ /**
3333
+ * Timestamp (Date.now()) of the most recent designer drag/resize gesture step.
3334
+ * Set continuously by `onResizing`/`onMoving` while the user manipulates an
3335
+ * element. Read by DesignerComponent.onWindowMouseup/onWindowTouchend to decide
3336
+ * whether the just-ended pointer release closed a designer mutation worth
3337
+ * pushing onto the undo stack. Static so a single global signal works regardless
3338
+ * of which template instance handled the gesture (every dashboard element has
3339
+ * its own DynamicDashboardTemplateComponent instance).
3340
+ *
3341
+ * Why not bind `(rzStop)`/`(stopped)` on every element template? There are 22
3342
+ * generated tag strings in designer.component.ts that would each need both
3343
+ * extra bindings, and the bindings would still need to call into the designer.
3344
+ * The mouseup/touchend hook already exists and runs in the designer — using a
3345
+ * shared timestamp reuses that path with two two-line writes.
3346
+ *
3347
+ * The 0 sentinel means "no pending gesture". The DesignerComponent consumes
3348
+ * the value (resets it to 0) after committing so a follow-up unrelated mouseup
3349
+ * does not trigger a spurious commit.
3350
+ */
3351
+ static lastDesignerGestureTimestamp = 0;
3332
3352
  /**
3333
3353
  * Input dal componente padre per inputs; usata nella configurazione e nel rendering del componente.
3334
3354
  */
@@ -3439,6 +3459,9 @@ class DynamicDashboardTemplateComponent {
3439
3459
  }
3440
3460
  element.inputs.width = event.size.width + 'px';
3441
3461
  element.inputs.height = event.size.height + 'px';
3462
+ // Mark "designer mutation in progress" so the next window:mouseup in
3463
+ // DesignerComponent commits a history snapshot. See the field doc.
3464
+ DynamicDashboardTemplateComponent.lastDesignerGestureTimestamp = Date.now();
3442
3465
  }
3443
3466
  /**
3444
3467
  * Gestisce la logica operativa di `onMoving` in modo coerente con l'implementazione corrente.
@@ -3467,6 +3490,9 @@ class DynamicDashboardTemplateComponent {
3467
3490
  }
3468
3491
  }
3469
3492
  element.inputs.transform = `matrix(${scaleX}, ${skewY}, ${skewX}, ${scaleY}, ${$event.position.x}, ${$event.position.y})`;
3493
+ // Mark "designer mutation in progress" so the next window:mouseup in
3494
+ // DesignerComponent commits a history snapshot. See the field doc.
3495
+ DynamicDashboardTemplateComponent.lastDesignerGestureTimestamp = Date.now();
3470
3496
  }
3471
3497
  /**
3472
3498
  * Gestisce la logica operativa di `onDragEnter` in modo coerente con l'implementazione corrente.
@@ -3599,27 +3625,41 @@ class DynamicDashboardTemplateComponent {
3599
3625
  return hash.includes('/designer');
3600
3626
  }
3601
3627
  /**
3602
- * Recupera i dati/valori richiesti da `getComponentFromTemplate`.
3603
- * @param template Parametro utilizzato dal metodo nel flusso elaborativo.
3604
- * @returns Valore risolto da `getComponentFromTemplate` in base ai criteri implementati.
3605
- */
3628
+ * Compila un template dashboard dinamico via `DynamicCompilerService`.
3629
+ * Refactor 2026-04-23: API pubblica `Compiler` sostituisce `ɵcompileComponent`
3630
+ * privata. Vedi skills/angular-jit-compiler-migration/SKILL.md.
3631
+ *
3632
+ * Nota: il precedente `styles: ['./dynamic-dashboard-template.component.css']`
3633
+ * era dead: `styles` del decorator `@Component` accetta CSS **inline**
3634
+ * stringhe, non path relativi. Il CSS del componente base e' gia' applicato
3635
+ * via `styleUrl` sulla classe originale; le subclass ereditano il nodo
3636
+ * Shadow DOM/Emulated del componente padre quando usate via NgComponentOutlet.
3637
+ */
3606
3638
  static getComponentFromTemplate(template) {
3607
3639
  const normalizedTemplate = String(template || '')
3608
3640
  .replace(/wuic-parametric-dialog(?!-lazy)/g, 'wuic-parametric-dialog-lazy')
3609
3641
  .replace(/ngxDraggableDom\s*=\s*\"true\"/g, '[ngxDraggableDom]="isDesignerMode()"')
3610
3642
  .replace(/ngxDraggableDom\s*=\s*\'true\'/g, '[ngxDraggableDom]="isDesignerMode()"');
3611
- _compileComponent(DynamicDashboardTemplateComponent, {
3643
+ return DynamicCompilerService.compile({
3612
3644
  template: normalizedTemplate,
3613
- standalone: true,
3614
- styles: ['./dynamic-dashboard-template.component.css'],
3615
- imports: [AsyncPipe, JsonPipe, NgFor, NgIf, PropConverterPipe, NgStyle, NgClass, NgxDraggableDomDirective, AngularResizableDirective, JsonPipe, DashboardComponent, DataSourceComponent, DataRepeaterComponent, DataBoundDirective, NgComponentOutlet, TabViewWrapperComponent, TabPanelWrapperComponent, SplitComponent, SplitAreaComponent, CdkAccordionModule, CdkAccordion, CdkAccordionItem, FilterBarComponent, LazyParametricDialogComponent, PagerComponent].concat(MetadataProviderService.customDesignerComponents)
3645
+ baseClass: DynamicDashboardTemplateComponent,
3646
+ imports: [
3647
+ AsyncPipe, JsonPipe, NgFor, NgIf, PropConverterPipe, NgStyle, NgClass,
3648
+ NgxDraggableDomDirective, AngularResizableDirective,
3649
+ DashboardComponent, DataSourceComponent, DataRepeaterComponent,
3650
+ DataBoundDirective, NgComponentOutlet,
3651
+ TabViewWrapperComponent, TabPanelWrapperComponent,
3652
+ SplitComponent, SplitAreaComponent,
3653
+ CdkAccordionModule, CdkAccordion, CdkAccordionItem,
3654
+ FilterBarComponent, LazyParametricDialogComponent, PagerComponent,
3655
+ ...MetadataProviderService.customDesignerComponents,
3656
+ ],
3616
3657
  });
3617
- return DynamicDashboardTemplateComponent;
3618
3658
  }
3619
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicDashboardTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3620
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: DynamicDashboardTemplateComponent, isStandalone: false, selector: "wuic-dynamic-dashboard-template", inputs: { inputs: "inputs", inputProps: "inputProps", toolProps: "toolProps", suggestions: "suggestions", toolId: "toolId", componentId: "componentId", uniqueName: "uniqueName", name: "name", tag: "tag", icon: "icon", group: "group", nestedComponents: "nestedComponents", allowedChildren: "allowedChildren", hide: "hide", componentRef: "componentRef", onDrop: "onDrop", ctxItems: "ctxItems", component: "component" }, ngImport: i0, template: '', isInline: true, styles: [""] });
3659
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DynamicDashboardTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3660
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.8", type: DynamicDashboardTemplateComponent, isStandalone: false, selector: "wuic-dynamic-dashboard-template", inputs: { inputs: "inputs", inputProps: "inputProps", toolProps: "toolProps", suggestions: "suggestions", toolId: "toolId", componentId: "componentId", uniqueName: "uniqueName", name: "name", tag: "tag", icon: "icon", group: "group", nestedComponents: "nestedComponents", allowedChildren: "allowedChildren", hide: "hide", componentRef: "componentRef", onDrop: "onDrop", ctxItems: "ctxItems", component: "component" }, ngImport: i0, template: '', isInline: true, styles: [""] });
3621
3661
  }
3622
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicDashboardTemplateComponent, decorators: [{
3662
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DynamicDashboardTemplateComponent, decorators: [{
3623
3663
  type: Component,
3624
3664
  args: [{ selector: 'wuic-dynamic-dashboard-template', template: '', standalone: false }]
3625
3665
  }], propDecorators: { inputs: [{
@@ -3716,12 +3756,12 @@ class DashboardComponent {
3716
3756
  debugger;
3717
3757
  }
3718
3758
  ;
3719
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3720
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DashboardComponent, isStandalone: true, selector: "wuic-dashboard", inputs: { dashboardElements: "dashboardElements" }, 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: [""], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }] });
3759
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3760
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DashboardComponent, isStandalone: true, selector: "wuic-dashboard", inputs: { dashboardElements: "dashboardElements" }, 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: [""], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }] });
3721
3761
  }
3722
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DashboardComponent, decorators: [{
3762
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DashboardComponent, decorators: [{
3723
3763
  type: Component,
3724
- args: [{ selector: 'wuic-dashboard', imports: [NgTemplateOutlet, 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" }]
3764
+ 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" }]
3725
3765
  }], ctorParameters: () => [], propDecorators: { dashboardElements: [{
3726
3766
  type: Input
3727
3767
  }] } });
@@ -3783,10 +3823,21 @@ class CssSheetEditorComponent {
3783
3823
  * Proprieta di stato del componente per new class name, usata dalla logica interna e dal template.
3784
3824
  */
3785
3825
  newClassName = '';
3826
+ alphaValue = 1;
3827
+ valore;
3828
+ pickerValue;
3829
+ ngAfterViewInit() {
3830
+ this.valore = this.pendingStyleValue;
3831
+ if (!this.valore) {
3832
+ this.valore = '#FFFFFF';
3833
+ }
3834
+ this.pickerValue = this.toHsbaModel(this.valore);
3835
+ this.alphaValue = this.clampAlpha(this.pickerValue?.a);
3836
+ }
3786
3837
  /**
3787
- * Gestisce i cambiamenti degli input aggiornando lo stato derivato e le dipendenze del componente.
3788
- * @param changes Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
3789
- */
3838
+ * Gestisce i cambiamenti degli input aggiornando lo stato derivato e le dipendenze del componente.
3839
+ * @param changes Parametro in ingresso utilizzato per determinare il flusso operativo del metodo.
3840
+ */
3790
3841
  ngOnChanges(changes) {
3791
3842
  const visibleChange = changes['visible'];
3792
3843
  const becameVisible = !!visibleChange && visibleChange.currentValue === true && visibleChange.previousValue !== true;
@@ -3795,8 +3846,8 @@ class CssSheetEditorComponent {
3795
3846
  }
3796
3847
  }
3797
3848
  /**
3798
- * Gestisce la logica operativa di `close` orchestrando le chiamate `emit`.
3799
- */
3849
+ * Gestisce la logica operativa di `close` orchestrando le chiamate `emit`.
3850
+ */
3800
3851
  close() {
3801
3852
  this.selectedSheetPathDraft = '';
3802
3853
  this.selectedClassSelector = '';
@@ -3808,8 +3859,8 @@ class CssSheetEditorComponent {
3808
3859
  this.visibleChange.emit(false);
3809
3860
  }
3810
3861
  /**
3811
- * Gestisce la logica operativa di `addSheet` orchestrando le chiamate `buildAssetSheetPath` e `some`.
3812
- */
3862
+ * Gestisce la logica operativa di `addSheet` orchestrando le chiamate `buildAssetSheetPath` e `some`.
3863
+ */
3813
3864
  addSheet() {
3814
3865
  const path = this.buildAssetSheetPath(this.newSheetName);
3815
3866
  if (!path) {
@@ -3827,8 +3878,8 @@ class CssSheetEditorComponent {
3827
3878
  this.emitChanges();
3828
3879
  }
3829
3880
  /**
3830
- * Esegue operazioni di persistenza/sincronizzazione in `removeSelectedSheet` trasformando e filtrando collezioni dati.
3831
- */
3881
+ * Esegue operazioni di persistenza/sincronizzazione in `removeSelectedSheet` trasformando e filtrando collezioni dati.
3882
+ */
3832
3883
  removeSelectedSheet() {
3833
3884
  const sheet = this.currentSheet;
3834
3885
  if (!sheet) {
@@ -3840,8 +3891,8 @@ class CssSheetEditorComponent {
3840
3891
  this.emitChanges();
3841
3892
  }
3842
3893
  /**
3843
- * Gestisce la logica operativa di `addClassToSelectedSheet` orchestrando le chiamate `replace` e `String`.
3844
- */
3894
+ * Gestisce la logica operativa di `addClassToSelectedSheet` orchestrando le chiamate `replace` e `String`.
3895
+ */
3845
3896
  addClassToSelectedSheet() {
3846
3897
  const sheet = this.currentSheet;
3847
3898
  if (!sheet) {
@@ -3867,8 +3918,8 @@ class CssSheetEditorComponent {
3867
3918
  this.emitChanges();
3868
3919
  }
3869
3920
  /**
3870
- * Esegue operazioni di persistenza/sincronizzazione in `removeSelectedClass` trasformando e filtrando collezioni dati.
3871
- */
3921
+ * Esegue operazioni di persistenza/sincronizzazione in `removeSelectedClass` trasformando e filtrando collezioni dati.
3922
+ */
3872
3923
  removeSelectedClass() {
3873
3924
  const sheet = this.currentSheet;
3874
3925
  const cssClass = this.currentClass;
@@ -3880,8 +3931,8 @@ class CssSheetEditorComponent {
3880
3931
  this.emitChanges();
3881
3932
  }
3882
3933
  /**
3883
- * Gestisce la logica operativa di `addStyleToSelectedClass` orchestrando le chiamate `String` e `defaultValueForProperty`.
3884
- */
3934
+ * Gestisce la logica operativa di `addStyleToSelectedClass` orchestrando le chiamate `String` e `defaultValueForProperty`.
3935
+ */
3885
3936
  addStyleToSelectedClass() {
3886
3937
  const cssClass = this.currentClass;
3887
3938
  if (!cssClass || !this.styleProps?.length) {
@@ -3902,9 +3953,9 @@ class CssSheetEditorComponent {
3902
3953
  this.emitChanges();
3903
3954
  }
3904
3955
  /**
3905
- * Esegue l'operazione di persistenza/sincronizzazione in `removeStyle` aggiornando lo stato locale quando necessario.
3906
- * @param index Parametro utilizzato dal metodo nel flusso elaborativo.
3907
- */
3956
+ * Esegue l'operazione di persistenza/sincronizzazione in `removeStyle` aggiornando lo stato locale quando necessario.
3957
+ * @param index Parametro utilizzato dal metodo nel flusso elaborativo.
3958
+ */
3908
3959
  removeStyle(index) {
3909
3960
  const cssClass = this.currentClass;
3910
3961
  if (!cssClass) {
@@ -3914,9 +3965,9 @@ class CssSheetEditorComponent {
3914
3965
  this.emitChanges();
3915
3966
  }
3916
3967
  /**
3917
- * Gestisce la logica operativa di `onStyleKeyChanged` in modo coerente con l'implementazione corrente.
3918
- * @param style Parametro utilizzato dal metodo nel flusso elaborativo.
3919
- */
3968
+ * Gestisce la logica operativa di `onStyleKeyChanged` in modo coerente con l'implementazione corrente.
3969
+ * @param style Parametro utilizzato dal metodo nel flusso elaborativo.
3970
+ */
3920
3971
  onStyleKeyChanged(style) {
3921
3972
  if (!style) {
3922
3973
  return;
@@ -3925,22 +3976,22 @@ class CssSheetEditorComponent {
3925
3976
  this.emitChanges();
3926
3977
  }
3927
3978
  /**
3928
- * Gestisce la logica operativa di `onStyleValueChanged` orchestrando le chiamate `emitChanges`.
3929
- */
3979
+ * Gestisce la logica operativa di `onStyleValueChanged` orchestrando le chiamate `emitChanges`.
3980
+ */
3930
3981
  onStyleValueChanged() {
3931
3982
  this.emitChanges();
3932
3983
  }
3933
3984
  /**
3934
- * Gestisce la logica operativa di `onPendingStyleKeyChanged` orchestrando le chiamate `defaultValueForProperty`.
3935
- */
3985
+ * Gestisce la logica operativa di `onPendingStyleKeyChanged` orchestrando le chiamate `defaultValueForProperty`.
3986
+ */
3936
3987
  onPendingStyleKeyChanged() {
3937
3988
  this.pendingStyleValue = this.defaultValueForProperty(this.pendingStyleKey, this.pendingStyleValue);
3938
3989
  }
3939
3990
  /**
3940
- * Recupera e prepara i dati richiesti dal chiamante normalizzando e trasformando collezioni di record.
3941
- * @param propKey Identificativo tecnico usato per lookup, confronto o aggiornamento mirato.
3942
- * @returns Collezione di tipo `string[]` derivata dalle trasformazioni applicate nel metodo.
3943
- */
3991
+ * Recupera e prepara i dati richiesti dal chiamante normalizzando e trasformando collezioni di record.
3992
+ * @param propKey Identificativo tecnico usato per lookup, confronto o aggiornamento mirato.
3993
+ * @returns Collezione di tipo `string[]` derivata dalle trasformazioni applicate nel metodo.
3994
+ */
3944
3995
  getPropertyValues(propKey) {
3945
3996
  const prop = this.styleProps.find((p) => p.key === propKey);
3946
3997
  if (!prop || prop.type !== 'dictionary') {
@@ -3971,10 +4022,10 @@ class CssSheetEditorComponent {
3971
4022
  return normalized.includes('color');
3972
4023
  }
3973
4024
  /**
3974
- * Gestisce la logica di `colorPickerValue` orchestrando le chiamate `String` e `test`.
3975
- * @param value Valore in ingresso elaborato o normalizzato dal metodo.
3976
- * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale).
3977
- */
4025
+ * Gestisce la logica di `colorPickerValue` orchestrando le chiamate `String` e `test`.
4026
+ * @param value Valore in ingresso elaborato o normalizzato dal metodo.
4027
+ * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale).
4028
+ */
3978
4029
  colorPickerValue(value) {
3979
4030
  const raw = String(value || '').trim();
3980
4031
  if (/^#[0-9a-f]{3}$/i.test(raw) || /^#[0-9a-f]{6}$/i.test(raw) || /^#[0-9a-f]{8}$/i.test(raw)) {
@@ -3983,17 +4034,25 @@ class CssSheetEditorComponent {
3983
4034
  return '#000000';
3984
4035
  }
3985
4036
  /**
3986
- * Gestisce la logica di `onPendingColorChanged` orchestrando le chiamate `String`.
3987
- * @param value Valore in ingresso elaborato o normalizzato dal metodo.
3988
- */
4037
+ * Gestisce la logica di `onPendingColorChanged` orchestrando le chiamate `String`.
4038
+ * @param value Valore in ingresso elaborato o normalizzato dal metodo.
4039
+ */
3989
4040
  onPendingColorChanged(value) {
3990
- this.pendingStyleValue = String(value || '').trim();
4041
+ const raw = value;
4042
+ const hsba = {
4043
+ ...(raw || {}),
4044
+ a: this.clampAlpha(raw?.a ?? this.alphaValue)
4045
+ };
4046
+ this.alphaValue = this.clampAlpha(hsba?.a);
4047
+ const newValue = this.toPersistedColor(raw);
4048
+ this.pickerValue = raw;
4049
+ this.pendingStyleValue = this.valore = newValue;
3991
4050
  }
3992
4051
  /**
3993
- * Gestisce la logica operativa di `onStyleColorChanged` in modo coerente con l'implementazione corrente.
3994
- * @param style Parametro utilizzato dal metodo nel flusso elaborativo.
3995
- * @param value Valore in ingresso elaborato o normalizzato dal metodo.
3996
- */
4052
+ * Gestisce la logica operativa di `onStyleColorChanged` in modo coerente con l'implementazione corrente.
4053
+ * @param style Parametro utilizzato dal metodo nel flusso elaborativo.
4054
+ * @param value Valore in ingresso elaborato o normalizzato dal metodo.
4055
+ */
3997
4056
  onStyleColorChanged(style, value) {
3998
4057
  if (!style) {
3999
4058
  return;
@@ -4002,8 +4061,8 @@ class CssSheetEditorComponent {
4002
4061
  this.onStyleValueChanged();
4003
4062
  }
4004
4063
  /**
4005
- * Gestisce la logica operativa di `onSelectedSheetChanged` orchestrando le chiamate `resetPendingStyle` e `emitChanges`.
4006
- */
4064
+ * Gestisce la logica operativa di `onSelectedSheetChanged` orchestrando le chiamate `resetPendingStyle` e `emitChanges`.
4065
+ */
4007
4066
  onSelectedSheetChanged() {
4008
4067
  const firstClass = this.currentSheet?.classes?.[0];
4009
4068
  this.selectedClassSelector = firstClass?.SelectorString || '';
@@ -4011,8 +4070,8 @@ class CssSheetEditorComponent {
4011
4070
  this.emitChanges();
4012
4071
  }
4013
4072
  /**
4014
- * Gestisce la logica operativa di `onSelectedClassChanged` orchestrando le chiamate `resetPendingStyle` e `emitChanges`.
4015
- */
4073
+ * Gestisce la logica operativa di `onSelectedClassChanged` orchestrando le chiamate `resetPendingStyle` e `emitChanges`.
4074
+ */
4016
4075
  onSelectedClassChanged() {
4017
4076
  this.resetPendingStyle();
4018
4077
  this.emitChanges();
@@ -4036,10 +4095,10 @@ class CssSheetEditorComponent {
4036
4095
  this.resetPendingStyle();
4037
4096
  }
4038
4097
  /**
4039
- * Gestisce la logica operativa di `cloneSheets` trasformando e filtrando collezioni dati.
4040
- * @param sheets Collezione di input processata dal metodo.
4041
- * @returns Collezione di tipo `CssSheetRow[]` risultante dalle trasformazioni applicate dal metodo.
4042
- */
4098
+ * Gestisce la logica operativa di `cloneSheets` trasformando e filtrando collezioni dati.
4099
+ * @param sheets Collezione di input processata dal metodo.
4100
+ * @returns Collezione di tipo `CssSheetRow[]` risultante dalle trasformazioni applicate dal metodo.
4101
+ */
4043
4102
  cloneSheets(sheets) {
4044
4103
  return (sheets || []).map((sheet) => ({
4045
4104
  SheetPath: this.normalizePath(sheet?.SheetPath),
@@ -4055,11 +4114,11 @@ class CssSheetEditorComponent {
4055
4114
  })).filter((sheet) => !!sheet.SheetPath);
4056
4115
  }
4057
4116
  /**
4058
- * Gestisce la logica di `defaultValueForProperty` trasformando e filtrando collezioni dati.
4059
- * @param propKey Identificativo tecnico usato per lookup, match o aggiornamento mirato.
4060
- * @param currentValue Valore in ingresso elaborato o normalizzato dal metodo.
4061
- * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale).
4062
- */
4117
+ * Gestisce la logica di `defaultValueForProperty` trasformando e filtrando collezioni dati.
4118
+ * @param propKey Identificativo tecnico usato per lookup, match o aggiornamento mirato.
4119
+ * @param currentValue Valore in ingresso elaborato o normalizzato dal metodo.
4120
+ * @returns Stringa calcolata dal metodo (chiave, etichetta o frammento testuale).
4121
+ */
4063
4122
  defaultValueForProperty(propKey, currentValue) {
4064
4123
  const prop = this.styleProps.find((p) => p.key === propKey);
4065
4124
  if (!prop) {
@@ -4082,18 +4141,18 @@ class CssSheetEditorComponent {
4082
4141
  return String(currentValue || '').trim();
4083
4142
  }
4084
4143
  /**
4085
- * Gestisce la logica operativa di `normalizePath` in modo coerente con l'implementazione corrente.
4086
- * @param path Parametro utilizzato dal metodo nel flusso elaborativo.
4087
- * @returns Stringa risultante calcolata da `normalizePath` per chiavi/label o valori testuali.
4088
- */
4144
+ * Gestisce la logica operativa di `normalizePath` in modo coerente con l'implementazione corrente.
4145
+ * @param path Parametro utilizzato dal metodo nel flusso elaborativo.
4146
+ * @returns Stringa risultante calcolata da `normalizePath` per chiavi/label o valori testuali.
4147
+ */
4089
4148
  normalizePath(path) {
4090
4149
  return String(path || '').trim().replace(/\\/g, '/');
4091
4150
  }
4092
4151
  /**
4093
- * Costruisce il payload/struttura risultante in `buildAssetSheetPath` partendo dai dati correnti.
4094
- * @param fileName Parametro utilizzato dal metodo nel flusso elaborativo.
4095
- * @returns Stringa risultante calcolata da `buildAssetSheetPath` per chiavi/label o valori testuali.
4096
- */
4152
+ * Costruisce il payload/struttura risultante in `buildAssetSheetPath` partendo dai dati correnti.
4153
+ * @param fileName Parametro utilizzato dal metodo nel flusso elaborativo.
4154
+ * @returns Stringa risultante calcolata da `buildAssetSheetPath` per chiavi/label o valori testuali.
4155
+ */
4097
4156
  buildAssetSheetPath(fileName) {
4098
4157
  let normalizedName = String(fileName || '').trim();
4099
4158
  if (!normalizedName) {
@@ -4114,8 +4173,8 @@ class CssSheetEditorComponent {
4114
4173
  return `assets/${folder}/${normalizedName}`;
4115
4174
  }
4116
4175
  /**
4117
- * Gestisce la logica operativa di `emitChanges` orchestrando le chiamate `emit` e `cloneSheets`.
4118
- */
4176
+ * Gestisce la logica operativa di `emitChanges` orchestrando le chiamate `emit` e `cloneSheets`.
4177
+ */
4119
4178
  emitChanges() {
4120
4179
  this.applyEditor.emit({
4121
4180
  sheets: this.cloneSheets(this.draftSheets),
@@ -4131,17 +4190,17 @@ class CssSheetEditorComponent {
4131
4190
  this.pendingStyleValue = this.defaultValueForProperty(this.pendingStyleKey);
4132
4191
  }
4133
4192
  /**
4134
- * Gestisce la logica operativa di `currentSheet` orchestrando le chiamate `find` e `normalizePath`.
4135
- * @returns Valore calcolato dinamicamente a partire dallo stato corrente del componente.
4136
- */
4193
+ * Gestisce la logica operativa di `currentSheet` orchestrando le chiamate `find` e `normalizePath`.
4194
+ * @returns Valore calcolato dinamicamente a partire dallo stato corrente del componente.
4195
+ */
4137
4196
  get currentSheet() {
4138
4197
  const match = this.draftSheets.find((s) => this.normalizePath(s.SheetPath) === this.normalizePath(this.selectedSheetPathDraft));
4139
4198
  return match || null;
4140
4199
  }
4141
4200
  /**
4142
- * Gestisce la logica operativa di `currentClass` orchestrando le chiamate `find` e `String`.
4143
- * @returns Valore calcolato dinamicamente a partire dallo stato corrente del componente.
4144
- */
4201
+ * Gestisce la logica operativa di `currentClass` orchestrando le chiamate `find` e `String`.
4202
+ * @returns Valore calcolato dinamicamente a partire dallo stato corrente del componente.
4203
+ */
4145
4204
  get currentClass() {
4146
4205
  const sheet = this.currentSheet;
4147
4206
  if (!sheet) {
@@ -4150,12 +4209,172 @@ class CssSheetEditorComponent {
4150
4209
  const found = sheet.classes.find((c) => String(c.SelectorString || '').trim() === String(this.selectedClassSelector || '').trim());
4151
4210
  return found || null;
4152
4211
  }
4153
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CssSheetEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4154
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", 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\n [header]=\"'CSS Editor'\"\n [(visible)]=\"visible\"\n (visibleChange)=\"visibleChange.emit($event)\"\n [modal]=\"true\"\n [closable]=\"true\"\n [style]=\"{ width: '1100px', maxWidth: '98vw' }\"\n>\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\n [options]=\"draftSheets\"\n optionLabel=\"SheetPath\"\n optionValue=\"SheetPath\"\n [(ngModel)]=\"selectedSheetPathDraft\"\n (ngModelChange)=\"onSelectedSheetChanged()\"\n 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=\"^[^/\\\\]+$\" [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()\" [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\n [options]=\"currentSheet?.classes || []\"\n optionLabel=\"SelectorString\"\n optionValue=\"SelectorString\"\n [(ngModel)]=\"selectedClassSelector\"\n (ngModelChange)=\"onSelectedClassChanged()\"\n 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()\" [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\n [options]=\"styleProps\"\n optionLabel=\"key\"\n optionValue=\"key\"\n [(ngModel)]=\"pendingStyleKey\"\n (ngModelChange)=\"onPendingStyleKeyChanged()\"\n appendTo=\"body\"\n [style]=\"{ width: '260px' }\">\n </p-select>\n\n @if (isPropertyDictionary(pendingStyleKey)) {\n <p-select\n [options]=\"getPropertyValues(pendingStyleKey)\"\n [(ngModel)]=\"pendingStyleValue\"\n appendTo=\"body\"\n [style]=\"{ width: '320px' }\">\n </p-select>\n } @else if (isPropertyColor(pendingStyleKey)) {\n <div class=\"css-style-color-input\">\n <p-colorPicker\n [ngModel]=\"colorPickerValue(pendingStyleValue)\"\n (ngModelChange)=\"onPendingColorChanged($event)\"\n appendTo=\"body\">\n </p-colorPicker>\n <input type=\"text\" [(ngModel)]=\"pendingStyleValue\" style=\"width: 252px;\" />\n </div>\n } @else {\n <input type=\"text\" [(ngModel)]=\"pendingStyleValue\" style=\"width: 320px;\" />\n }\n\n <p-button label=\"Aggiungi propriet\u00E0 corrente\" (onClick)=\"addStyleToSelectedClass()\" [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>\n", 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}}\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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { 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: i2$1.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: i2$2.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"] }] });
4212
+ async onAlphaChange(rawAlpha) {
4213
+ this.alphaValue = this.clampAlpha(rawAlpha);
4214
+ this.pickerValue = {
4215
+ ...(this.pickerValue || {}),
4216
+ a: this.alphaValue
4217
+ };
4218
+ const newValue = this.toPersistedColor(this.pickerValue);
4219
+ this.pendingStyleValue = this.valore = newValue;
4220
+ }
4221
+ toPersistedColor(raw) {
4222
+ if (raw === undefined || raw === null) {
4223
+ return '';
4224
+ }
4225
+ if (typeof raw === 'string') {
4226
+ return raw.trim();
4227
+ }
4228
+ const h = Number(raw?.h);
4229
+ const s = Number(raw?.s);
4230
+ const b = Number(raw?.b);
4231
+ let a = Number(raw?.a);
4232
+ if (!Number.isFinite(h) || !Number.isFinite(s) || !Number.isFinite(b)) {
4233
+ return String(raw);
4234
+ }
4235
+ if (!Number.isFinite(a)) {
4236
+ a = this.alphaValue;
4237
+ }
4238
+ a = this.clampAlpha(a);
4239
+ return this.hsbaToRgbaString(h, s, b, a);
4240
+ }
4241
+ toHsbaModel(value) {
4242
+ const fallback = { h: 0, s: 0, b: 100, a: 1 };
4243
+ if (value === undefined || value === null) {
4244
+ return fallback;
4245
+ }
4246
+ if (typeof value === 'object' && value?.h !== undefined && value?.s !== undefined && value?.b !== undefined) {
4247
+ return {
4248
+ h: Number(value.h) || 0,
4249
+ s: Number(value.s) || 0,
4250
+ b: Number(value.b) || 0,
4251
+ a: Number.isFinite(Number(value.a)) ? Number(value.a) : 1
4252
+ };
4253
+ }
4254
+ const str = String(value).trim();
4255
+ if (!str) {
4256
+ return fallback;
4257
+ }
4258
+ const rgbMatch = str.match(/^rgba?\(([^)]+)\)$/i);
4259
+ if (rgbMatch) {
4260
+ const parts = rgbMatch[1].split(',').map((x) => x.trim());
4261
+ const r = Number(parts[0]);
4262
+ const g = Number(parts[1]);
4263
+ const b = Number(parts[2]);
4264
+ const a = parts.length > 3 ? Number(parts[3]) : 1;
4265
+ if (Number.isFinite(r) && Number.isFinite(g) && Number.isFinite(b)) {
4266
+ return this.rgbaToHsbaModel(r, g, b, Number.isFinite(a) ? a : 1);
4267
+ }
4268
+ return fallback;
4269
+ }
4270
+ const hex = str.replace('#', '');
4271
+ if (/^[0-9a-f]{3,8}$/i.test(hex)) {
4272
+ const normalized = hex.length === 3
4273
+ ? hex.split('').map((x) => `${x}${x}`).join('') + 'ff'
4274
+ : hex.length === 4
4275
+ ? hex.split('').map((x) => `${x}${x}`).join('')
4276
+ : hex.length === 6
4277
+ ? `${hex}ff`
4278
+ : hex;
4279
+ const r = parseInt(normalized.slice(0, 2), 16);
4280
+ const g = parseInt(normalized.slice(2, 4), 16);
4281
+ const b = parseInt(normalized.slice(4, 6), 16);
4282
+ const a = parseInt(normalized.slice(6, 8), 16) / 255;
4283
+ return this.rgbaToHsbaModel(r, g, b, a);
4284
+ }
4285
+ return fallback;
4286
+ }
4287
+ rgbaToHsbaModel(rRaw, gRaw, bRaw, aRaw) {
4288
+ const r = Math.max(0, Math.min(255, rRaw)) / 255;
4289
+ const g = Math.max(0, Math.min(255, gRaw)) / 255;
4290
+ const b = Math.max(0, Math.min(255, bRaw)) / 255;
4291
+ const a = Math.max(0, Math.min(1, aRaw));
4292
+ const max = Math.max(r, g, b);
4293
+ const min = Math.min(r, g, b);
4294
+ const delta = max - min;
4295
+ let h = 0;
4296
+ if (delta !== 0) {
4297
+ if (max === r) {
4298
+ h = 60 * (((g - b) / delta) % 6);
4299
+ }
4300
+ else if (max === g) {
4301
+ h = 60 * (((b - r) / delta) + 2);
4302
+ }
4303
+ else {
4304
+ h = 60 * (((r - g) / delta) + 4);
4305
+ }
4306
+ }
4307
+ if (h < 0) {
4308
+ h += 360;
4309
+ }
4310
+ const s = max === 0 ? 0 : (delta / max) * 100;
4311
+ const v = max * 100;
4312
+ return {
4313
+ h: Math.round(h),
4314
+ s: Math.round(s),
4315
+ b: Math.round(v),
4316
+ a: Number(a.toFixed(3))
4317
+ };
4318
+ }
4319
+ hsbaToRgbaString(hRaw, sRaw, bRaw, aRaw) {
4320
+ const h = ((hRaw % 360) + 360) % 360;
4321
+ const s = Math.max(0, Math.min(100, sRaw)) / 100;
4322
+ const v = Math.max(0, Math.min(100, bRaw)) / 100;
4323
+ const a = Math.max(0, Math.min(1, aRaw));
4324
+ const c = v * s;
4325
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
4326
+ const m = v - c;
4327
+ let r1 = 0;
4328
+ let g1 = 0;
4329
+ let b1 = 0;
4330
+ if (h < 60) {
4331
+ r1 = c;
4332
+ g1 = x;
4333
+ b1 = 0;
4334
+ }
4335
+ else if (h < 120) {
4336
+ r1 = x;
4337
+ g1 = c;
4338
+ b1 = 0;
4339
+ }
4340
+ else if (h < 180) {
4341
+ r1 = 0;
4342
+ g1 = c;
4343
+ b1 = x;
4344
+ }
4345
+ else if (h < 240) {
4346
+ r1 = 0;
4347
+ g1 = x;
4348
+ b1 = c;
4349
+ }
4350
+ else if (h < 300) {
4351
+ r1 = x;
4352
+ g1 = 0;
4353
+ b1 = c;
4354
+ }
4355
+ else {
4356
+ r1 = c;
4357
+ g1 = 0;
4358
+ b1 = x;
4359
+ }
4360
+ const r = Math.round((r1 + m) * 255);
4361
+ const g = Math.round((g1 + m) * 255);
4362
+ const b = Math.round((b1 + m) * 255);
4363
+ return `rgba(${r}, ${g}, ${b}, ${Number(a.toFixed(3))})`;
4364
+ }
4365
+ clampAlpha(value) {
4366
+ const parsed = Number(value);
4367
+ if (!Number.isFinite(parsed)) {
4368
+ return 1;
4369
+ }
4370
+ return Math.max(0, Math.min(1, parsed));
4371
+ }
4372
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: CssSheetEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4373
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", 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: i12.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: i2.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"] }] });
4155
4374
  }
4156
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CssSheetEditorComponent, decorators: [{
4375
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: CssSheetEditorComponent, decorators: [{
4157
4376
  type: Component,
4158
- args: [{ selector: 'wuic-css-sheet-editor', imports: [FormsModule, DialogModule, ButtonModule, SelectModule, ColorPickerModule], template: "<p-dialog\n [header]=\"'CSS Editor'\"\n [(visible)]=\"visible\"\n (visibleChange)=\"visibleChange.emit($event)\"\n [modal]=\"true\"\n [closable]=\"true\"\n [style]=\"{ width: '1100px', maxWidth: '98vw' }\"\n>\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\n [options]=\"draftSheets\"\n optionLabel=\"SheetPath\"\n optionValue=\"SheetPath\"\n [(ngModel)]=\"selectedSheetPathDraft\"\n (ngModelChange)=\"onSelectedSheetChanged()\"\n 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=\"^[^/\\\\]+$\" [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()\" [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\n [options]=\"currentSheet?.classes || []\"\n optionLabel=\"SelectorString\"\n optionValue=\"SelectorString\"\n [(ngModel)]=\"selectedClassSelector\"\n (ngModelChange)=\"onSelectedClassChanged()\"\n 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()\" [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\n [options]=\"styleProps\"\n optionLabel=\"key\"\n optionValue=\"key\"\n [(ngModel)]=\"pendingStyleKey\"\n (ngModelChange)=\"onPendingStyleKeyChanged()\"\n appendTo=\"body\"\n [style]=\"{ width: '260px' }\">\n </p-select>\n\n @if (isPropertyDictionary(pendingStyleKey)) {\n <p-select\n [options]=\"getPropertyValues(pendingStyleKey)\"\n [(ngModel)]=\"pendingStyleValue\"\n appendTo=\"body\"\n [style]=\"{ width: '320px' }\">\n </p-select>\n } @else if (isPropertyColor(pendingStyleKey)) {\n <div class=\"css-style-color-input\">\n <p-colorPicker\n [ngModel]=\"colorPickerValue(pendingStyleValue)\"\n (ngModelChange)=\"onPendingColorChanged($event)\"\n appendTo=\"body\">\n </p-colorPicker>\n <input type=\"text\" [(ngModel)]=\"pendingStyleValue\" style=\"width: 252px;\" />\n </div>\n } @else {\n <input type=\"text\" [(ngModel)]=\"pendingStyleValue\" style=\"width: 320px;\" />\n }\n\n <p-button label=\"Aggiungi propriet\u00E0 corrente\" (onClick)=\"addStyleToSelectedClass()\" [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>\n", 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}}\n"] }]
4377
+ args: [{ selector: 'wuic-css-sheet-editor', imports: [FormsModule, DialogModule, ButtonModule, SelectModule, ColorPickerModule, NgStyle], 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"] }]
4159
4378
  }], propDecorators: { visible: [{
4160
4379
  type: Input
4161
4380
  }], visibleChange: [{
@@ -4265,6 +4484,7 @@ class DesignerComponent {
4265
4484
  currentDashboardDescription = '';
4266
4485
  showArchetypeConfigurator = false;
4267
4486
  archetypeConfigTool = null;
4487
+ propFilter;
4268
4488
  popupManagedArchetypes = ['map', 'chart', 'carousel'];
4269
4489
  propertySectionStateByTool = {};
4270
4490
  maxHistoryLength = 100;
@@ -4274,8 +4494,13 @@ class DesignerComponent {
4274
4494
  lastCommittedSnapshot = null;
4275
4495
  pendingColorHistoryBase = null;
4276
4496
  pendingColorHistoryDirty = false;
4497
+ _historyApplyIsRedo = false;
4498
+ _lastHistoryApplyTime = 0;
4499
+ _suppressRedoClear = false;
4500
+ _redoRebindTimer;
4277
4501
  lastKnownHashRoute = '';
4278
4502
  suppressNextHashGuard = false;
4503
+ _routeParamSub;
4279
4504
  footerHoverTargetElements = [];
4280
4505
  footerHoverOverlayElement = null;
4281
4506
  footerHoverTabPanelPreviousSelection = [];
@@ -4304,7 +4529,7 @@ class DesignerComponent {
4304
4529
  this.workflowRuntimeMetadata = workflowRuntimeMetadata;
4305
4530
  this.defaultCtxItems = [
4306
4531
  {
4307
- label: 'Remove',
4532
+ label: this.t('designer.remove', 'Remove'),
4308
4533
  icon: 'pi pi-trash',
4309
4534
  command: (menuItem) => {
4310
4535
  if (this.ctxElement) {
@@ -4316,14 +4541,14 @@ class DesignerComponent {
4316
4541
  this.ctxItems.next(this.defaultCtxItems);
4317
4542
  this.footerCtxItems = [
4318
4543
  {
4319
- label: 'Rename',
4544
+ label: this.t('designer.rename', 'Rename'),
4320
4545
  icon: 'pi pi-pencil',
4321
4546
  command: () => {
4322
4547
  this.renameFooterContextItem();
4323
4548
  }
4324
4549
  },
4325
4550
  {
4326
- label: 'Remove',
4551
+ label: this.t('designer.remove', 'Remove'),
4327
4552
  icon: 'pi pi-trash',
4328
4553
  command: () => {
4329
4554
  const uniqueName = String(this.footerCtxElement?.uniqueName || '').trim();
@@ -4335,7 +4560,7 @@ class DesignerComponent {
4335
4560
  ];
4336
4561
  this.hierarchyCtxItems = [
4337
4562
  {
4338
- label: 'Remove',
4563
+ label: this.t('designer.remove', 'Remove'),
4339
4564
  icon: 'pi pi-trash',
4340
4565
  command: () => {
4341
4566
  const uniqueName = String(this.hierarchyCtxElement?.uniqueName || '').trim();
@@ -4347,24 +4572,25 @@ class DesignerComponent {
4347
4572
  ];
4348
4573
  this.htmlStyleString = '[ngClass]="0.cssClass" [ngStyle]="{width: 0.width, maxWidth: 0.maxWidth, height: 0.height, maxHeight: 0.maxHeight, minWidth: 0.minWidth, minHeight: 0.minHeight, position: 0.position, left: 0.left, top: 0.top, float: 0.float, display: 0.display, boxSizing: 0.boxSizing, backgroundColor: 0.backgroundColor, color: 0.color, borderRadius: 0.borderRadius, borderBottomStyle: 0.borderBottomStyle, borderBottomWidth: 0.borderBottomWidth, borderBottomColor: 0.borderBottomColor, borderLeftStyle: 0.borderLeftStyle, borderLeftWidth: 0.borderLeftWidth, borderLeftColor: 0.borderLeftColor, borderRightStyle: 0.borderRightStyle, borderRightWidth: 0.borderRightWidth, borderRightColor: 0.borderRightColor, borderTopStyle: 0.borderTopStyle, borderTopWidth: 0.borderTopWidth, borderTopColor: 0.borderTopColor, paddingTop: 0.paddingTop, paddingRight: 0.paddingRight, paddingBottom: 0.paddingBottom, paddingLeft: 0.paddingLeft, marginTop: 0.marginTop, marginRight: 0.marginRight, marginBottom: 0.marginBottom, marginLeft: 0.marginLeft, fontSize: 0.fontSize, fontFamily: 0.fontFamily, fontWeight: 0.fontWeight, fontStyle: 0.fontStyle, textDecoration: 0.textDecoration, textAlign: 0.textAlign, verticalAlign: 0.verticalAlign, lineHeight: 0.lineHeight, letterSpacing: 0.letterSpacing, wordSpacing: 0.wordSpacing, textTransform: 0.textTransform, textIndent: 0.textIndent, whiteSpace: 0.whiteSpace, wordWrap: 0.wordWrap, wordBreak: 0.wordBreak, overflow: 0.overflow, overflowX: 0.overflowX, overflowY: 0.overflowY, zIndex: 0.zIndex, cursor: 0.cursor, visibility: 0.visibility, opacity: 0.opacity, filter: 0.filter, transform: 0.transform, transformOrigin: 0.transformOrigin, transition: 0.transition, boxShadow: 0.boxShadow, textShadow: 0.textShadow, backgroundPosition: 0.backgroundPosition, backgroundRepeat: 0.backgroundRepeat, backgroundAttachment: 0.backgroundAttachment, backgroundSize: 0.backgroundSize, backgroundImage: 0.backgroundImage, backgroundClip: 0.backgroundClip, backgroundOrigin: 0.backgroundOrigin, backgroundBlendMode: 0.backgroundBlendMode, clip: 0.clip, clipPath: 0.clipPath, clipRule: 0.clipRule, mask: 0.mask, maskType: 0.maskType, maskImage: 0.maskImage, maskMode: 0.maskMode, maskSize: 0.maskSize, maskRepeat: 0.maskRepeat, maskPosition: 0.maskPosition, maskClip: 0.maskClip, maskOrigin: 0.maskOrigin, maskComposite: 0.maskComposite, maskBorder: 0.maskBorder, maskBorderSource: 0.maskBorderSource, maskBorderSlice: 0.maskBorderSlice, maskBorderWidth: 0.maskBorderWidth, maskBorderOutset: 0.maskBorderOutset, maskBorderRepeat: 0.maskBorderRepeat, maskBorderMode: 0.maskBorderMode, maskBorderClip: 0.maskBorderClip, maskBorderOrigin: 0.maskBorderOrigin, maskBorder, tableLayout: 0.tableLayout, borderCollapse: 0.borderCollapse, borderSpacing: 0.borderSpacing, captionSide: 0.captionSide, emptyCells: 0.emptyCells, tableCaption: 0.tableCaption, tableBorder: 0.tableBorder, tableBorderSpacing: 0.tableBorderSpacing, tableBorderCollapse: 0.tableBorderCollapse, listStyle: 0.listStyle}"';
4349
4574
  this.htmlInputProperties = {
4350
- cssFile: { type: 'dictionary', values: this.availableProjectCssFiles, propertyCaption: 'CSS File' },
4351
- cssClass: { type: 'dictionary', values: [''], propertyCaption: 'CSS Classes' },
4352
- width: { type: 'string' },
4353
- maxWidth: { type: 'string' },
4354
- height: { type: 'string' },
4355
- maxHeight: { type: 'string' },
4356
- minWidth: { type: 'string' },
4357
- minHeight: { type: 'string' },
4358
- position: { type: 'dictionary', values: ['', 'relative', 'absolute', 'fixed', 'static', 'sticky', 'inherit'] },
4359
- transform: { type: 'string' },
4360
- top: { type: 'string' },
4361
- left: { type: 'string' },
4362
- float: { type: 'dictionary', values: ['', 'left', 'right', 'none', 'inherit'] },
4363
- display: { type: 'dictionary', values: ['', 'block', 'inline', 'inline-block', 'flex', 'none', 'inherit'] },
4364
- boxSizing: { type: 'dictionary', values: ['', 'content-box', 'border-box', 'inherit', 'initial', 'unset'] },
4575
+ animation: { type: 'string' },
4576
+ animationName: { type: 'string' },
4577
+ animationDuration: { type: 'string' },
4578
+ animationTimingFunction: { type: 'string' },
4579
+ animationDelay: { type: 'string' },
4580
+ animationIterationCount: { type: 'string' },
4581
+ animationDirection: { type: 'dictionary', values: ['', 'normal', 'reverse', 'alternate', 'alternate-reverse', 'inherit'] },
4582
+ animationFillMode: { type: 'dictionary', values: ['', 'none', 'forwards', 'backwards', 'both', 'inherit'] },
4583
+ animationPlayState: { type: 'dictionary', values: ['', 'running', 'paused', 'inherit'] },
4584
+ background: { type: 'string' },
4585
+ backgroundAttachment: { type: 'dictionary', values: ['', 'scroll', 'fixed', 'local', 'inherit'] },
4586
+ backgroundBlendMode: { type: 'dictionary', values: ['', 'normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'saturation', 'color', 'luminosity', 'inherit'] },
4587
+ backgroundClip: { type: 'dictionary', values: ['', 'border-box', 'padding-box', 'content-box', 'inherit'] },
4365
4588
  backgroundColor: { type: 'color' },
4366
- color: { type: 'color' },
4367
- // border: { type: 'string' },
4589
+ backgroundImage: { type: 'string' },
4590
+ backgroundOrigin: { type: 'dictionary', values: ['', 'padding-box', 'border-box', 'content-box', 'inherit'] },
4591
+ backgroundPosition: { type: 'dictionary', values: ['', 'left top', 'left center', 'left bottom', 'right top', 'right center', 'right bottom', 'center top', 'center center', 'center bottom', 'x% y%', 'xpos ypos', 'inherit'] },
4592
+ backgroundRepeat: { type: 'dictionary', values: ['', 'repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'inherit'] },
4593
+ backgroundSize: { type: 'dictionary', values: ['', 'auto', 'cover', 'contain', 'inherit'] },
4368
4594
  borderRadius: { type: 'string' },
4369
4595
  borderStyle: {
4370
4596
  type: 'dictionary', values: ['', 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge',
@@ -4384,54 +4610,32 @@ class DesignerComponent {
4384
4610
  borderTopStyle: { type: 'dictionary', values: ['', 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset', 'inherit'] },
4385
4611
  borderTopWidth: { type: 'string' },
4386
4612
  borderTopColor: { type: 'color' },
4387
- paddingTop: { type: 'string' },
4388
- paddingRight: { type: 'string' },
4389
- paddingBottom: { type: 'string' },
4390
- paddingLeft: { type: 'string' },
4391
- marginTop: { type: 'string' },
4392
- marginRight: { type: 'string' },
4393
- marginBottom: { type: 'string' },
4394
- marginLeft: { type: 'string' },
4613
+ boxSizing: { type: 'dictionary', values: ['', 'content-box', 'border-box', 'inherit', 'initial', 'unset'] },
4614
+ boxShadow: { type: 'string' },
4615
+ clip: { type: 'string' },
4616
+ clipPath: { type: 'string' },
4617
+ clipRule: { type: 'dictionary', values: ['', 'nonzero', 'evenodd', 'inherit'] },
4618
+ color: { type: 'color' },
4619
+ cssFile: { type: 'dictionary', values: this.availableProjectCssFiles, propertyCaption: 'CSS File' },
4620
+ cssClass: { type: 'dictionary', values: [], propertyCaption: 'CSS Classes' },
4621
+ cursor: { type: 'dictionary', values: ['', 'auto', 'crosshair', 'default', 'pointer', 'move', 'e-resize', 'ne-resize', 'nw-resize', 'n-resize', 'se-resize', 'sw-resize', 's-resize', 'w-resize', 'text', 'wait', 'help', 'progress', 'inherit'] },
4622
+ display: { type: 'dictionary', values: ['', 'block', 'inline', 'inline-block', 'flex', 'none', 'inherit'] },
4623
+ filter: { type: 'string' },
4624
+ float: { type: 'dictionary', values: ['', 'left', 'right', 'none', 'inherit'] },
4625
+ // border: { type: 'string' },
4395
4626
  fontSize: { type: 'string' },
4396
4627
  fontFamily: { type: 'dictionary', values: ['', 'Arial', 'Verdana', 'Times New Roman', 'Georgia', 'Trebuchet MS', 'Tahoma', 'Courier New', 'Lucida Console', 'Impact', 'Comic Sans MS', 'Palatino Linotype', 'Book Antiqua', 'Lucida Sans Unicode', 'Arial Black', 'Garamond', 'Courier', 'Brush Script MT', 'Arial Narrow', 'Geneva', 'Gill Sans', 'Helvetica', 'sans-serif', 'serif', 'monospace', 'cursive', 'fantasy'] },
4397
4628
  fontWeight: { type: 'dictionary', values: ['', 'normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900'] },
4398
4629
  fontStyle: { type: 'dictionary', values: ['', 'normal', 'italic', 'oblique'] },
4399
- textDecoration: { type: 'dictionary', values: ['', 'none', 'underline', 'overline', 'line-through', 'blink'] },
4400
- textAlign: { type: 'dictionary', values: ['', 'left', 'right', 'center', 'justify', 'inherit'] },
4401
- verticalAlign: { type: 'dictionary', values: ['', 'baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom', 'inherit'] },
4402
- lineHeight: { type: 'string' },
4630
+ height: { type: 'string' },
4631
+ left: { type: 'string' },
4403
4632
  letterSpacing: { type: 'string' },
4633
+ lineHeight: { type: 'string' },
4404
4634
  listStyle: { type: 'dictionary', values: ['', 'none', 'disc', 'circle', 'square', 'decimal', 'decimal-leading-zero', 'lower-roman', 'upper-roman', 'lower-greek', 'lower-latin', 'upper-latin', 'armenian', 'georgian', 'lower-alpha', 'upper-alpha', 'none', 'inherit'] },
4405
- wordSpacing: { type: 'dictionary', values: ['', 'normal', 'inherit'] },
4406
- textTransform: { type: 'dictionary', values: ['', 'none', 'capitalize', 'uppercase', 'lowercase', 'inherit'] },
4407
- textIndent: { type: 'string' },
4408
- whiteSpace: { type: 'dictionary', values: ['', 'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit'] },
4409
- wordWrap: { type: 'dictionary', values: ['', 'normal', 'break-word', 'inherit'] },
4410
- wordBreak: { type: 'dictionary', values: ['', 'normal', 'break-all', 'keep-all', 'inherit'] },
4411
- overflow: { type: 'dictionary', values: ['', 'visible', 'hidden', 'scroll', 'auto', 'inherit'] },
4412
- overflowX: { type: 'dictionary', values: ['', 'visible', 'hidden', 'scroll', 'auto', 'inherit'] },
4413
- overflowY: { type: 'dictionary', values: ['', 'visible', 'hidden', 'scroll', 'auto', 'inherit'] },
4414
- zIndex: { type: 'string' },
4415
- cursor: { type: 'dictionary', values: ['', 'auto', 'crosshair', 'default', 'pointer', 'move', 'e-resize', 'ne-resize', 'nw-resize', 'n-resize', 'se-resize', 'sw-resize', 's-resize', 'w-resize', 'text', 'wait', 'help', 'progress', 'inherit'] },
4416
- visibility: { type: 'dictionary', values: ['', 'visible', 'hidden', 'collapse', 'inherit'] },
4417
- opacity: { type: 'string' },
4418
- filter: { type: 'string' },
4419
- transformOrigin: { type: 'string' },
4420
- transition: { type: 'string' },
4421
- boxShadow: { type: 'string' },
4422
- textShadow: { type: 'string' },
4423
- background: { type: 'string' },
4424
- backgroundPosition: { type: 'dictionary', values: ['', 'left top', 'left center', 'left bottom', 'right top', 'right center', 'right bottom', 'center top', 'center center', 'center bottom', 'x% y%', 'xpos ypos', 'inherit'] },
4425
- backgroundRepeat: { type: 'dictionary', values: ['', 'repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'inherit'] },
4426
- backgroundAttachment: { type: 'dictionary', values: ['', 'scroll', 'fixed', 'local', 'inherit'] },
4427
- backgroundSize: { type: 'dictionary', values: ['', 'auto', 'cover', 'contain', 'inherit'] },
4428
- backgroundImage: { type: 'string' },
4429
- backgroundClip: { type: 'dictionary', values: ['', 'border-box', 'padding-box', 'content-box', 'inherit'] },
4430
- backgroundOrigin: { type: 'dictionary', values: ['', 'padding-box', 'border-box', 'content-box', 'inherit'] },
4431
- backgroundBlendMode: { type: 'dictionary', values: ['', 'normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'saturation', 'color', 'luminosity', 'inherit'] },
4432
- clip: { type: 'string' },
4433
- clipPath: { type: 'string' },
4434
- clipRule: { type: 'dictionary', values: ['', 'nonzero', 'evenodd', 'inherit'] },
4635
+ marginTop: { type: 'string' },
4636
+ marginRight: { type: 'string' },
4637
+ marginBottom: { type: 'string' },
4638
+ marginLeft: { type: 'string' },
4435
4639
  mask: { type: 'string' },
4436
4640
  maskType: { type: 'dictionary', values: ['', 'luminance', 'alpha', 'auto', 'inherit'] },
4437
4641
  maskImage: { type: 'string' },
@@ -4452,19 +4656,40 @@ class DesignerComponent {
4452
4656
  maskBorderClip: { type: 'dictionary', values: ['', 'border-box', 'padding-box', 'content-box', 'inherit'] },
4453
4657
  maskBorderOrigin: { type: 'dictionary', values: ['', 'border-box', 'padding-box', 'content-box', 'inherit'] },
4454
4658
  maskBorderComposite: { type: 'dictionary', values: ['', 'add', 'subtract', 'intersect', 'exclude', 'inherit'] },
4659
+ maxHeight: { type: 'string' },
4660
+ maxWidth: { type: 'string' },
4661
+ minWidth: { type: 'string' },
4662
+ minHeight: { type: 'string' },
4663
+ opacity: { type: 'string' },
4664
+ overflow: { type: 'dictionary', values: ['', 'visible', 'hidden', 'scroll', 'auto', 'inherit'] },
4665
+ overflowX: { type: 'dictionary', values: ['', 'visible', 'hidden', 'scroll', 'auto', 'inherit'] },
4666
+ overflowY: { type: 'dictionary', values: ['', 'visible', 'hidden', 'scroll', 'auto', 'inherit'] },
4667
+ paddingTop: { type: 'string' },
4668
+ paddingRight: { type: 'string' },
4669
+ paddingBottom: { type: 'string' },
4670
+ paddingLeft: { type: 'string' },
4671
+ position: { type: 'dictionary', values: ['', 'relative', 'absolute', 'fixed', 'static', 'sticky', 'inherit'] },
4672
+ textAlign: { type: 'dictionary', values: ['', 'left', 'right', 'center', 'justify', 'inherit'] },
4673
+ textIndent: { type: 'string' },
4674
+ textTransform: { type: 'dictionary', values: ['', 'none', 'capitalize', 'uppercase', 'lowercase', 'inherit'] },
4675
+ textDecoration: { type: 'dictionary', values: ['', 'none', 'underline', 'overline', 'line-through', 'blink'] },
4676
+ textShadow: { type: 'string' },
4677
+ top: { type: 'string' },
4678
+ transformOrigin: { type: 'string' },
4679
+ transform: { type: 'string' },
4680
+ transition: { type: 'string' },
4455
4681
  transitionProperty: { type: 'string' },
4456
4682
  transitionDuration: { type: 'string' },
4457
4683
  transitionTimingFunction: { type: 'string' },
4458
4684
  transitionDelay: { type: 'string' },
4459
- animation: { type: 'string' },
4460
- animationName: { type: 'string' },
4461
- animationDuration: { type: 'string' },
4462
- animationTimingFunction: { type: 'string' },
4463
- animationDelay: { type: 'string' },
4464
- animationIterationCount: { type: 'string' },
4465
- animationDirection: { type: 'dictionary', values: ['', 'normal', 'reverse', 'alternate', 'alternate-reverse', 'inherit'] },
4466
- animationFillMode: { type: 'dictionary', values: ['', 'none', 'forwards', 'backwards', 'both', 'inherit'] },
4467
- animationPlayState: { type: 'dictionary', values: ['', 'running', 'paused', 'inherit'] }
4685
+ verticalAlign: { type: 'dictionary', values: ['', 'baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom', 'inherit'] },
4686
+ visibility: { type: 'dictionary', values: ['', 'visible', 'hidden', 'collapse', 'inherit'] },
4687
+ whiteSpace: { type: 'dictionary', values: ['', 'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit'] },
4688
+ width: { type: 'string' },
4689
+ wordSpacing: { type: 'dictionary', values: ['', 'normal', 'inherit'] },
4690
+ wordWrap: { type: 'dictionary', values: ['', 'normal', 'break-word', 'inherit'] },
4691
+ wordBreak: { type: 'dictionary', values: ['', 'normal', 'break-all', 'keep-all', 'inherit'] },
4692
+ zIndex: { type: 'string' }
4468
4693
  };
4469
4694
  this.tableInputProperties = {
4470
4695
  rows: { type: 'numberToArray', converter: this.converter.bind(this) },
@@ -4480,24 +4705,24 @@ class DesignerComponent {
4480
4705
  tableBorderCollapse: { type: 'dictionary', values: ['', 'separate', 'collapse', 'inherit'] }
4481
4706
  };
4482
4707
  this.htmlInputs = {
4483
- cssClass: [],
4484
- cssFile: '',
4485
- width: '100px',
4486
- height: '100px',
4487
- backgroundColor: 'transparent',
4488
- color: 'inherit',
4489
- borderBottomStyle: 'solid',
4490
- borderBottomWidth: '1px',
4491
- borderBottomColor: 'inherit',
4492
- borderLeftStyle: 'solid',
4493
- borderLeftWidth: '1px',
4494
- borderLeftColor: 'inherit',
4495
- borderRightStyle: 'solid',
4496
- borderRightWidth: '1px',
4497
- borderRightColor: 'inherit',
4498
- borderTopStyle: 'solid',
4499
- borderTopWidth: '1px',
4500
- borderTopColor: 'inherit'
4708
+ cssClass: ['html-input-designer'],
4709
+ cssFile: 'styles.css',
4710
+ // width: '100px',
4711
+ // height: '100px',
4712
+ // backgroundColor: 'transparent',
4713
+ // color: 'inherit',
4714
+ // borderBottomStyle: 'solid',
4715
+ // borderBottomWidth: '1px',
4716
+ // borderBottomColor: 'inherit',
4717
+ // borderLeftStyle: 'solid',
4718
+ // borderLeftWidth: '1px',
4719
+ // borderLeftColor: 'inherit',
4720
+ // borderRightStyle: 'solid',
4721
+ // borderRightWidth: '1px',
4722
+ // borderRightColor: 'inherit',
4723
+ // borderTopStyle: 'solid',
4724
+ // borderTopWidth: '1px',
4725
+ // borderTopColor: 'inherit'
4501
4726
  };
4502
4727
  this.tableInputs = {
4503
4728
  rows: 2, // Array(2).fill(1).map((x, i) => i)
@@ -4590,24 +4815,7 @@ class DesignerComponent {
4590
4815
  };
4591
4816
  Object.assign(this.bindableHtmlInputs, this.htmlInputs);
4592
4817
  Object.assign(this.bindableHtmlInputs, {
4593
- width: null,
4594
- display: 'inline-block',
4595
- height: null,
4596
- // borderStyle: null,
4597
- // borderWidth: null,
4598
- // borderColor: null,
4599
- borderBottomStyle: null,
4600
- borderBottomWidth: null,
4601
- borderBottomColor: null,
4602
- borderLeftStyle: null,
4603
- borderLeftWidth: null,
4604
- borderLeftColor: null,
4605
- borderRightStyle: null,
4606
- borderRightWidth: null,
4607
- borderRightColor: null,
4608
- borderTopStyle: null,
4609
- borderTopWidth: null,
4610
- borderTopColor: null
4818
+ cssClass: ['html-input-bindable-designer']
4611
4819
  });
4612
4820
  this.headerProps = {
4613
4821
  headerType: {
@@ -4675,6 +4883,10 @@ class DesignerComponent {
4675
4883
  area.inputs.size = event.sizes[i];
4676
4884
  });
4677
4885
  cd.detectChanges();
4886
+ // Splitter dragEnd is the gesture-end signal — mutated `area.inputs.size`
4887
+ // values must be persisted in undo history right here. Without this,
4888
+ // resizing splitter areas was not undoable.
4889
+ this.commitHistoryIfChanged();
4678
4890
  }
4679
4891
  };
4680
4892
  Object.assign(this.splitterInputs, this.htmlInputs);
@@ -4690,6 +4902,7 @@ class DesignerComponent {
4690
4902
  Object.assign(this.splitterAreaInputs, this.htmlInputs);
4691
4903
  delete this.splitterAreaInputs['width'];
4692
4904
  delete this.splitterAreaInputs['height'];
4905
+ delete this.splitterAreaInputs['cssClass'];
4693
4906
  this.accordionProps = {
4694
4907
  items: { type: 'numberToArray', converter: this.converterAccordion.bind(this) },
4695
4908
  toggle: { type: 'function', hide: true }
@@ -4721,6 +4934,7 @@ class DesignerComponent {
4721
4934
  items: 2
4722
4935
  };
4723
4936
  Object.assign(this.accordionAreaInputs, this.htmlInputs);
4937
+ delete this.accordionAreaInputs['cssClass'];
4724
4938
  this.accordionAreaInputs['height'] = null;
4725
4939
  this.accordionAreaInputs['display'] = 'block';
4726
4940
  // this.accordionAreaInputs['borderStyle'] = 'none';
@@ -4745,7 +4959,7 @@ class DesignerComponent {
4745
4959
  group: 'HTML',
4746
4960
  toolId: 1,
4747
4961
  name: 'TABLE',
4748
- tag: `<table [attr.id]="uniqueName" [attr.title]="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" [attr.title]="uniqueName + ' - ' + nestedTR.uniqueName" ${this.htmlStyleString.replace(/0/g, 'nestedTR.inputs')}><td *ngFor="let nestedTD of nestedTR.nestedComponents" [attr.id]="nestedTD.uniqueName" [attr.title]="uniqueName + ' - ' + nestedTR.uniqueName + ' - ' + 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>`,
4962
+ 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>`,
4749
4963
  icon: 'pi pi-table',
4750
4964
  inputProps: tableProps,
4751
4965
  inputs: tableFullInputs,
@@ -4760,7 +4974,7 @@ class DesignerComponent {
4760
4974
  tag: ``,
4761
4975
  icon: 'pi pi-bars',
4762
4976
  inputProps: this.htmlInputProperties,
4763
- inputs: tableFullInputs,
4977
+ inputs: Object.assign({}, tableFullInputs, { cssClass: [] }),
4764
4978
  nestedComponents: []
4765
4979
  },
4766
4980
  {
@@ -4777,14 +4991,14 @@ class DesignerComponent {
4777
4991
  inputs: Object.assign({}, tableFullInputs, {
4778
4992
  colSpan: '',
4779
4993
  rowSpan: ''
4780
- }),
4994
+ }, { cssClass: [] }),
4781
4995
  nestedComponents: []
4782
4996
  },
4783
4997
  {
4784
4998
  group: 'HTML',
4785
4999
  toolId: 2,
4786
5000
  name: 'DIV',
4787
- tag: `<div [attr.id]="uniqueName" [attr.title]="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>`,
5001
+ 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>`,
4788
5002
  icon: 'pi pi-stop',
4789
5003
  inputProps: this.htmlInputProperties,
4790
5004
  inputs: this.htmlInputs,
@@ -4795,7 +5009,7 @@ class DesignerComponent {
4795
5009
  group: 'HTML',
4796
5010
  toolId: 3,
4797
5011
  name: 'SPAN',
4798
- tag: `<span [attr.id]="uniqueName" [attr.title]="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>`,
5012
+ 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>`,
4799
5013
  icon: 'pi pi-language',
4800
5014
  inputProps: this.bindableHtmlProps,
4801
5015
  inputs: this.bindableHtmlInputs
@@ -4804,7 +5018,7 @@ class DesignerComponent {
4804
5018
  group: 'HTML',
4805
5019
  toolId: 17,
4806
5020
  name: 'LABEL',
4807
- tag: `<label [attr.id]="uniqueName" [attr.title]="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>`,
5021
+ 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>`,
4808
5022
  icon: 'pi pi-tag',
4809
5023
  inputProps: Object.assign({}, this.bindableHtmlProps, {
4810
5024
  displayField: { type: 'dictionary', values: [''], propertyCaption: 'Display Field' },
@@ -4822,7 +5036,7 @@ class DesignerComponent {
4822
5036
  group: 'HTML',
4823
5037
  toolId: 4,
4824
5038
  name: 'Hx',
4825
- tag: `<h1 *ngIf="inputs.headerType == 'h1'" [attr.id]="uniqueName" [attr.title]="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" [attr.title]="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" [attr.title]="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" [attr.title]="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" [attr.title]="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" [attr.title]="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>`,
5039
+ 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>`,
4826
5040
  icon: 'pi pi-chevron-up',
4827
5041
  inputProps: this.headerProps,
4828
5042
  inputs: this.headerInputs
@@ -4831,7 +5045,7 @@ class DesignerComponent {
4831
5045
  group: 'HTML',
4832
5046
  toolId: 5,
4833
5047
  name: 'ANCHOR',
4834
- tag: `<a [attr.id]="uniqueName" [attr.title]="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>`,
5048
+ 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>`,
4835
5049
  icon: 'pi pi-link',
4836
5050
  inputProps: this.anchorProps,
4837
5051
  inputs: this.anchorInputs
@@ -4840,7 +5054,7 @@ class DesignerComponent {
4840
5054
  group: 'HTML',
4841
5055
  toolId: 6,
4842
5056
  name: 'IMG',
4843
- tag: `<img [attr.id]="uniqueName" [attr.title]="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')} />`,
5057
+ 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')} />`,
4844
5058
  icon: 'pi pi-image',
4845
5059
  inputProps: this.imgProps,
4846
5060
  inputs: this.imgInputs
@@ -4849,7 +5063,7 @@ class DesignerComponent {
4849
5063
  group: 'HTML',
4850
5064
  toolId: 18,
4851
5065
  name: 'IFRAME',
4852
- tag: `<iframe [attr.id]="uniqueName" [attr.title]="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>`,
5066
+ 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>`,
4853
5067
  icon: 'pi pi-window-maximize',
4854
5068
  inputProps: Object.assign({}, this.htmlInputProperties, {
4855
5069
  src: { type: 'string', propertyCaption: 'Source URL' },
@@ -4868,7 +5082,7 @@ class DesignerComponent {
4868
5082
  group: 'HTML',
4869
5083
  toolId: 7,
4870
5084
  name: 'UL',
4871
- tag: `<ul [attr.id]="uniqueName" [attr.title]="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')}>
5085
+ 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')}>
4872
5086
  <li *ngFor="let li of (inputs.datasource?.component?.value?.resultInfo?.dato || (inputs.optionsCsv || '').split(','))">
4873
5087
  <ng-container *ngIf="inputs.displayFormula; else ulItemTemplate">{{getUlItemDisplayValue(inputs, li)}}</ng-container>
4874
5088
  <ng-template #ulItemTemplate>
@@ -4899,7 +5113,7 @@ class DesignerComponent {
4899
5113
  group: 'HTML',
4900
5114
  toolId: 8,
4901
5115
  name: 'BUTTON',
4902
- tag: `<button [attr.id]="uniqueName" [attr.title]="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>`,
5116
+ 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>`,
4903
5117
  icon: 'pi pi-arrow-circle-down',
4904
5118
  inputProps: this.htmlButtonProps,
4905
5119
  inputs: this.bindableHtmlInputs
@@ -4908,7 +5122,7 @@ class DesignerComponent {
4908
5122
  group: 'HTML',
4909
5123
  toolId: 9,
4910
5124
  name: 'INPUT',
4911
- tag: `<input [attr.id]="uniqueName" [attr.title]="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')} />`,
5125
+ 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')} />`,
4912
5126
  icon: 'pi pi-pencil',
4913
5127
  inputProps: Object.assign({}, this.htmlInputProperties, {
4914
5128
  inputType: { type: 'dictionary', propertyCaption: 'Type', values: ['text', 'number', 'email', 'password', 'search', 'url'] },
@@ -4930,7 +5144,7 @@ class DesignerComponent {
4930
5144
  group: 'HTML',
4931
5145
  toolId: 10,
4932
5146
  name: 'TEXTAREA',
4933
- tag: `<textarea [attr.id]="uniqueName" [attr.title]="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>`,
5147
+ 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>`,
4934
5148
  icon: 'pi pi-align-left',
4935
5149
  inputProps: Object.assign({}, this.htmlInputProperties, {
4936
5150
  placeholder: { type: 'string', propertyCaption: 'Placeholder' },
@@ -4952,7 +5166,7 @@ class DesignerComponent {
4952
5166
  group: 'HTML',
4953
5167
  toolId: 11,
4954
5168
  name: 'CHECKBOX',
4955
- tag: `<label [attr.id]="uniqueName" [attr.title]="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>`,
5169
+ 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>`,
4956
5170
  icon: 'pi pi-check-square',
4957
5171
  inputProps: Object.assign({}, this.htmlInputProperties, {
4958
5172
  label: { type: 'string', propertyCaption: 'Label' },
@@ -4976,7 +5190,7 @@ class DesignerComponent {
4976
5190
  group: 'HTML',
4977
5191
  toolId: 12,
4978
5192
  name: 'SEPARATOR',
4979
- tag: `<hr [attr.id]="uniqueName" [attr.title]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
5193
+ tag: `<hr [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
4980
5194
  icon: 'pi pi-minus',
4981
5195
  inputProps: this.htmlInputProperties,
4982
5196
  inputs: Object.assign({}, this.htmlInputs, {
@@ -4995,7 +5209,7 @@ class DesignerComponent {
4995
5209
  group: 'HTML',
4996
5210
  toolId: 19,
4997
5211
  name: 'HR',
4998
- tag: `<hr [attr.id]="uniqueName" [attr.title]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
5212
+ tag: `<hr [attr.id]="uniqueName" ngxDraggableDom="true" ngResizable [rzHandles]="'e'" (rzResizing)="onResizing($event, this)" (moved)="onMoving($event, this)" ${this.htmlStyleString.replace(/0/g, 'inputs')} />`,
4999
5213
  icon: 'pi pi-minus',
5000
5214
  inputProps: this.htmlInputProperties,
5001
5215
  inputs: Object.assign({}, this.htmlInputs, {
@@ -5014,7 +5228,7 @@ class DesignerComponent {
5014
5228
  group: 'HTML',
5015
5229
  toolId: 13,
5016
5230
  name: 'KPI',
5017
- tag: `<div [attr.id]="uniqueName" [attr.title]="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>`,
5231
+ 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>`,
5018
5232
  icon: 'pi pi-chart-line',
5019
5233
  inputProps: Object.assign({}, this.htmlInputProperties, {
5020
5234
  caption: { type: 'string', propertyCaption: 'Caption' },
@@ -5039,7 +5253,7 @@ class DesignerComponent {
5039
5253
  group: 'HTML',
5040
5254
  toolId: 14,
5041
5255
  name: 'DATE',
5042
- tag: `<input [attr.id]="uniqueName" [attr.title]="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')} />`,
5256
+ 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')} />`,
5043
5257
  icon: 'pi pi-calendar',
5044
5258
  inputProps: Object.assign({}, this.htmlInputProperties, {
5045
5259
  value: { type: 'string', propertyCaption: 'Value (yyyy-mm-dd)' },
@@ -5058,7 +5272,7 @@ class DesignerComponent {
5058
5272
  group: 'HTML',
5059
5273
  toolId: 15,
5060
5274
  name: 'SELECT',
5061
- tag: `<select [attr.id]="uniqueName" [attr.title]="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>`,
5275
+ 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>`,
5062
5276
  icon: 'pi pi-list',
5063
5277
  inputProps: Object.assign({}, this.htmlInputProperties, this.dsProperties, {
5064
5278
  optionsCsv: { type: 'string', propertyCaption: 'Options CSV' },
@@ -5085,7 +5299,7 @@ class DesignerComponent {
5085
5299
  group: 'HTML',
5086
5300
  toolId: 16,
5087
5301
  name: 'MULTISELECT',
5088
- tag: `<select [attr.id]="uniqueName" [attr.title]="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>`,
5302
+ 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>`,
5089
5303
  icon: 'pi pi-check-square',
5090
5304
  inputProps: Object.assign({}, this.htmlInputProperties, this.dsProperties, {
5091
5305
  optionsCsv: { type: 'string', propertyCaption: 'Options CSV' },
@@ -5114,7 +5328,7 @@ class DesignerComponent {
5114
5328
  group: 'DATA',
5115
5329
  toolId: 100,
5116
5330
  name: 'DATASOURCE',
5117
- tag: `<wuic-data-source [attr.id]="uniqueName" [attr.title]="uniqueName" #datasource [autoload]="inputs.autoload" [routeFromRouting]="inputs.routeFromRouting" [route]="inputs.route" [parentRecord]="inputs.selectedItem" [parentMetaInfo]="inputs.parentMetaInfo" [componentRef]="inputs.componentRef"></wuic-data-source>`,
5331
+ tag: `<wuic-data-source [attr.id]="uniqueName" #datasource [autoload]="inputs.autoload" [routeFromRouting]="inputs.routeFromRouting" [route]="inputs.route" [parentRecord]="inputs.selectedItem" [parentMetaInfo]="inputs.parentMetaInfo" [componentRef]="inputs.componentRef"></wuic-data-source>`,
5118
5332
  icon: 'pi pi-database',
5119
5333
  inputProps: {
5120
5334
  autoload: { type: 'boolean' },
@@ -5160,7 +5374,7 @@ class DesignerComponent {
5160
5374
  group: 'DATA',
5161
5375
  toolId: 101,
5162
5376
  name: 'DATAREPEATER',
5163
- tag: `<wuic-data-repeater [attr.id]="uniqueName" [attr.title]="uniqueName" [datasource]="inputs.datasource?.component" [action]="inputs.action" [hideToolbar]="inputs.hideToolbar" [rowCustomSelect]="inputs.rowCustomSelect?.bind(inputs)"></wuic-data-repeater>`,
5377
+ tag: `<wuic-data-repeater [attr.id]="uniqueName" [datasource]="inputs.datasource?.component" [action]="inputs.action" [hideToolbar]="inputs.hideToolbar" [rowCustomSelect]="inputs.rowCustomSelect?.bind(inputs)"></wuic-data-repeater>`,
5164
5378
  icon: 'pi pi-table',
5165
5379
  inputProps: this.repeaterProperties,
5166
5380
  inputs: {
@@ -5181,7 +5395,7 @@ class DesignerComponent {
5181
5395
  group: 'DATA',
5182
5396
  toolId: 102,
5183
5397
  name: 'FILTERBAR',
5184
- tag: `<wuic-filter-bar [attr.id]="uniqueName" [attr.title]="uniqueName" [datasource]="inputs.datasource?.component"></wuic-filter-bar>`,
5398
+ tag: `<wuic-filter-bar [attr.id]="uniqueName" [datasource]="inputs.datasource?.component"></wuic-filter-bar>`,
5185
5399
  icon: 'pi pi-filter',
5186
5400
  inputProps: Object.assign({}, this.dsProperties),
5187
5401
  inputs: {
@@ -5193,7 +5407,7 @@ class DesignerComponent {
5193
5407
  group: 'DATA',
5194
5408
  toolId: 104,
5195
5409
  name: 'PAGER',
5196
- tag: `<wuic-pager [attr.id]="uniqueName" [attr.title]="uniqueName" [datasource]="inputs.datasource?.component" [pageSize]="inputs.pageSize" [currentPage]="inputs.currentPage"></wuic-pager>`,
5410
+ tag: `<wuic-pager [attr.id]="uniqueName" [datasource]="inputs.datasource?.component" [pageSize]="inputs.pageSize" [currentPage]="inputs.currentPage"></wuic-pager>`,
5197
5411
  icon: 'pi pi-angle-double-right',
5198
5412
  inputProps: Object.assign({}, this.dsProperties, {
5199
5413
  pageSize: { type: 'string', propertyCaption: 'Page Size' },
@@ -5210,12 +5424,12 @@ class DesignerComponent {
5210
5424
  group: 'CONTAINER',
5211
5425
  toolId: 1000,
5212
5426
  name: 'TABVIEW',
5213
- tag: `<p-tabView [attr.id]="uniqueName" [attr.title]="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')}>
5427
+ 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')}>
5214
5428
  <wuic-dashboard [dashboardElements]="nestedComponents"></wuic-dashboard>
5215
5429
  </p-tabView>`,
5216
5430
  icon: 'pi pi-folder',
5217
5431
  inputProps: this.htmlInputProperties,
5218
- inputs: this.htmlInputs,
5432
+ inputs: Object.assign({}, this.htmlInputs, { cssClass: [] }),
5219
5433
  nestedComponents: [],
5220
5434
  allowedChildren: ['TABPANEL']
5221
5435
  },
@@ -5223,7 +5437,7 @@ class DesignerComponent {
5223
5437
  group: 'CONTAINER',
5224
5438
  toolId: 1001,
5225
5439
  name: 'TABPANEL',
5226
- tag: `<p-tabPanel [attr.id]="uniqueName" [attr.title]="uniqueName" [selected]="inputs.selected">
5440
+ tag: `<p-tabPanel [attr.id]="uniqueName" [selected]="inputs.selected">
5227
5441
  <wuic-dashboard [dashboardElements]="nestedComponents"></wuic-dashboard>
5228
5442
  </p-tabPanel>`,
5229
5443
  icon: 'pi pi-tags',
@@ -5238,8 +5452,8 @@ class DesignerComponent {
5238
5452
  group: 'CONTAINER',
5239
5453
  toolId: 1002,
5240
5454
  name: 'SPLITTER',
5241
- tag: `<p-splitter [attr.id]="uniqueName" [attr.title]="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')}>
5242
- <p-splitter-area *ngFor="let nestedArea of nestedComponents" [attr.id]="nestedArea.uniqueName" [attr.title]="uniqueName + ' - ' + nestedArea.uniqueName" [size]="nestedArea.inputs.size" ${this.htmlStyleString.replace(/0/g, 'nestedArea.inputs')}>
5455
+ 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')}>
5456
+ <p-splitter-area *ngFor="let nestedArea of nestedComponents" [attr.id]="nestedArea.uniqueName" [size]="nestedArea.inputs.size" ${this.htmlStyleString.replace(/0/g, 'nestedArea.inputs')}>
5243
5457
  <wuic-dashboard [dashboardElements]="nestedArea.nestedComponents"></wuic-dashboard>
5244
5458
  </p-splitter-area>
5245
5459
  </p-splitter>`,
@@ -5266,8 +5480,8 @@ class DesignerComponent {
5266
5480
  group: 'CONTAINER',
5267
5481
  toolId: 1004,
5268
5482
  name: 'ACCORDION',
5269
- tag: ` <cdk-accordion class="wuic-accordion-tab" [attr.id]="uniqueName" [attr.title]="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')}>
5270
- <cdk-accordion-item *ngFor="let nestedItem of nestedComponents" [attr.id]="nestedItem.uniqueName" [attr.title]="nestedItem.uniqueName"
5483
+ 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')}>
5484
+ <cdk-accordion-item *ngFor="let nestedItem of nestedComponents" [attr.id]="nestedItem.uniqueName"
5271
5485
  ${this.htmlStyleString.replace(/0/g, 'nestedItem.inputs')}>
5272
5486
  <div class="wuic-accordion-header">
5273
5487
  <a class="wuic-accordion-header-link" (click)="inputs.toggle?.($event, this, nestedItem)">{{nestedItem.inputs.header}}</a>
@@ -5327,7 +5541,7 @@ class DesignerComponent {
5327
5541
  label: this.trslSrv.instant('load')
5328
5542
  },
5329
5543
  {
5330
- label: 'CSS',
5544
+ label: this.t('designer.css', 'CSS'),
5331
5545
  command: () => {
5332
5546
  this.openCssSheetEditor();
5333
5547
  }
@@ -5335,23 +5549,58 @@ class DesignerComponent {
5335
5549
  ];
5336
5550
  this.dashMenus = menus;
5337
5551
  this.refreshGraphActionsMenuItems();
5338
- //verifica se c'è un dashboard da caricare route /datshboard/route-name e fai il loaddashboard di conseguenza
5339
- var routeDashboard = this.route.snapshot.paramMap.get('route');
5340
- if (routeDashboard) {
5341
- this.noEdit = true;
5342
- this.setDesignerEditModeClass(false);
5343
- await this.loadDashboard({ board_route: routeDashboard });
5344
- return;
5345
- }
5346
- this.noEdit = false;
5347
- this.setDesignerEditModeClass(true);
5348
- this.reloadDashboards();
5552
+ // Subscribe to route param changes so navigating between
5553
+ // /:route/dashboard URLs reloads the dashboard (e.g. sasa/dashboard → master-det/dashboard).
5554
+ // Using paramMap observable instead of snapshot ensures the component reacts
5555
+ // when Angular reuses the same instance for a different :route value.
5556
+ this._routeParamSub = this.route.paramMap.subscribe(async (params) => {
5557
+ const routeDashboard = params.get('route');
5558
+ if (routeDashboard) {
5559
+ this.noEdit = true;
5560
+ this.setDesignerEditModeClass(false);
5561
+ await this.loadDashboard({ board_route: routeDashboard });
5562
+ }
5563
+ else {
5564
+ this.noEdit = false;
5565
+ this.setDesignerEditModeClass(true);
5566
+ this.reloadDashboards();
5567
+ }
5568
+ });
5569
+ // Capture-phase mouseup/touchend listeners for post-gesture history commit.
5570
+ //
5571
+ // Why capture phase instead of the @HostListener('window:mouseup') above?
5572
+ // `NgxDraggableDomDirective` attaches a BUBBLE-phase mouseup listener on
5573
+ // `document` that calls `event.stopImmediatePropagation()` (see
5574
+ // directive/ngx-draggable-dom.directive.ts onMouseUp), which kills every
5575
+ // window-level bubble listener — including our HostListener. So dropping a
5576
+ // dragged div never reached `onWindowMouseup` and the history commit was
5577
+ // skipped.
5578
+ //
5579
+ // A capture-phase listener fires BEFORE the bubble phase, so it runs even
5580
+ // if something downstream stops propagation. We still keep the HostListener
5581
+ // path: the commit helper consumes the timestamp (sets it to 0), so the
5582
+ // listener that fires first commits, and any subsequent call no-ops.
5583
+ this._designerGestureMouseUp = this.commitHistoryAfterDesignerGestureIfNeeded.bind(this);
5584
+ document.addEventListener('mouseup', this._designerGestureMouseUp, true);
5585
+ document.addEventListener('touchend', this._designerGestureMouseUp, true);
5349
5586
  }
5350
5587
  ngOnDestroy() {
5588
+ this._routeParamSub?.unsubscribe();
5589
+ if (this._designerGestureMouseUp) {
5590
+ document.removeEventListener('mouseup', this._designerGestureMouseUp, true);
5591
+ document.removeEventListener('touchend', this._designerGestureMouseUp, true);
5592
+ this._designerGestureMouseUp = undefined;
5593
+ }
5351
5594
  this.clearHierarchyHoverHighlight();
5352
5595
  this.clearFooterHoverHighlight();
5353
5596
  this.setDesignerEditModeClass(false);
5354
5597
  }
5598
+ /**
5599
+ * Handler capture-phase per mouseup/touchend su document. Riferimento
5600
+ * conservato per poter fare `removeEventListener` in `ngOnDestroy` (bind
5601
+ * produce una funzione diversa a ogni chiamata quindi va memorizzata).
5602
+ */
5603
+ _designerGestureMouseUp;
5355
5604
  async onWindowHashChange() {
5356
5605
  const nextHash = String(window?.location?.hash || '');
5357
5606
  const previousHash = this.lastKnownHashRoute;
@@ -5665,7 +5914,8 @@ class DesignerComponent {
5665
5914
  value: '',
5666
5915
  required: true
5667
5916
  }
5668
- ], null, "400px");
5917
+ // height=340px: evita lo scroll interno al dialog con 2 campi + footer.
5918
+ ], null, "400px", "340px");
5669
5919
  if (!resp) {
5670
5920
  WtoolboxService.messageNotificationService.add({
5671
5921
  severity: 'warn',
@@ -5727,11 +5977,37 @@ class DesignerComponent {
5727
5977
  'blueprint',
5728
5978
  'extraProps'
5729
5979
  ]);
5730
- this.flattenComponentTree(this.dashboardElements).forEach((element) => {
5980
+ const serializationFlattened = this.flattenComponentTree(this.dashboardElements);
5981
+ serializationFlattened.forEach((element) => {
5731
5982
  if (element.name == 'DATASOURCE') {
5732
5983
  const componentRef = element?.inputs?.['componentRef']?.value?.component;
5733
5984
  const metaInfoFromRef = componentRef?.value?.metaInfo ?? componentRef?.metaInfo ?? null;
5734
- element.inputs['metaInfo'] = metaInfoFromRef;
5985
+ // Only overwrite metaInfo if we got a live reference; otherwise keep the
5986
+ // serialized copy so that undo/redo snapshots preserve the metadata.
5987
+ if (metaInfoFromRef) {
5988
+ element.inputs['metaInfo'] = metaInfoFromRef;
5989
+ }
5990
+ }
5991
+ // Normalize DATAREPEATER.datasource to a lightweight {uniqueName, component}
5992
+ // before serialization. Ensures uniqueName survives JSON round-trip.
5993
+ if (element.name === 'DATAREPEATER' || element.name === 'SELECT' || element.name === 'MULTISELECT' || element.name === 'UL') {
5994
+ const dsInput = element.inputs?.['datasource'];
5995
+ if (dsInput && typeof dsInput === 'object' && !(dsInput instanceof BehaviorSubject)) {
5996
+ // Case 1: full DS element (has inputs) — reduce to lightweight ref
5997
+ if (dsInput.uniqueName && dsInput.inputs) {
5998
+ element.inputs['datasource'] = {
5999
+ uniqueName: dsInput.uniqueName,
6000
+ component: dsInput.component ?? null
6001
+ };
6002
+ }
6003
+ // Case 2: already lightweight but missing uniqueName — recover from tree
6004
+ if (!dsInput.uniqueName && dsInput.component) {
6005
+ const firstDs = serializationFlattened.find((e) => e.name === 'DATASOURCE');
6006
+ if (firstDs?.uniqueName) {
6007
+ dsInput.uniqueName = firstDs.uniqueName;
6008
+ }
6009
+ }
6010
+ }
5735
6011
  }
5736
6012
  });
5737
6013
  return WtoolboxService.safeStringify(this.dashboardElements, function (key, value) {
@@ -5741,6 +6017,16 @@ class DesignerComponent {
5741
6017
  if (key == 'component' && (currentParentProp == 'componentRef' || currentParentProp == 'datasource' || currentParentProp == 'parentDatasource')) {
5742
6018
  return null;
5743
6019
  }
6020
+ // Also null-out live DataSourceComponent instances nested deeper in the tree
6021
+ // (e.g. DATAREPEATER.inputs.datasource.component) where currentParentProp
6022
+ // tracking loses context due to JSON.stringify's sequential key visitation.
6023
+ // The value may be the component directly OR a BehaviorSubject wrapping it.
6024
+ if (key === 'component' && value && typeof value === 'object') {
6025
+ const inner = (value instanceof BehaviorSubject) ? value.value : value;
6026
+ if (inner && typeof inner === 'object' && ('fetchInfo$' in inner || '__ngContext__' in inner)) {
6027
+ return null;
6028
+ }
6029
+ }
5744
6030
  currentParentProp = key;
5745
6031
  if (value instanceof BehaviorSubject) {
5746
6032
  return value.value === undefined ? null : value.value;
@@ -5802,14 +6088,35 @@ class DesignerComponent {
5802
6088
  if (typeof document === 'undefined') {
5803
6089
  return;
5804
6090
  }
5805
- const normalized = Array.from(new Set((sheetPaths || []).map((x) => this.normalizeSheetPath(x)).filter((x) => !!x)));
6091
+ // Filter out placeholder defaults (`styles.css` bare filename) and any
6092
+ // bare-filename path that isn't anchored to an assets/ folder. These are
6093
+ // defaults set on the tool metadata (see `this.htmlInputs.cssFile =
6094
+ // 'styles.css'` at the top of the component) which the user never
6095
+ // overrode with a real CSS file. Emitting a `<link>` for them 404s on
6096
+ // both the frontend origin and the backend fallback, producing noisy
6097
+ // console errors in dev/E2E without any functional impact.
6098
+ const isPlaceholderPath = (p) => {
6099
+ if (!p)
6100
+ return true;
6101
+ const lower = p.toLowerCase();
6102
+ // Single-segment, no `assets/` prefix → treat as placeholder.
6103
+ const stripped = lower.replace(/^\/+/, '');
6104
+ if (stripped === 'styles.css')
6105
+ return true;
6106
+ if (!stripped.includes('/') && stripped.endsWith('.css'))
6107
+ return true;
6108
+ return false;
6109
+ };
6110
+ const normalized = Array.from(new Set((sheetPaths || [])
6111
+ .map((x) => this.normalizeSheetPath(x))
6112
+ .filter((x) => !!x && !isPlaceholderPath(x))));
5806
6113
  const head = document.head;
5807
6114
  const existingLinks = Array.from(head.querySelectorAll('link[data-wuic-dashboard-sheet="true"]'));
5808
6115
  const keepSet = new Set(normalized.map((x) => x.toLowerCase()));
5809
6116
  const resolveStaticBaseUrl = () => {
5810
6117
  try {
5811
6118
  // In designer/ng-serve scenarios css assets are served by the current frontend origin.
5812
- return new URL(document.baseURI || window.location.href).toString();
6119
+ return WtoolboxService.appSettings?.file_path;
5813
6120
  }
5814
6121
  catch {
5815
6122
  return window.location.origin;
@@ -5817,7 +6124,7 @@ class DesignerComponent {
5817
6124
  };
5818
6125
  const resolveBackendStaticBaseUrl = () => {
5819
6126
  try {
5820
- const raw = String(WtoolboxService.appSettings?.global_root_url || '').trim();
6127
+ const raw = WtoolboxService.appSettings?.file_path;
5821
6128
  if (!raw) {
5822
6129
  return '';
5823
6130
  }
@@ -6025,35 +6332,94 @@ class DesignerComponent {
6025
6332
  * Ripristina lo snapshot precedente dalla history undo.
6026
6333
  */
6027
6334
  undo() {
6335
+ console.log(`[UNDO-v9] called. undoLen=${this.undoHistory.length} redoLen=${this.redoHistory.length} applyingHistory=${this.applyingHistory}`);
6028
6336
  if (this.applyingHistory || this.undoHistory.length === 0) {
6337
+ console.log(`[UNDO-v9] SKIP`);
6029
6338
  return;
6030
6339
  }
6031
- const target = this.undoHistory.pop();
6032
- if (!target) {
6033
- return;
6340
+ // Cancel any pending redo rebind timer
6341
+ if (this._redoRebindTimer) {
6342
+ clearTimeout(this._redoRebindTimer);
6343
+ this._redoRebindTimer = undefined;
6344
+ console.log(`[UNDO-v9] cancelled redo rebind timer`);
6345
+ }
6346
+ try {
6347
+ const target = this.undoHistory.pop();
6348
+ if (this.lastCommittedSnapshot) {
6349
+ this.redoHistory.push(this.lastCommittedSnapshot);
6350
+ }
6351
+ this.lastCommittedSnapshot = target;
6352
+ console.log(`[UNDO-v9] applying target. undoLen=${this.undoHistory.length} redoLen=${this.redoHistory.length}`);
6353
+ this.applyHistorySnapshot(target, false);
6034
6354
  }
6035
- if (this.lastCommittedSnapshot) {
6036
- this.redoHistory.push(this.lastCommittedSnapshot);
6355
+ catch (err) {
6037
6356
  }
6038
- this.applyHistorySnapshot(target);
6039
- this.lastCommittedSnapshot = target;
6040
6357
  }
6041
6358
  /**
6042
6359
  * Riapplica lo snapshot successivo dalla history redo.
6043
6360
  */
6044
6361
  redo() {
6362
+ console.log(`[REDO-v9] called. undoLen=${this.undoHistory.length} redoLen=${this.redoHistory.length} applyingHistory=${this.applyingHistory}`);
6045
6363
  if (this.applyingHistory || this.redoHistory.length === 0) {
6364
+ console.log(`[REDO-v9] SKIP`);
6046
6365
  return;
6047
6366
  }
6048
- const target = this.redoHistory.pop();
6049
- if (!target) {
6050
- return;
6367
+ try {
6368
+ const target = this.redoHistory.pop();
6369
+ if (this.lastCommittedSnapshot) {
6370
+ this.undoHistory.push(this.lastCommittedSnapshot);
6371
+ }
6372
+ console.log(`[REDO-v9] applying target. undoLen=${this.undoHistory.length} redoLen=${this.redoHistory.length}`);
6373
+ this.lastCommittedSnapshot = target;
6374
+ this.applyHistorySnapshot(target, true);
6375
+ // Re-bind DATAREPEATER→DATASOURCE after redo.
6376
+ // Cancel any previous pending rebind (e.g. if user does redo then undo quickly).
6377
+ if (this._redoRebindTimer) {
6378
+ clearTimeout(this._redoRebindTimer);
6379
+ }
6380
+ this._redoRebindTimer = setTimeout(() => {
6381
+ this._redoRebindTimer = undefined;
6382
+ console.log(`[REDO-REBIND-v9] timer fired. redoLen=${this.redoHistory.length} applyingHistory=${this.applyingHistory}`);
6383
+ // Skip if user already did undo since the redo
6384
+ if (this.redoHistory.length > 0 || this.applyingHistory) {
6385
+ console.log(`[REDO-REBIND-v9] SKIP`);
6386
+ return;
6387
+ }
6388
+ this.applyingHistory = true;
6389
+ try {
6390
+ const liveFlat = this.flattenedDashboardElements || [];
6391
+ liveFlat.forEach((el) => {
6392
+ if (el?.name === 'DATASOURCE') {
6393
+ const cr = el?.inputs?.['componentRef'];
6394
+ const crVal = (cr instanceof BehaviorSubject) ? cr.value : cr;
6395
+ const liveComp = crVal?.component instanceof BehaviorSubject
6396
+ ? crVal.component.value : crVal?.component;
6397
+ if (liveComp) {
6398
+ liveFlat.forEach((dr) => {
6399
+ if (dr?.name === 'DATAREPEATER' || dr?.name === 'SELECT' || dr?.name === 'MULTISELECT' || dr?.name === 'UL') {
6400
+ const dsRef = dr?.inputs?.['datasource'];
6401
+ if (dsRef?.uniqueName === el.uniqueName && dsRef?.component instanceof BehaviorSubject) {
6402
+ dsRef.component.next(liveComp);
6403
+ }
6404
+ }
6405
+ });
6406
+ if (liveComp.fetchData) {
6407
+ liveComp.fetchData();
6408
+ }
6409
+ }
6410
+ }
6411
+ });
6412
+ this.cd.detectChanges();
6413
+ }
6414
+ finally {
6415
+ this.applyingHistory = false;
6416
+ this._lastHistoryApplyTime = Date.now();
6417
+ }
6418
+ }, 1000);
6051
6419
  }
6052
- if (this.lastCommittedSnapshot) {
6053
- this.undoHistory.push(this.lastCommittedSnapshot);
6420
+ catch (err) {
6421
+ // redo error — ignore
6054
6422
  }
6055
- this.applyHistorySnapshot(target);
6056
- this.lastCommittedSnapshot = target;
6057
6423
  }
6058
6424
  /**
6059
6425
  * Gestisce shortcut globali undo/redo (`Ctrl/Cmd+Z`, `Ctrl/Cmd+Shift+Z`, `Ctrl/Cmd+Y`)
@@ -6087,30 +6453,73 @@ class DesignerComponent {
6087
6453
  }
6088
6454
  }
6089
6455
  /**
6090
- * Chiude transazioni history pendenti da color picker al rilascio mouse.
6456
+ * Chiude transazioni history pendenti da color picker al rilascio mouse e
6457
+ * committa la history se l'utente ha appena terminato un drag/resize di un
6458
+ * elemento del designer.
6091
6459
  */
6092
6460
  onWindowMouseup() {
6093
- this.finalizePendingColorHistory();
6094
- this.commitHistoryIfChanged();
6461
+ if (!this.finalizePendingColorHistory()) {
6462
+ // Generic mouseup MUST NOT call commitHistoryIfChanged unconditionally:
6463
+ // mouseup fires BEFORE click, so clicking the Undo/Redo button would
6464
+ // otherwise commit (clearing redoHistory) before the (click) handler runs.
6465
+ //
6466
+ // Drag/resize gestures however are NOT captured by any other commit path
6467
+ // (onResizing/onMoving in DynamicDashboardTemplateComponent only mutate
6468
+ // inputs.width/height/transform without any history hook), so the final
6469
+ // size/position would never make it into undoHistory.
6470
+ //
6471
+ // We resolve the conflict via a "did the user just drag/resize a
6472
+ // designer element?" check: onResizing/onMoving stamp a static timestamp
6473
+ // each time they fire; here we commit only if that timestamp is fresh,
6474
+ // then consume it so unrelated mouseups don't trigger spurious commits.
6475
+ this.commitHistoryAfterDesignerGestureIfNeeded();
6476
+ }
6477
+ }
6478
+ /**
6479
+ * Variante touch: stesso meccanismo di mouseup per supportare drag/resize
6480
+ * via touch su designer.
6481
+ */
6482
+ onWindowTouchend() {
6483
+ if (!this.finalizePendingColorHistory()) {
6484
+ this.commitHistoryAfterDesignerGestureIfNeeded();
6485
+ }
6095
6486
  }
6096
6487
  /**
6097
- * Variante touch di finalizzazione history pendente.
6488
+ * Se l'utente ha appena terminato un drag/resize di un elemento del designer
6489
+ * (rilevato tramite il timestamp statico aggiornato da `onResizing`/`onMoving`
6490
+ * in `DynamicDashboardTemplateComponent`), committa lo snapshot history e
6491
+ * consuma il timestamp. La finestra di 1000ms tollera lievi ritardi tra
6492
+ * ultimo evento di gesture e mouseup; valori piu bassi rischiavano di
6493
+ * mancare commit su gesture brevi su laptop lenti.
6098
6494
  */
6099
- onWindowTouchend() {
6100
- this.finalizePendingColorHistory();
6495
+ commitHistoryAfterDesignerGestureIfNeeded() {
6496
+ const ts = DynamicDashboardTemplateComponent.lastDesignerGestureTimestamp;
6497
+ if (!ts) {
6498
+ return;
6499
+ }
6500
+ const elapsed = Date.now() - ts;
6501
+ if (elapsed > 1000) {
6502
+ // Stale signal (the gesture was much earlier — e.g., the user dragged,
6503
+ // released, then later clicked an unrelated button without dragging).
6504
+ // Reset so we don't keep checking a never-cleared old timestamp.
6505
+ DynamicDashboardTemplateComponent.lastDesignerGestureTimestamp = 0;
6506
+ return;
6507
+ }
6508
+ DynamicDashboardTemplateComponent.lastDesignerGestureTimestamp = 0;
6101
6509
  this.commitHistoryIfChanged();
6102
6510
  }
6103
6511
  /**
6104
6512
  * Esegue commit history su modifiche input concluse da tastiera.
6105
6513
  */
6106
6514
  onWindowKeyup() {
6107
- this.commitHistoryIfChanged();
6108
6515
  }
6109
6516
  /**
6110
6517
  * Esegue commit history su eventi `change` globali dei controlli.
6111
6518
  */
6112
6519
  onWindowChange() {
6113
- this.commitHistoryIfChanged();
6520
+ // Removed commitHistoryIfChanged — change events from inputs during
6521
+ // undo/redo rehydration cause spurious commits that clear redoHistory.
6522
+ // Commits are already triggered by setValue, drop, mouseup, etc.
6114
6523
  }
6115
6524
  get currentDashboardTitle() {
6116
6525
  const route = String(this.currentDashboardRoute || '').trim();
@@ -6217,27 +6626,48 @@ class DesignerComponent {
6217
6626
  }
6218
6627
  /**
6219
6628
  * Rigenera il menu azioni rapido del designer (`graphActionsMenuItems`),
6220
- * collegando le entry ai rispettivi handler toolbar (riapri, nuovo, salva, elimina, CSS).
6629
+ * collegando le entry ai rispettivi handler toolbar (riapri, nuovo, salva,
6630
+ * elimina, CSS). Viene invocato:
6631
+ * - al bootstrap del component;
6632
+ * - ogni volta che l'utente clicca il button "Azioni designer" (handler
6633
+ * nel template chiama `refreshGraphActionsMenuItems()` PRIMA di
6634
+ * `graphActionsMenu.toggle($event)`), cosi' i label sono sempre
6635
+ * ri-tradotti con la lingua corrente — fix 2026-04-23 per il caso in
6636
+ * cui l'utente cambia lingua mentre il popup non e' mai stato aperto
6637
+ * in quella lingua: i `this.t(...)` dei label restavano appiccicati
6638
+ * alla lingua di bootstrap;
6639
+ * - dopo `toggleHideDatasourcesInCanvas()` per aggiornare la label/icon
6640
+ * della voce show/hide datasource.
6641
+ *
6642
+ * Deve essere `public` perche' il template lo invoca direttamente
6643
+ * (strictTemplates: true in tsconfig).
6221
6644
  */
6222
6645
  refreshGraphActionsMenuItems() {
6223
6646
  this.graphActionsMenuItems = [
6224
6647
  {
6225
- label: 'Riapri',
6648
+ label: this.t('designer.menu_reopen', 'Riapri'),
6226
6649
  icon: 'pi pi-folder-open',
6227
6650
  command: () => this.openReopenDashboardDialog()
6228
6651
  },
6229
6652
  {
6230
- label: 'Nuovo grafo',
6653
+ label: this.t('designer.menu_new', 'Nuovo grafo'),
6231
6654
  icon: 'pi pi-file',
6232
6655
  command: () => this.onToolbarNewDashboard()
6233
6656
  },
6234
6657
  {
6235
- label: 'Salva grafo',
6658
+ label: this.t('designer.menu_save', 'Salva grafo'),
6236
6659
  icon: 'pi pi-save',
6237
6660
  command: () => this.onToolbarSaveDashboard()
6238
6661
  },
6239
6662
  {
6240
- label: 'Elimina',
6663
+ label: this.t('designer.css', 'CSS'),
6664
+ icon: 'pi pi-palette',
6665
+ command: () => {
6666
+ this.openCssSheetEditor();
6667
+ }
6668
+ },
6669
+ {
6670
+ label: this.t('designer.menu_delete', 'Elimina'),
6241
6671
  icon: 'pi pi-trash',
6242
6672
  disabled: !this.currentDashboardRoute,
6243
6673
  command: () => this.onToolbarDeleteDashboard()
@@ -6246,7 +6676,9 @@ class DesignerComponent {
6246
6676
  separator: true
6247
6677
  },
6248
6678
  {
6249
- label: this.hideDatasourcesInCanvas ? 'Mostra datasource nel canvas' : 'Nascondi datasource nel canvas',
6679
+ label: this.hideDatasourcesInCanvas
6680
+ ? this.t('designer.menu_show_datasources', 'Mostra datasource nel canvas')
6681
+ : this.t('designer.menu_hide_datasources', 'Nascondi datasource nel canvas'),
6250
6682
  icon: this.hideDatasourcesInCanvas ? 'pi pi-eye' : 'pi pi-eye-slash',
6251
6683
  command: () => this.toggleHideDatasourcesInCanvas()
6252
6684
  }
@@ -7176,7 +7608,7 @@ class DesignerComponent {
7176
7608
  buildFieldEditorContextMenuItems(field, ds) {
7177
7609
  return [
7178
7610
  {
7179
- label: 'Apri metadato colonna',
7611
+ label: this.t('designer.ctx_open_column_metadata', 'Apri metadato colonna'),
7180
7612
  icon: 'pi pi-external-link',
7181
7613
  command: () => {
7182
7614
  void this.metadataEditorSrv.openMetadataColumnEditorInContext(field, this.metaSrv, ds)
@@ -7184,7 +7616,7 @@ class DesignerComponent {
7184
7616
  }
7185
7617
  },
7186
7618
  {
7187
- label: 'Sposta in nuovo Tab',
7619
+ label: this.t('designer.ctx_move_to_new_tab', 'Sposta in nuovo Tab'),
7188
7620
  icon: 'pi pi-folder-open',
7189
7621
  command: () => {
7190
7622
  void this.moveContextFieldToNewTab(field, ds)
@@ -7192,7 +7624,7 @@ class DesignerComponent {
7192
7624
  }
7193
7625
  },
7194
7626
  {
7195
- label: 'Sposta in tab esistente',
7627
+ label: this.t('designer.ctx_move_to_existing_tab', 'Sposta in tab esistente'),
7196
7628
  icon: 'pi pi-list',
7197
7629
  command: () => {
7198
7630
  void this.moveContextFieldToExistingTab(field, ds)
@@ -7205,9 +7637,9 @@ class DesignerComponent {
7205
7637
  * Prompt nome tab e aggiorna `mc_edit_associated_tab` della colonna nel datasource designer.
7206
7638
  */
7207
7639
  async moveContextFieldToNewTab(field, ds) {
7208
- const promptResult = await WtoolboxService.promptDialog('Sposta in nuovo Tab', [{
7640
+ const promptResult = await WtoolboxService.promptDialog(this.t('designer.ctx_move_to_new_tab', 'Sposta in nuovo Tab'), [{
7209
7641
  name: 'tabName',
7210
- caption: 'Nome Tab',
7642
+ caption: this.t('designer.tab_name_caption', 'Nome Tab'),
7211
7643
  type: 'text',
7212
7644
  required: true,
7213
7645
  value: this.getAssociatedTabValue(field)
@@ -7685,8 +8117,21 @@ class DesignerComponent {
7685
8117
  if (tool.inputs[toolProp.key] == $event) {
7686
8118
  return;
7687
8119
  }
7688
- if (toolProp.value.asyncPath && !($event[toolProp.value.asyncPath] instanceof BehaviorSubject)) {
7689
- $event[toolProp.value.asyncPath] = new BehaviorSubject($event.inputs.componentRef.value.component);
8120
+ if (toolProp.value.asyncPath) {
8121
+ // For dropped-component-list (e.g. DATAREPEATER.datasource), store a lightweight
8122
+ // reference {uniqueName, component: BS(liveComp)} instead of the full element.
8123
+ // The full element contains circular references and Angular internals that break
8124
+ // JSON serialization and produce snapshots missing the uniqueName.
8125
+ const liveComp = $event?.inputs?.componentRef?.value?.component
8126
+ ?? $event?.inputs?.componentRef?.component
8127
+ ?? null;
8128
+ const compBs = ($event[toolProp.value.asyncPath] instanceof BehaviorSubject)
8129
+ ? $event[toolProp.value.asyncPath]
8130
+ : new BehaviorSubject(liveComp);
8131
+ $event = {
8132
+ uniqueName: $event.uniqueName,
8133
+ [toolProp.value.asyncPath]: compBs
8134
+ };
7690
8135
  }
7691
8136
  tool.inputs[toolProp.key] = $event;
7692
8137
  }
@@ -9030,6 +9475,14 @@ Display formula context:
9030
9475
  }
9031
9476
  }
9032
9477
  }
9478
+ if (!destination) {
9479
+ WtoolboxService.messageNotificationService.add({
9480
+ severity: 'error',
9481
+ summary: this.t('error', 'Error'),
9482
+ detail: this.t('designer.invalid_child_component', 'Invalid child component')
9483
+ });
9484
+ return;
9485
+ }
9033
9486
  destination.push(currentTool);
9034
9487
  if (currentTool.onDrop) {
9035
9488
  currentTool.onDrop(currentTool);
@@ -9053,7 +9506,7 @@ Display formula context:
9053
9506
  filterTool(tool) {
9054
9507
  return !tool.hide;
9055
9508
  }
9056
- getToolPropertySections(tool) {
9509
+ getToolPropertySections(tool, propFilter) {
9057
9510
  const sectionOrder = ['data', 'content', 'layout', 'style', 'behavior', 'advanced'];
9058
9511
  const labels = {
9059
9512
  data: 'Data',
@@ -9074,7 +9527,7 @@ Display formula context:
9074
9527
  const grouped = {};
9075
9528
  sectionOrder.forEach((key) => grouped[key] = []);
9076
9529
  (tool?.toolProps || [])
9077
- .filter((tp) => this.filterTool(tp?.value || {}) && !this.shouldHideToolProp(tool, tp))
9530
+ .filter((tp) => this.filterTool(tp?.value || {}) && !this.shouldHideToolProp(tool, tp, propFilter))
9078
9531
  .forEach((tp) => {
9079
9532
  const section = this.getPropertySectionKey(tp?.key, tp?.value);
9080
9533
  grouped[section].push(tp);
@@ -9086,10 +9539,13 @@ Display formula context:
9086
9539
  .map((key) => ({
9087
9540
  key: key,
9088
9541
  label: labels[key],
9089
- open: savedState[key] !== undefined ? !!savedState[key] : openByDefault[key],
9542
+ open: (propFilter && propFilter.length >= 3 && grouped[key].length) ? true : (savedState[key] !== undefined ? !!savedState[key] : openByDefault[key]),
9090
9543
  props: grouped[key]
9091
9544
  }));
9092
9545
  }
9546
+ clearPropFilter() {
9547
+ this.propFilter = "";
9548
+ }
9093
9549
  /**
9094
9550
  * Persiste lo stato open/close di una sezione pannello proprieta
9095
9551
  * per il tool corrente (chiave per `componentId/uniqueName`).
@@ -9117,7 +9573,7 @@ Display formula context:
9117
9573
  * Determina se una proprieta va nascosta nel pannello:
9118
9574
  * per DATASOURCE nasconde i campi formula master-detail quando manca `parentDatasource`.
9119
9575
  */
9120
- shouldHideToolProp(tool, toolProp) {
9576
+ shouldHideToolProp(tool, toolProp, propFilter) {
9121
9577
  if (!tool || !toolProp) {
9122
9578
  return false;
9123
9579
  }
@@ -9127,6 +9583,9 @@ Display formula context:
9127
9583
  if (tool.name === 'DATAREPEATER' && (toolProp.key === 'wizardNextConfig' || toolProp.key === 'wizardCompleteConfig' || toolProp.key === 'wizardPrevConfig')) {
9128
9584
  return this.getRepeaterAction(tool) !== 'wizard';
9129
9585
  }
9586
+ if (propFilter && propFilter.length >= 3) {
9587
+ return toolProp.key.toLocaleLowerCase().indexOf(propFilter.toLocaleLowerCase()) < 0;
9588
+ }
9130
9589
  return false;
9131
9590
  }
9132
9591
  /**
@@ -9301,6 +9760,17 @@ Display formula context:
9301
9760
  dragEnd() {
9302
9761
  this.draggedPayload = null;
9303
9762
  }
9763
+ /**
9764
+ * Double-click su un tool nella palette: lo droppa al primo livello (root) del canvas,
9765
+ * senza nesting. Simula il flusso drag+drop ma forza destination = dashboardElements.
9766
+ */
9767
+ dropToolAtRoot(payload) {
9768
+ if (this.noEdit) {
9769
+ return;
9770
+ }
9771
+ this.draggedPayload = payload;
9772
+ this.drop({ toElement: null });
9773
+ }
9304
9774
  /**
9305
9775
  * Salva il dashboard corrente tramite `dataSrv.saveDashboard` -> server `MetaService.saveDashboard`.
9306
9776
  * Mapping persistenza verificato su `Kiara_wuic_new.dbo.dom_board`:
@@ -9356,7 +9826,10 @@ Display formula context:
9356
9826
  value: '',
9357
9827
  required: true
9358
9828
  }
9359
- ], null, "320px");
9829
+ // width=400px, height=340px: con default height=250px il body scrollava perche'
9830
+ // 2 campi text con label + footer OK/Cancel non ci stavano. 340px contiene:
9831
+ // header ~45 + 2 x (label+input) ~140 + footer ~60 + padding ~50 = ~295, margine.
9832
+ ], null, "400px", "340px");
9360
9833
  if (resp) {
9361
9834
  var dashboardName = resp.dashboardName.value;
9362
9835
  var newRoute = resp.route.value;
@@ -9394,7 +9867,7 @@ Display formula context:
9394
9867
  * e ricostruisce lo stato runtime del designer partendo da `dom_board.boardcontent`.
9395
9868
  * Supporta route in forme alias (`board_route`, `boardroute`, `dashRoute`).
9396
9869
  */
9397
- async loadDashboard(dashboard) {
9870
+ async loadDashboard(dashboard, skipServerFetch = false) {
9398
9871
  const dashRoute = String(dashboard?.board_route ??
9399
9872
  dashboard?.boardroute ??
9400
9873
  dashboard?.boardRoute ??
@@ -9417,14 +9890,17 @@ Display formula context:
9417
9890
  }
9418
9891
  this.currentDashboardRoute = dashRoute;
9419
9892
  this.refreshGraphActionsMenuItems();
9420
- var payload = {
9421
- user_id: this.userInfo.getuserInfo().user_id,
9422
- dashRoute: dashRoute
9423
- };
9424
- var result = await this.dataSrv.loadDashboard(payload);
9425
- const resultRows = Array.isArray(result)
9426
- ? result
9427
- : (Array.isArray(result?.results) ? result.results : (result ? [result] : []));
9893
+ let resultRows = [];
9894
+ if (!skipServerFetch) {
9895
+ var payload = {
9896
+ user_id: this.userInfo.getuserInfo().user_id,
9897
+ dashRoute: dashRoute
9898
+ };
9899
+ var result = await this.dataSrv.loadDashboard(payload);
9900
+ resultRows = Array.isArray(result)
9901
+ ? result
9902
+ : (Array.isArray(result?.results) ? result.results : (result ? [result] : []));
9903
+ }
9428
9904
  this.currentDashboardDescription = String(dashboard?.board_des ??
9429
9905
  dashboard?.boarddes ??
9430
9906
  resultRows?.[0]?.board_des ??
@@ -9536,6 +10012,7 @@ Display formula context:
9536
10012
  var dsElement = flattened.find(x => x.uniqueName == v.uniqueName);
9537
10013
  if (dsElement) {
9538
10014
  if (ds.component instanceof BehaviorSubject) {
10015
+ console.log(`[SUBSCRIBE-CHAIN-LOAD-v9] pushing liveComp into DR.datasource.component for ${ds.uniqueName}`);
9539
10016
  ds.component.next(v.component);
9540
10017
  if (dsElement.inputs['parentDatasource'] instanceof BehaviorSubject) {
9541
10018
  var dsParent = (dsElement.inputs['parentDatasource'] instanceof BehaviorSubject) ? dsElement.inputs['parentDatasource'].value : dsElement.inputs['parentDatasource'];
@@ -9553,7 +10030,7 @@ Display formula context:
9553
10030
  if (dsElements.length == dsElementCount) {
9554
10031
  combineLatest(dsSubs).subscribe((infos) => {
9555
10032
  infos.forEach((info, i) => {
9556
- if (info && dsElements[i].inputs['metaInfo']) {
10033
+ if (info?.metaInfo && dsElements[i].inputs['metaInfo']) {
9557
10034
  Object.assign(info.metaInfo, dsElements[i].inputs['metaInfo']);
9558
10035
  dsElements[i].inputs['metaInfo'] = null;
9559
10036
  }
@@ -9564,6 +10041,11 @@ Display formula context:
9564
10041
  this.propertyTreeBuilder(ld.inputs['action'].value, ld.inputs);
9565
10042
  }
9566
10043
  });
10044
+ // All DataSources loaded — re-capture the history snapshot
10045
+ // so it includes the full metaInfo. Without this, the initial
10046
+ // snapshot captured by resetHistory() has empty metaInfo because
10047
+ // the DS fetch is async.
10048
+ this.lastCommittedSnapshot = this.captureHistorySnapshot();
9567
10049
  });
9568
10050
  }
9569
10051
  }
@@ -9618,6 +10100,11 @@ Display formula context:
9618
10100
  if (this.applyingHistory || this.noEdit) {
9619
10101
  return;
9620
10102
  }
10103
+ // Skip commit right after undo/redo — the rehydration triggers change
10104
+ // events that would create spurious snapshots and clear redoHistory.
10105
+ if (Date.now() - this._lastHistoryApplyTime < 500) {
10106
+ return;
10107
+ }
9621
10108
  const current = this.captureHistorySnapshot();
9622
10109
  const previous = this.lastCommittedSnapshot;
9623
10110
  if (!previous) {
@@ -9632,7 +10119,9 @@ Display formula context:
9632
10119
  if (this.undoHistory.length > this.maxHistoryLength) {
9633
10120
  this.undoHistory.shift();
9634
10121
  }
9635
- this.redoHistory = [];
10122
+ if (!this._suppressRedoClear) {
10123
+ this.redoHistory = [];
10124
+ }
9636
10125
  this.lastCommittedSnapshot = current;
9637
10126
  }
9638
10127
  /**
@@ -9646,17 +10135,25 @@ Display formula context:
9646
10135
  this.pendingColorHistoryDirty = false;
9647
10136
  }
9648
10137
  /**
9649
- * Applica uno snapshot storico deserializzando gli elementi e ripristinando la selezione.
10138
+ * Applica uno snapshot storico usando lo stesso codepath di loadDashboard.
10139
+ * Passa il serializedElements come boardcontent finto, preservando la route corrente.
9650
10140
  */
9651
- applyHistorySnapshot(snapshot) {
10141
+ applyHistorySnapshot(snapshot, isRedo = false) {
9652
10142
  this.applyingHistory = true;
10143
+ // Destroy + recreate synchronously so applyingHistory stays true
10144
+ // through the entire operation and mouseup doesn't clear redoHistory.
9653
10145
  try {
10146
+ this.dashboardElements = [];
10147
+ this.flattenedDashboardElements = [];
10148
+ this.cd.detectChanges();
9654
10149
  this.applySerializedDashboardElements(snapshot?.serializedElements || '[]', snapshot?.selectedUniqueName || null);
9655
10150
  }
9656
10151
  finally {
9657
- this.applyingHistory = false;
9658
10152
  this.pendingColorHistoryBase = null;
9659
10153
  this.pendingColorHistoryDirty = false;
10154
+ this.lastCommittedSnapshot = snapshot;
10155
+ this.applyingHistory = false;
10156
+ this._lastHistoryApplyTime = Date.now();
9660
10157
  }
9661
10158
  }
9662
10159
  /**
@@ -9664,10 +10161,11 @@ Display formula context:
9664
10161
  */
9665
10162
  finalizePendingColorHistory() {
9666
10163
  if (this.applyingHistory || !this.pendingColorHistoryBase || !this.pendingColorHistoryDirty) {
9667
- return;
10164
+ return false;
9668
10165
  }
9669
10166
  const current = this.captureHistorySnapshot();
9670
10167
  const base = this.pendingColorHistoryBase;
10168
+ let committed = false;
9671
10169
  if (base.serializedElements !== current.serializedElements) {
9672
10170
  this.undoHistory.push(base);
9673
10171
  if (this.undoHistory.length > this.maxHistoryLength) {
@@ -9675,9 +10173,11 @@ Display formula context:
9675
10173
  }
9676
10174
  this.redoHistory = [];
9677
10175
  this.lastCommittedSnapshot = current;
10176
+ committed = true;
9678
10177
  }
9679
10178
  this.pendingColorHistoryBase = null;
9680
10179
  this.pendingColorHistoryDirty = false;
10180
+ return committed;
9681
10181
  }
9682
10182
  /**
9683
10183
  * Ripristina il designer da JSON serializzato:
@@ -9701,6 +10201,11 @@ Display formula context:
9701
10201
  }
9702
10202
  this.mergeMissingToolPropsRecursive(loadedDashboard);
9703
10203
  this.dashboardComponents = [];
10204
+ // Use the same DS tracking / combineLatest rehydration path as loadDashboard
10205
+ // so that DATASOURCE ↔ DATAREPEATER bindings are fully restored on undo/redo.
10206
+ const dsSubs = [];
10207
+ const dsElements = [];
10208
+ const dsElementCount = (loadedDashboard || []).filter((x) => x?.name === 'DATASOURCE').length;
9704
10209
  const flattened = this.flattenComponentTree(loadedDashboard);
9705
10210
  flattened.forEach((element) => {
9706
10211
  if (element?.inputs && element.inputs['cssClass'] !== undefined) {
@@ -9711,6 +10216,16 @@ Display formula context:
9711
10216
  if (normalizedAction) {
9712
10217
  element.inputs['action'] = normalizedAction;
9713
10218
  }
10219
+ else {
10220
+ const inferredFromCustom = Object.keys(element?.inputs || {})
10221
+ .find((k) => k.startsWith('customProps_') && element.inputs[k] != null);
10222
+ if (inferredFromCustom) {
10223
+ const inferredAction = this.normalizeArchetypeAction(inferredFromCustom.replace('customProps_', ''));
10224
+ if (inferredAction) {
10225
+ element.inputs['action'] = inferredAction;
10226
+ }
10227
+ }
10228
+ }
9714
10229
  this.ensureDataRepeaterTagSupportsHideToolbar(element);
9715
10230
  this.ensureDataRepeaterHideToolbar(element);
9716
10231
  this.ensureDataRepeaterRowCustomSelect(element);
@@ -9728,8 +10243,27 @@ Display formula context:
9728
10243
  const customProps = Object.keys(element?.inputs || {}).filter((x) => x.startsWith('customProps_'));
9729
10244
  customProps.forEach((prop) => this.hidrateCustomPropsRecursive(element.inputs[prop]));
9730
10245
  Object.keys(element?.inputProps || {}).forEach((prop) => {
9731
- if (element.inputProps[prop].async) {
9732
- if (element.inputProps[prop].type == 'dropped-component') {
10246
+ const propDef = element.inputProps[prop];
10247
+ // Hydrate dropped-component-list props (e.g. DATAREPEATER.datasource) that have
10248
+ // asyncPath but no async flag. Ensure the inner path (e.g. 'component') is a
10249
+ // BehaviorSubject so the DS→DR binding can be reconnected when Angular creates
10250
+ // the live DataSourceComponent. Do NOT wrap the outer value in a BS — the runtime
10251
+ // expects datasource to remain a plain object {uniqueName, component: BS(...)}.
10252
+ if (!propDef.async && propDef.asyncPath && (propDef.type === 'dropped-component-list' || propDef.type === 'dropped-component')) {
10253
+ const path = propDef.asyncPath;
10254
+ const rawValue = element.inputs[prop];
10255
+ console.log(`[HYDRATE-v9] ${element.name}.${prop}: rawValue=${rawValue === null ? 'NULL' : rawValue === undefined ? 'UNDEF' : 'object'} uniqueName=${rawValue?.uniqueName} keys=${rawValue ? Object.keys(rawValue) : '[]'}`);
10256
+ if (rawValue && typeof rawValue === 'object' && !(rawValue instanceof BehaviorSubject)) {
10257
+ // Only hydrate the component BS — do NOT invent a uniqueName if the
10258
+ // snapshot didn't have one. That would create a false binding on undo.
10259
+ if (!(rawValue[path] instanceof BehaviorSubject)) {
10260
+ rawValue[path] = new BehaviorSubject(rawValue[path] ?? null);
10261
+ console.log(`[HYDRATE-v9] created BS for ${path}`);
10262
+ }
10263
+ }
10264
+ }
10265
+ if (propDef.async) {
10266
+ if (propDef.type == 'dropped-component') {
9733
10267
  const currentValue = element.inputs[prop];
9734
10268
  element.inputs[prop] = new BehaviorSubject({
9735
10269
  component: currentValue?.component ?? currentValue ?? null,
@@ -9738,8 +10272,8 @@ Display formula context:
9738
10272
  uniqueName: element.uniqueName
9739
10273
  });
9740
10274
  }
9741
- else if (element.inputProps[prop].asyncPath) {
9742
- const path = element.inputProps[prop].asyncPath;
10275
+ else if (propDef.asyncPath) {
10276
+ const path = propDef.asyncPath;
9743
10277
  const rawValue = element.inputs[prop] ?? {};
9744
10278
  element.inputs[prop] = new BehaviorSubject({
9745
10279
  ...rawValue,
@@ -9765,8 +10299,45 @@ Display formula context:
9765
10299
  if (dsProp) {
9766
10300
  const dsBs = x.inputs[dsProp];
9767
10301
  const ds = (dsBs instanceof BehaviorSubject) ? dsBs.value : dsBs;
9768
- if (ds && ds.uniqueName == v.uniqueName && ds.component instanceof BehaviorSubject) {
9769
- ds.component.next(v.component);
10302
+ if (ds && ds.uniqueName == v.uniqueName) {
10303
+ const dsElement = flattened.find(fe => fe.uniqueName == v.uniqueName);
10304
+ if (dsElement) {
10305
+ if (ds.component instanceof BehaviorSubject) {
10306
+ console.log(`[SUBSCRIBE-CHAIN-v9] pushing liveComp into DR.datasource.component for ${ds.uniqueName}. applyingHistory=${this.applyingHistory}`);
10307
+ ds.component.next(v.component);
10308
+ if (dsElement.inputs['parentDatasource'] instanceof BehaviorSubject) {
10309
+ const dsParent = (dsElement.inputs['parentDatasource'] instanceof BehaviorSubject) ? dsElement.inputs['parentDatasource'].value : dsElement.inputs['parentDatasource'];
10310
+ if (dsParent?.uniqueName) {
10311
+ const parentElement = flattened.find(fe => fe.uniqueName == dsParent.uniqueName);
10312
+ if (parentElement) {
10313
+ dsParent.component.next(parentElement.inputs['componentRef'] instanceof BehaviorSubject ? parentElement.inputs['componentRef'].value : parentElement.inputs['componentRef']);
10314
+ }
10315
+ }
10316
+ }
10317
+ }
10318
+ if (!dsElements.find(de => de.uniqueName == v.uniqueName)) {
10319
+ dsSubs.push(v.component.fetchInfo$);
10320
+ dsElements.push(dsElement);
10321
+ if (dsElements.length == dsElementCount) {
10322
+ combineLatest(dsSubs).subscribe((infos) => {
10323
+ infos.forEach((info, i) => {
10324
+ if (info?.metaInfo && dsElements[i].inputs['metaInfo']) {
10325
+ Object.assign(info.metaInfo, dsElements[i].inputs['metaInfo']);
10326
+ dsElements[i].inputs['metaInfo'] = null;
10327
+ }
10328
+ });
10329
+ flattened.forEach((ld) => {
10330
+ if (ld.inputs['propertyTree']) {
10331
+ ld.inputs['propertyTree'] = new BehaviorSubject([]);
10332
+ this.propertyTreeBuilder(ld.inputs['action'].value, ld.inputs);
10333
+ }
10334
+ });
10335
+ // Re-capture snapshot after DS load (same as loadDashboard path)
10336
+ this.lastCommittedSnapshot = this.captureHistorySnapshot();
10337
+ });
10338
+ }
10339
+ }
10340
+ }
9770
10341
  }
9771
10342
  }
9772
10343
  });
@@ -9790,6 +10361,59 @@ Display formula context:
9790
10361
  ? (this.flattenedDashboardElements || []).find((x) => x?.uniqueName === selectedUniqueName) || null
9791
10362
  : null;
9792
10363
  this.cd.detectChanges();
10364
+ // After undo/redo, re-bind DATAREPEATER→DATASOURCE and force re-fetch.
10365
+ // This runs after Angular has created the live DataSourceComponent instances.
10366
+ if (this.applyingHistory) {
10367
+ setTimeout(() => {
10368
+ const liveFlat = this.flattenedDashboardElements || [];
10369
+ // Collect live DataSourceComponents by uniqueName
10370
+ const liveDataSources = {};
10371
+ liveFlat.forEach((el) => {
10372
+ if (el?.name === 'DATASOURCE') {
10373
+ const cr = el?.inputs?.['componentRef'];
10374
+ const crVal = (cr instanceof BehaviorSubject) ? cr.value : cr;
10375
+ const liveComp = crVal?.component instanceof BehaviorSubject
10376
+ ? crVal.component.value
10377
+ : crVal?.component;
10378
+ if (liveComp) {
10379
+ liveDataSources[el.uniqueName] = liveComp;
10380
+ if (liveComp.fetchData) {
10381
+ liveComp.fetchData();
10382
+ }
10383
+ }
10384
+ }
10385
+ });
10386
+ // Re-bind DATAREPEATERs: replicate the same binding that loadDashboard
10387
+ // and setValue do — get the live DataSourceComponent from the DS element's
10388
+ // componentRef and push it into the DATAREPEATER's datasource.component BS.
10389
+ liveFlat.forEach((el) => {
10390
+ if (el?.name === 'DATAREPEATER' || el?.name === 'SELECT' || el?.name === 'MULTISELECT' || el?.name === 'UL') {
10391
+ const dsRef = el?.inputs?.['datasource'];
10392
+ const dsUniqueName = dsRef?.uniqueName;
10393
+ if (dsUniqueName) {
10394
+ const dsElement = liveFlat.find((e) => e.uniqueName === dsUniqueName);
10395
+ if (dsElement) {
10396
+ // Get the live DataSourceComponent from componentRef — same path as setValue line 4078
10397
+ const crBs = dsElement.inputs?.['componentRef'];
10398
+ const crVal = (crBs instanceof BehaviorSubject) ? crBs.value : crBs;
10399
+ const liveComponent = crVal?.component instanceof BehaviorSubject
10400
+ ? crVal.component.value
10401
+ : crVal?.component;
10402
+ if (liveComponent) {
10403
+ if (!(dsRef.component instanceof BehaviorSubject)) {
10404
+ dsRef.component = new BehaviorSubject(liveComponent);
10405
+ }
10406
+ else {
10407
+ dsRef.component.next(liveComponent);
10408
+ }
10409
+ }
10410
+ }
10411
+ }
10412
+ }
10413
+ });
10414
+ this.cd.detectChanges();
10415
+ }, 300);
10416
+ }
9793
10417
  }
9794
10418
  /**
9795
10419
  * Rileva se il target evento e un controllo di input/editable per evitare shortcut globali indesiderate.
@@ -9999,6 +10623,11 @@ Display formula context:
9999
10623
  }
10000
10624
  });
10001
10625
  this.cd.detectChanges();
10626
+ // Same rationale as the constructor-scoped splitter resize callback:
10627
+ // dragEnd is the gesture-end signal, so commit immediately. Required
10628
+ // because deserialized elements (loaded from boardcontent) get this
10629
+ // dynamic callback rather than the constructor template default.
10630
+ this.commitHistoryIfChanged();
10002
10631
  };
10003
10632
  }
10004
10633
  /**
@@ -10169,7 +10798,7 @@ Display formula context:
10169
10798
  }
10170
10799
  const base = window.location.href.split('#')[0];
10171
10800
  const url = `${base}#/${encodeURIComponent(route)}/dashboard`;
10172
- window.open(url, '_blank', 'noopener');
10801
+ window.open(url, '_blank');
10173
10802
  }
10174
10803
  /**
10175
10804
  * Idrata ricorsivamente `customProps` convertendo i valori in `BehaviorSubject`
@@ -10186,12 +10815,12 @@ Display formula context:
10186
10815
  });
10187
10816
  // return customProps;
10188
10817
  }
10189
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DesignerComponent, deps: [{ token: i1$1.ActivatedRoute }, { token: DataProviderService }, { token: MetadataProviderService }, { token: UserInfoService }, { token: i0.ChangeDetectorRef }, { token: TranslationManagerService }, { token: MetadataEditorService }, { token: WorkflowRuntimeMetadataService }], target: i0.ɵɵFactoryTarget.Component });
10190
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", 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], 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\" (click)=\"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\">{{ '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 <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=\"col designer-toolbox\">\n @for (section of getToolPropertySections(tool); 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\n [ngModel]=\"getDesignerColorPickerHex(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorPickerHexChange($event, tool, toolProp)\" appendTo=\"body\" />\n <div class=\"designer-color-alpha-row\">\n <label class=\"designer-color-alpha-label\">{{ 'designer.alpha' | translate }}</label>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n <input\n type=\"number\"\n min=\"0\"\n max=\"1\"\n 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\" pDroppable (onDrop)=\"drop($event)\" #canvas\n (contextmenu)=\"showCtx($event, this)\">\n <wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\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]=\"'Riapri dashboard'\" [(visible)]=\"reopenDashboardDialogVisible\" [modal]=\"true\" [closable]=\"true\"\n [draggable]=\"false\" [resizable]=\"false\" [appendTo]=\"'body'\" [style]=\"{ width: '34rem' }\"\n (onHide)=\"cancelReopenDashboardDialog()\">\n <div class=\"route-popup-form\">\n <label for=\"designer-reopen-select\">Dashboard esistenti</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\">Riapri</button>\n </div>\n </div>\n</p-dialog>\n", 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}.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}:host ::ng-deep .designer-left-bottom-splitter .p-splitterpanel>.p-splitterpanel-content{height:100%;min-height:0;overflow:hidden}.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}: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}\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: i2$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i11.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i11.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: i2$2.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$3.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: i9.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: i17.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: i9$1.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: i3.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" }] });
10818
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DesignerComponent, deps: [{ token: i1$1.ActivatedRoute }, { token: DataProviderService }, { token: MetadataProviderService }, { token: UserInfoService }, { token: i0.ChangeDetectorRef }, { token: TranslationManagerService }, { token: MetadataEditorService }, { token: WorkflowRuntimeMetadataService }], target: i0.ɵɵFactoryTarget.Component });
10819
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", 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], 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\" (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 <label class=\"designer-color-alpha-label\">{{ 'designer.alpha' | translate }}</label>\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\" pDroppable\n (onDrop)=\"drop($event)\" #canvas (contextmenu)=\"showCtx($event, this)\">\n <wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\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}: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}\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: i11.Splitter, selector: "p-splitter", inputs: ["styleClass", "panelStyleClass", "panelStyle", "stateStorage", "stateKey", "layout", "gutterSize", "step", "minSizes", "panelSizes"], outputs: ["onResizeEnd", "onResizeStart"] }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i11$1.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i11$1.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: i13.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: i17.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: i9.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: i12.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" }] });
10191
10820
  }
10192
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DesignerComponent, decorators: [{
10821
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DesignerComponent, decorators: [{
10193
10822
  type: Component,
10194
- args: [{ selector: 'wuic-designer', imports: [NgClass, TranslateModule, NgTemplateOutlet, NgComponentOutlet, AsyncPipe, FormsModule, SplitterModule, DragDropModule, SelectModule, ColorPickerModule, AutoCompleteModule, DashboardComponent, CallbackPipe, FieldEditorComponent, JsonPipe, 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\" (click)=\"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\">{{ '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 <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=\"col designer-toolbox\">\n @for (section of getToolPropertySections(tool); 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\n [ngModel]=\"getDesignerColorPickerHex(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorPickerHexChange($event, tool, toolProp)\" appendTo=\"body\" />\n <div class=\"designer-color-alpha-row\">\n <label class=\"designer-color-alpha-label\">{{ 'designer.alpha' | translate }}</label>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n [ngModel]=\"getDesignerColorAlpha(tool, toolProp)\"\n (ngModelChange)=\"onDesignerColorAlphaChange($event, tool, toolProp)\" />\n <input\n type=\"number\"\n min=\"0\"\n max=\"1\"\n 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\" pDroppable (onDrop)=\"drop($event)\" #canvas\n (contextmenu)=\"showCtx($event, this)\">\n <wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\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]=\"'Riapri dashboard'\" [(visible)]=\"reopenDashboardDialogVisible\" [modal]=\"true\" [closable]=\"true\"\n [draggable]=\"false\" [resizable]=\"false\" [appendTo]=\"'body'\" [style]=\"{ width: '34rem' }\"\n (onHide)=\"cancelReopenDashboardDialog()\">\n <div class=\"route-popup-form\">\n <label for=\"designer-reopen-select\">Dashboard esistenti</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\">Riapri</button>\n </div>\n </div>\n</p-dialog>\n", 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}.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}:host ::ng-deep .designer-left-bottom-splitter .p-splitterpanel>.p-splitterpanel-content{height:100%;min-height:0;overflow:hidden}.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}: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}\n"] }]
10823
+ 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\" (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 <label class=\"designer-color-alpha-label\">{{ 'designer.alpha' | translate }}</label>\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\" pDroppable\n (onDrop)=\"drop($event)\" #canvas (contextmenu)=\"showCtx($event, this)\">\n <wuic-dashboard [dashboardElements]=\"dashboardElements\"></wuic-dashboard>\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}: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}\n"] }]
10195
10824
  }], ctorParameters: () => [{ type: i1$1.ActivatedRoute }, { type: DataProviderService }, { type: MetadataProviderService }, { type: UserInfoService }, { type: i0.ChangeDetectorRef }, { type: TranslationManagerService }, { type: MetadataEditorService }, { type: WorkflowRuntimeMetadataService }], propDecorators: { onWindowHashChange: [{
10196
10825
  type: HostListener,
10197
10826
  args: ['window:hashchange']
@@ -10216,4 +10845,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
10216
10845
  }] } });
10217
10846
 
10218
10847
  export { DesignerComponent };
10219
- //# sourceMappingURL=wuic-framework-lib-designer.component-B61jxcjI.mjs.map
10848
+ //# sourceMappingURL=wuic-framework-lib-designer.component-CJj2TAfG.mjs.map