@arsedizioni/ars-utils 22.1.5 → 22.5.2

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 (78) hide show
  1. package/README.md +158 -10
  2. package/clipper.ui/clipper.scss +564 -0
  3. package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs +1 -1
  4. package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs.map +1 -1
  5. package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs +11 -7
  6. package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs.map +1 -1
  7. package/fesm2022/arsedizioni-ars-utils-core.date.mjs +609 -0
  8. package/fesm2022/arsedizioni-ars-utils-core.date.mjs.map +1 -0
  9. package/fesm2022/arsedizioni-ars-utils-core.markdown.mjs +591 -0
  10. package/fesm2022/arsedizioni-ars-utils-core.markdown.mjs.map +1 -0
  11. package/fesm2022/arsedizioni-ars-utils-core.mjs +270 -1449
  12. package/fesm2022/arsedizioni-ars-utils-core.mjs.map +1 -1
  13. package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs +1 -1
  14. package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs.map +1 -1
  15. package/fesm2022/arsedizioni-ars-utils-support.common.mjs +1 -1
  16. package/fesm2022/arsedizioni-ars-utils-support.common.mjs.map +1 -1
  17. package/fesm2022/arsedizioni-ars-utils-ui.application.mjs +14 -4108
  18. package/fesm2022/arsedizioni-ars-utils-ui.application.mjs.map +1 -1
  19. package/fesm2022/arsedizioni-ars-utils-ui.controls.mjs +962 -0
  20. package/fesm2022/arsedizioni-ars-utils-ui.controls.mjs.map +1 -0
  21. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.auth.mjs +506 -0
  22. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.auth.mjs.map +1 -0
  23. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.mjs +450 -0
  24. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.mjs.map +1 -0
  25. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.prompt.mjs +184 -0
  26. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.prompt.mjs.map +1 -0
  27. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.select.mjs +825 -0
  28. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.select.mjs.map +1 -0
  29. package/fesm2022/arsedizioni-ars-utils-ui.files.mjs +708 -0
  30. package/fesm2022/arsedizioni-ars-utils-ui.files.mjs.map +1 -0
  31. package/fesm2022/arsedizioni-ars-utils-ui.filters.mjs +426 -0
  32. package/fesm2022/arsedizioni-ars-utils-ui.filters.mjs.map +1 -0
  33. package/fesm2022/arsedizioni-ars-utils-ui.help.mjs +531 -0
  34. package/fesm2022/arsedizioni-ars-utils-ui.help.mjs.map +1 -0
  35. package/fesm2022/arsedizioni-ars-utils-ui.mjs +54 -1227
  36. package/fesm2022/arsedizioni-ars-utils-ui.mjs.map +1 -1
  37. package/fesm2022/arsedizioni-ars-utils-ui.navigation.mjs +1049 -0
  38. package/fesm2022/arsedizioni-ars-utils-ui.navigation.mjs.map +1 -0
  39. package/fesm2022/arsedizioni-ars-utils-ui.notifications.mjs +263 -0
  40. package/fesm2022/arsedizioni-ars-utils-ui.notifications.mjs.map +1 -0
  41. package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs +4 -3
  42. package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs.map +1 -1
  43. package/fesm2022/arsedizioni-ars-utils-ui.paginator.mjs +53 -0
  44. package/fesm2022/arsedizioni-ars-utils-ui.paginator.mjs.map +1 -0
  45. package/fesm2022/arsedizioni-ars-utils-ui.shell.mjs +517 -0
  46. package/fesm2022/arsedizioni-ars-utils-ui.shell.mjs.map +1 -0
  47. package/fesm2022/arsedizioni-ars-utils-ui.tinymce.mjs +246 -0
  48. package/fesm2022/arsedizioni-ars-utils-ui.tinymce.mjs.map +1 -0
  49. package/fesm2022/arsedizioni-ars-utils.mjs +13 -12
  50. package/fesm2022/arsedizioni-ars-utils.mjs.map +1 -1
  51. package/help/package.json +4 -0
  52. package/package.json +80 -14
  53. package/styles/ui.colors.scss +23 -0
  54. package/support.ui/package.json +4 -0
  55. package/tinymce/package.json +4 -0
  56. package/types/arsedizioni-ars-utils-clipper.common.d.ts +1 -2
  57. package/types/arsedizioni-ars-utils-clipper.ui.d.ts +4 -1
  58. package/types/arsedizioni-ars-utils-core.d.ts +684 -1004
  59. package/types/arsedizioni-ars-utils-core.date.d.ts +304 -0
  60. package/types/arsedizioni-ars-utils-core.markdown.d.ts +159 -0
  61. package/types/arsedizioni-ars-utils-ui.application.d.ts +10 -2022
  62. package/types/arsedizioni-ars-utils-ui.controls.d.ts +413 -0
  63. package/types/arsedizioni-ars-utils-ui.d.ts +183 -566
  64. package/types/arsedizioni-ars-utils-ui.dialogs.auth.d.ts +224 -0
  65. package/types/arsedizioni-ars-utils-ui.dialogs.d.ts +228 -0
  66. package/types/arsedizioni-ars-utils-ui.dialogs.prompt.d.ts +47 -0
  67. package/types/arsedizioni-ars-utils-ui.dialogs.select.d.ts +309 -0
  68. package/types/arsedizioni-ars-utils-ui.files.d.ts +271 -0
  69. package/types/arsedizioni-ars-utils-ui.filters.d.ts +163 -0
  70. package/types/arsedizioni-ars-utils-ui.help.d.ts +220 -0
  71. package/types/arsedizioni-ars-utils-ui.navigation.d.ts +650 -0
  72. package/types/arsedizioni-ars-utils-ui.notifications.d.ts +73 -0
  73. package/types/arsedizioni-ars-utils-ui.paginator.d.ts +23 -0
  74. package/types/arsedizioni-ars-utils-ui.shell.d.ts +345 -0
  75. package/types/arsedizioni-ars-utils-ui.tinymce.d.ts +63 -0
  76. package/types/arsedizioni-ars-utils.d.ts +4 -10
  77. package/ui.tinymce/README.md +12 -0
  78. package/ui.tinymce/langs/it.js +466 -0
@@ -0,0 +1,962 @@
1
+ import * as i0 from '@angular/core';
2
+ import { output, inject, Renderer2, signal, input, effect, Input, Optional, Self, ChangeDetectionStrategy, Component, computed, DestroyRef, booleanAttribute, ChangeDetectorRef, afterNextRender, model, viewChild, ElementRef } from '@angular/core';
3
+ import { coerceBooleanProperty } from '@angular/cdk/coercion';
4
+ import * as i6 from '@angular/material/button';
5
+ import { MatButtonModule } from '@angular/material/button';
6
+ import * as i3 from '@angular/material/icon';
7
+ import { MatIconModule } from '@angular/material/icon';
8
+ import * as i5 from '@angular/material/menu';
9
+ import { MatMenuModule } from '@angular/material/menu';
10
+ import { SystemUtils, SafeHtmlPipe } from '@arsedizioni/ars-utils/core';
11
+ import * as i2 from '@arsedizioni/ars-utils/ui';
12
+ import { FlexLayoutModule } from '@arsedizioni/ars-utils/ui';
13
+ import { Subject, auditTime, animationFrameScheduler } from 'rxjs';
14
+ import * as i1 from '@angular/forms';
15
+ import { FormsModule } from '@angular/forms';
16
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
17
+ import * as i7 from '@angular/material/badge';
18
+ import { MatBadgeModule } from '@angular/material/badge';
19
+ import * as i5$1 from '@angular/material/chips';
20
+ import { MatChipsModule } from '@angular/material/chips';
21
+ import * as i2$1 from '@angular/material/form-field';
22
+ import { MatFormFieldModule } from '@angular/material/form-field';
23
+ import * as i3$1 from '@angular/material/select';
24
+ import { MatSelectModule } from '@angular/material/select';
25
+ import * as i8 from '@angular/material/tooltip';
26
+ import { MatTooltipModule } from '@angular/material/tooltip';
27
+ import * as i1$1 from '@angular/material/tree';
28
+ import { MatTree, MatTreeModule } from '@angular/material/tree';
29
+ import * as i2$2 from '@angular/material/checkbox';
30
+ import { MatCheckboxModule } from '@angular/material/checkbox';
31
+ import * as i4 from '@angular/material/tabs';
32
+ import { MatTabsModule } from '@angular/material/tabs';
33
+ import * as i9 from '@angular/material/input';
34
+ import { MatInputModule } from '@angular/material/input';
35
+ import { MatCalendar } from '@angular/material/datepicker';
36
+
37
+ class ButtonSelectorComponent {
38
+ set value(value) {
39
+ this.setValue(value, true);
40
+ }
41
+ /**
42
+ * Updates the internal state. Form propagation is skipped for model->view
43
+ * writes (writeValue) to avoid the CVA echo loop, and performed for
44
+ * user/programmatic changes via the `value` setter.
45
+ * @param value - The new value to store and display.
46
+ * @param propagate - When `true`, notifies the registered onChange callback.
47
+ */
48
+ setValue(value, propagate) {
49
+ this._value = value;
50
+ if (propagate) {
51
+ this.propagateChange(this._value);
52
+ }
53
+ this.stateChanges.next();
54
+ this.changed.emit(this._value);
55
+ this.current.set(this._value);
56
+ }
57
+ /** The current value as the selected item. */
58
+ get value() {
59
+ return this._value;
60
+ }
61
+ get disabled() {
62
+ if (this.ngControl && this.ngControl.disabled != null) {
63
+ return this.ngControl.disabled;
64
+ }
65
+ return this._disabled;
66
+ }
67
+ set disabled(value) {
68
+ this._disabled = coerceBooleanProperty(value);
69
+ if (this.focused) {
70
+ this.focused = false;
71
+ this.stateChanges.next();
72
+ }
73
+ }
74
+ constructor(ngControl) {
75
+ this.ngControl = ngControl;
76
+ /** Emitted whenever the selected value changes (including programmatic resets). */
77
+ this.changed = output();
78
+ /** Emitted when the user explicitly picks an item from the menu. */
79
+ this.selected = output();
80
+ this.stateChanges = new Subject();
81
+ this.focused = false;
82
+ this._value = undefined;
83
+ this._disabled = false;
84
+ this.propagateChange = () => { };
85
+ this.propagateTouched = () => { };
86
+ this.id = `button-selector--${SystemUtils.generateUUID()}`;
87
+ this.describedBy = '';
88
+ this.renderer = inject(Renderer2);
89
+ /** Currently selected item, kept in sync with the form control value. */
90
+ this.current = signal(undefined, /* @ts-ignore */
91
+ ...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
92
+ /** Width of the trigger button in pixels. Use `-1` for 100 %, `0` for `auto`. */
93
+ this.width = input(-1, /* @ts-ignore */
94
+ ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
95
+ /** Border thickness override. Use `-1` to inherit. */
96
+ this.border = input(-1, /* @ts-ignore */
97
+ ...(ngDevMode ? [{ debugName: "border" }] : /* istanbul ignore next */ []));
98
+ /** CSS border-radius of the trigger button. Defaults to a pill shape. */
99
+ this.borderRadius = input('9999px', /* @ts-ignore */
100
+ ...(ngDevMode ? [{ debugName: "borderRadius" }] : /* istanbul ignore next */ []));
101
+ /** Placeholder label shown when nothing is selected. */
102
+ this.label = input(undefined, /* @ts-ignore */
103
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
104
+ /** Label shown above the selected value (replaces `label` when an item is selected). */
105
+ this.labelSelected = input(undefined, /* @ts-ignore */
106
+ ...(ngDevMode ? [{ debugName: "labelSelected" }] : /* istanbul ignore next */ []));
107
+ /** List of selectable options. */
108
+ this.options = input([], /* @ts-ignore */
109
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
110
+ /** When `true`, the first available option is pre-selected on init. */
111
+ this.autoSelect = input(false, /* @ts-ignore */
112
+ ...(ngDevMode ? [{ debugName: "autoSelect" }] : /* istanbul ignore next */ []));
113
+ if (this.ngControl != null) {
114
+ this.ngControl.valueAccessor = this;
115
+ }
116
+ // Pre-select the first option whenever options change and autoSelect is enabled
117
+ effect(() => {
118
+ if (this.autoSelect()) {
119
+ const options = this.options();
120
+ // !== undefined: values like 0 or false are legitimate selections
121
+ if (options.length > 0 && options[0].value !== undefined) {
122
+ this.current.set(options[0]);
123
+ }
124
+ }
125
+ });
126
+ }
127
+ ngOnDestroy() {
128
+ this.stateChanges.complete();
129
+ }
130
+ /**
131
+ * Writes a new value to the component (called by the form layer).
132
+ * @param value - The new value to display.
133
+ */
134
+ writeValue(value) {
135
+ // Model -> view write: must NOT propagate back to the form (echo loop)
136
+ this.setValue(value, false);
137
+ }
138
+ /**
139
+ * Registers the on-change callback (called by the form layer).
140
+ * @param fn - Callback to invoke whenever the value changes.
141
+ */
142
+ registerOnChange(fn) {
143
+ this.propagateChange = fn;
144
+ }
145
+ /**
146
+ * Registers the on-touched callback (called by the form layer).
147
+ * @param fn - Callback to invoke when the control is touched.
148
+ */
149
+ registerOnTouched(fn) {
150
+ this.propagateTouched = fn;
151
+ }
152
+ /**
153
+ * Sets the ARIA described-by IDs for accessibility.
154
+ * @param ids - The list of element IDs to associate with this control.
155
+ */
156
+ setDescribedByIds(ids) {
157
+ this.describedBy = ids.join(' ');
158
+ }
159
+ /**
160
+ * Updates the disabled state when the Angular form layer changes it.
161
+ * @param isDisabled - Whether the control should be disabled.
162
+ */
163
+ setDisabledState(isDisabled) {
164
+ this._disabled = isDisabled;
165
+ if (isDisabled && this.focused) {
166
+ this.focused = false;
167
+ this.stateChanges.next();
168
+ }
169
+ if (!SystemUtils.isBrowser())
170
+ return;
171
+ const elem = document.getElementById(this.id);
172
+ if (elem) {
173
+ this.renderer.setProperty(elem, 'disabled', isDisabled);
174
+ }
175
+ }
176
+ /**
177
+ * Handles a click on the container element, focusing it and marking it as touched.
178
+ */
179
+ onContainerClick() {
180
+ if (!this.focused) {
181
+ if (!SystemUtils.isBrowser())
182
+ return;
183
+ const elem = document.getElementById(this.id);
184
+ if (elem) {
185
+ elem.focus();
186
+ this.propagateTouched();
187
+ }
188
+ }
189
+ }
190
+ /**
191
+ * Selects an option and optionally emits the `selected` output event.
192
+ * @param item - The item to select.
193
+ * @param notify - When `true` (default), emits the `selected` event.
194
+ */
195
+ select(item, notify = true) {
196
+ this.setValue(item, true);
197
+ if (notify) {
198
+ this.selected.emit(item);
199
+ }
200
+ }
201
+ /** Clears the current selection and resets the control to an empty state. */
202
+ reset() {
203
+ this.setValue(undefined, true);
204
+ }
205
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ButtonSelectorComponent, deps: [{ token: i1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
206
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ButtonSelectorComponent, isStandalone: true, selector: "button-selector", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, border: { classPropertyName: "border", publicName: "border", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, labelSelected: { classPropertyName: "labelSelected", publicName: "labelSelected", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed", selected: "selected" }, host: { properties: { "id": "id", "attr.aria-describedBy": "describedBy" } }, ngImport: i0, template: "<button mat-stroked-button class=\"menu-selector-button\" [style.border]=\"border() >= 0 ? border() : 'auto'\"\r\n [style.border-radius]=\"borderRadius()\" [style.height]=\"border() <= 0 ? '40px' : 'auto'\"\r\n [style.min-width]=\"width() > 0 ? width()+'px' : (width() === -1 ? '100%' : 'auto')\" [attr.aria-label]=\"label()\"\r\n [matMenuTriggerFor]=\"optionsMenu\">\r\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxFill>\r\n <div fxFlex=\"100\" fxFlexAlign=\"center\">\r\n @if(current()) {\r\n <div style=\"text-align: left;\"\r\n [style.min-width]=\"width() > 0 ? width()+'px' : (width() === -1 ? '100%' : 'auto')\">\r\n @if(labelSelected() || label()) {\r\n <div class=\"x-small \">{{labelSelected() ?? label()}}</div>\r\n <div fxHide.xs class=\"small truncated-1\">{{current()?.shortName ?? current()?.name ?? ''}}</div>\r\n <div fxHide.gt-xs class=\"x-small truncated-1\" style=\"max-width: 120px;\">\r\n <div>{{current()?.shortName ?? current()?.name ?? ''}}</div>\r\n </div>\r\n } @else {\r\n <div fxHide.xs class=\"small truncated\">{{current()?.shortName ?? current()?.name ?? ''}}</div>\r\n <div fxHide.gt-xs class=\"x-small truncated\" style=\"max-width: 120px;\">\r\n <div>{{current()?.shortName ?? current()?.name ?? ''}}</div>\r\n </div>\r\n }\r\n </div>\r\n } @else if(labelSelected() || label()) {\r\n <div class=\"truncated\" style=\"text-align: left;\"\r\n [style.min-width]=\"width() > 0 ? width()+'px' : (width() === -1 ? '100%' : 'auto')\">\r\n {{labelSelected() ?? label()}}</div>\r\n }\r\n </div>\r\n <div fxLayoutAlign=\"end\" fxFlexAlign=\"center\">\r\n <mat-icon>arrow_drop_down</mat-icon>\r\n </div>\r\n </div>\r\n</button>\r\n<mat-menu #optionsMenu=\"matMenu\">\r\n @for (o of options(); track $index) {\r\n <button mat-menu-item (click)=\"select(o)\" [disabled]=\"o.disabled\">\r\n {{o.name}}\r\n @if(o.bag) {\r\n ({{o.bag}})\r\n }\r\n </button>\r\n }\r\n</mat-menu>", styles: [".menu-selector-button{padding:0 10px 0 20px!important;border-radius:9999px!important}.menu-selector-button .in-search-bar{height:56px!important;padding:0 20px!important;border-top-left-radius:0!important;border-bottom-left-radius:0!important}::ng-deep .menu-selector-button>.mdc-button__label{width:100%!important}.truncated-1{min-width:0;max-width:100%}@supports (-webkit-line-clamp: 1){.truncated-1{overflow:hidden;text-overflow:ellipsis;white-space:initial;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical}}\n"], dependencies: [{ kind: "ngmodule", type: FlexLayoutModule }, { kind: "directive", type: i2.FxLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg] ", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i2.FxFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg] ", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2.FxShowHideDirective, selector: " [fxShow], [fxHide], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg] ", inputs: ["fxShow", "fxShow.xs", "fxShow.sm", "fxShow.md", "fxShow.lg", "fxShow.xl", "fxShow.lt-sm", "fxShow.lt-md", "fxShow.lt-lg", "fxShow.lt-xl", "fxShow.gt-xs", "fxShow.gt-sm", "fxShow.gt-md", "fxShow.gt-lg", "fxHide", "fxHide.xs", "fxHide.sm", "fxHide.md", "fxHide.lg", "fxHide.xl", "fxHide.lt-sm", "fxHide.lt-md", "fxHide.lt-lg", "fxHide.lt-xl", "fxHide.gt-xs", "fxHide.gt-sm", "fxHide.gt-md", "fxHide.gt-lg"] }, { kind: "directive", type: i2.FxLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg] ", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i2.FxLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg] ", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i2.FxFlexAlignDirective, selector: " [fxFlexAlign], [fxFlexAlign.xs], [fxFlexAlign.sm], [fxFlexAlign.md], [fxFlexAlign.lg], [fxFlexAlign.xl], [fxFlexAlign.lt-sm], [fxFlexAlign.lt-md], [fxFlexAlign.lt-lg], [fxFlexAlign.lt-xl], [fxFlexAlign.gt-xs], [fxFlexAlign.gt-sm], [fxFlexAlign.gt-md], [fxFlexAlign.gt-lg] ", inputs: ["fxFlexAlign", "fxFlexAlign.xs", "fxFlexAlign.sm", "fxFlexAlign.md", "fxFlexAlign.lg", "fxFlexAlign.xl", "fxFlexAlign.lt-sm", "fxFlexAlign.lt-md", "fxFlexAlign.lt-lg", "fxFlexAlign.lt-xl", "fxFlexAlign.gt-xs", "fxFlexAlign.gt-sm", "fxFlexAlign.gt-md", "fxFlexAlign.gt-lg"] }, { kind: "directive", type: i2.FxFlexFillDirective, selector: " [fxFlexFill], [fxFill], [fxFlexFill.xs], [fxFlexFill.sm], [fxFlexFill.md], [fxFlexFill.lg], [fxFlexFill.xl], [fxFlexFill.lt-sm], [fxFlexFill.lt-md], [fxFlexFill.lt-lg], [fxFlexFill.lt-xl], [fxFlexFill.gt-xs], [fxFlexFill.gt-sm], [fxFlexFill.gt-md], [fxFlexFill.gt-lg] ", inputs: ["fxFlexFill", "fxFill", "fxFlexFill.xs", "fxFlexFill.sm", "fxFlexFill.md", "fxFlexFill.lg", "fxFlexFill.xl", "fxFlexFill.lt-sm", "fxFlexFill.lt-md", "fxFlexFill.lt-lg", "fxFlexFill.lt-xl", "fxFlexFill.gt-xs", "fxFlexFill.gt-sm", "fxFlexFill.gt-md", "fxFlexFill.gt-lg"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
207
+ }
208
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ButtonSelectorComponent, decorators: [{
209
+ type: Component,
210
+ args: [{ selector: 'button-selector', standalone: true, imports: [FlexLayoutModule, MatIconModule, MatButtonModule,
211
+ MatMenuModule], changeDetection: ChangeDetectionStrategy.OnPush, host: {
212
+ '[id]': 'id',
213
+ '[attr.aria-describedBy]': 'describedBy',
214
+ }, template: "<button mat-stroked-button class=\"menu-selector-button\" [style.border]=\"border() >= 0 ? border() : 'auto'\"\r\n [style.border-radius]=\"borderRadius()\" [style.height]=\"border() <= 0 ? '40px' : 'auto'\"\r\n [style.min-width]=\"width() > 0 ? width()+'px' : (width() === -1 ? '100%' : 'auto')\" [attr.aria-label]=\"label()\"\r\n [matMenuTriggerFor]=\"optionsMenu\">\r\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxFill>\r\n <div fxFlex=\"100\" fxFlexAlign=\"center\">\r\n @if(current()) {\r\n <div style=\"text-align: left;\"\r\n [style.min-width]=\"width() > 0 ? width()+'px' : (width() === -1 ? '100%' : 'auto')\">\r\n @if(labelSelected() || label()) {\r\n <div class=\"x-small \">{{labelSelected() ?? label()}}</div>\r\n <div fxHide.xs class=\"small truncated-1\">{{current()?.shortName ?? current()?.name ?? ''}}</div>\r\n <div fxHide.gt-xs class=\"x-small truncated-1\" style=\"max-width: 120px;\">\r\n <div>{{current()?.shortName ?? current()?.name ?? ''}}</div>\r\n </div>\r\n } @else {\r\n <div fxHide.xs class=\"small truncated\">{{current()?.shortName ?? current()?.name ?? ''}}</div>\r\n <div fxHide.gt-xs class=\"x-small truncated\" style=\"max-width: 120px;\">\r\n <div>{{current()?.shortName ?? current()?.name ?? ''}}</div>\r\n </div>\r\n }\r\n </div>\r\n } @else if(labelSelected() || label()) {\r\n <div class=\"truncated\" style=\"text-align: left;\"\r\n [style.min-width]=\"width() > 0 ? width()+'px' : (width() === -1 ? '100%' : 'auto')\">\r\n {{labelSelected() ?? label()}}</div>\r\n }\r\n </div>\r\n <div fxLayoutAlign=\"end\" fxFlexAlign=\"center\">\r\n <mat-icon>arrow_drop_down</mat-icon>\r\n </div>\r\n </div>\r\n</button>\r\n<mat-menu #optionsMenu=\"matMenu\">\r\n @for (o of options(); track $index) {\r\n <button mat-menu-item (click)=\"select(o)\" [disabled]=\"o.disabled\">\r\n {{o.name}}\r\n @if(o.bag) {\r\n ({{o.bag}})\r\n }\r\n </button>\r\n }\r\n</mat-menu>", styles: [".menu-selector-button{padding:0 10px 0 20px!important;border-radius:9999px!important}.menu-selector-button .in-search-bar{height:56px!important;padding:0 20px!important;border-top-left-radius:0!important;border-bottom-left-radius:0!important}::ng-deep .menu-selector-button>.mdc-button__label{width:100%!important}.truncated-1{min-width:0;max-width:100%}@supports (-webkit-line-clamp: 1){.truncated-1{overflow:hidden;text-overflow:ellipsis;white-space:initial;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical}}\n"] }]
215
+ }], ctorParameters: () => [{ type: i1.NgControl, decorators: [{
216
+ type: Optional
217
+ }, {
218
+ type: Self
219
+ }] }], propDecorators: { changed: [{ type: i0.Output, args: ["changed"] }], selected: [{ type: i0.Output, args: ["selected"] }], disabled: [{
220
+ type: Input
221
+ }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], border: [{ type: i0.Input, args: [{ isSignal: true, alias: "border", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], labelSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelSelected", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], autoSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSelect", required: false }] }] } });
222
+
223
+ class ButtonToggleComponent {
224
+ constructor() {
225
+ /** Emitted each time the button is clicked. Carries the current `value` and the new `toggled` state. */
226
+ this.changed = output();
227
+ /** Current value bound from the parent. Drives label and icon selection. */
228
+ this.value = input(false, /* @ts-ignore */
229
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
230
+ /** Width of the button in pixels. Use `-1` for automatic sizing. */
231
+ this.width = input(-1, /* @ts-ignore */
232
+ ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
233
+ /** Border thickness override in pixels. Use `-1` to inherit. */
234
+ this.border = input(-1, /* @ts-ignore */
235
+ ...(ngDevMode ? [{ debugName: "border" }] : /* istanbul ignore next */ []));
236
+ /** Label shown when `value` is `true`. */
237
+ this.labelOn = input(undefined, /* @ts-ignore */
238
+ ...(ngDevMode ? [{ debugName: "labelOn" }] : /* istanbul ignore next */ []));
239
+ /** Label shown when `value` is `false`. */
240
+ this.labelOff = input(undefined, /* @ts-ignore */
241
+ ...(ngDevMode ? [{ debugName: "labelOff" }] : /* istanbul ignore next */ []));
242
+ /** Material icon name shown when `value` is `true`. */
243
+ this.iconOn = input(undefined, /* @ts-ignore */
244
+ ...(ngDevMode ? [{ debugName: "iconOn" }] : /* istanbul ignore next */ []));
245
+ /** Material icon name shown when `value` is `false`. */
246
+ this.iconOff = input(undefined, /* @ts-ignore */
247
+ ...(ngDevMode ? [{ debugName: "iconOff" }] : /* istanbul ignore next */ []));
248
+ /** CSS class applied to the button at all breakpoints. */
249
+ this.cssClass = input(undefined, /* @ts-ignore */
250
+ ...(ngDevMode ? [{ debugName: "cssClass" }] : /* istanbul ignore next */ []));
251
+ /** CSS class applied to the button on `xs` screens. */
252
+ this.cssClassSmall = input(undefined, /* @ts-ignore */
253
+ ...(ngDevMode ? [{ debugName: "cssClassSmall" }] : /* istanbul ignore next */ []));
254
+ /** Resolves the appropriate label for the current value state. */
255
+ this.label = computed(() => this.value() ? this.labelOn() ?? '' : this.labelOff() ?? '', /* @ts-ignore */
256
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
257
+ /** Resolves the appropriate icon name for the current value state. */
258
+ this.icon = computed(() => this.value() ? this.iconOn() ?? '' : this.iconOff() ?? '', /* @ts-ignore */
259
+ ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
260
+ }
261
+ /**
262
+ * Toggles the button state and emits the `changed` event.
263
+ * The emitted `toggled` value is the logical inverse of the current `value`.
264
+ */
265
+ toggle() {
266
+ const toggled = !this.value();
267
+ this.changed.emit({ value: this.value(), toggled });
268
+ }
269
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ButtonToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
270
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ButtonToggleComponent, isStandalone: true, selector: "button-toggle", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, border: { classPropertyName: "border", publicName: "border", isSignal: true, isRequired: false, transformFunction: null }, labelOn: { classPropertyName: "labelOn", publicName: "labelOn", isSignal: true, isRequired: false, transformFunction: null }, labelOff: { classPropertyName: "labelOff", publicName: "labelOff", isSignal: true, isRequired: false, transformFunction: null }, iconOn: { classPropertyName: "iconOn", publicName: "iconOn", isSignal: true, isRequired: false, transformFunction: null }, iconOff: { classPropertyName: "iconOff", publicName: "iconOff", isSignal: true, isRequired: false, transformFunction: null }, cssClass: { classPropertyName: "cssClass", publicName: "cssClass", isSignal: true, isRequired: false, transformFunction: null }, cssClassSmall: { classPropertyName: "cssClassSmall", publicName: "cssClassSmall", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, ngImport: i0, template: "<button mat-stroked-button [style.border]=\"border() >= 0 ? border() : 'auto'\"\n [style.height]=\"border() <= 0 ? '40px' : 'auto'\" [style.minWidth.px]=\"width() > 0 ? width() : 'auto'\"\n [style.mxn-width.px]=\"width() > 0 ? width() : 'auto'\" [class]=\"cssClass()\" [attr.aria-label]=\"label()\"\n (click)=\"toggle()\" [class.button-on]=\"value() === true\" [fxClass.xs]=\"cssClassSmall()\">\n <div fxLayout=\"row\" fxLayoutGap=\"8px\" fxLayoutAlign=\"center center\" fxFill>\n @if(icon()) {\n <div fxFlex=\"24px\"><mat-icon style=\"display: block;\">{{icon()}}</mat-icon></div>\n }\n <div [innerHtml]=\"label() | safeHtml\"></div>\n </div>\n</button>", styles: [".button-on{background-color:var(--mat-switch-selected-focus-handle-color)!important;border-color:var(--mat-switch-selected-focus-handle-color)!important;font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: FlexLayoutModule }, { kind: "directive", type: i2.FxLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg] ", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i2.FxFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg] ", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2.FxLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg] ", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i2.FxLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg] ", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i2.FxFlexFillDirective, selector: " [fxFlexFill], [fxFill], [fxFlexFill.xs], [fxFlexFill.sm], [fxFlexFill.md], [fxFlexFill.lg], [fxFlexFill.xl], [fxFlexFill.lt-sm], [fxFlexFill.lt-md], [fxFlexFill.lt-lg], [fxFlexFill.lt-xl], [fxFlexFill.gt-xs], [fxFlexFill.gt-sm], [fxFlexFill.gt-md], [fxFlexFill.gt-lg] ", inputs: ["fxFlexFill", "fxFill", "fxFlexFill.xs", "fxFlexFill.sm", "fxFlexFill.md", "fxFlexFill.lg", "fxFlexFill.xl", "fxFlexFill.lt-sm", "fxFlexFill.lt-md", "fxFlexFill.lt-lg", "fxFlexFill.lt-xl", "fxFlexFill.gt-xs", "fxFlexFill.gt-sm", "fxFlexFill.gt-md", "fxFlexFill.gt-lg"] }, { kind: "directive", type: i2.FxClassDirective, selector: " [fxClass], [fxClass.xs], [fxClass.sm], [fxClass.md], [fxClass.lg], [fxClass.xl], [fxClass.lt-sm], [fxClass.lt-md], [fxClass.lt-lg], [fxClass.lt-xl], [fxClass.gt-xs], [fxClass.gt-sm], [fxClass.gt-md], [fxClass.gt-lg] ", inputs: ["fxClass", "fxClass.xs", "fxClass.sm", "fxClass.md", "fxClass.lg", "fxClass.xl", "fxClass.lt-sm", "fxClass.lt-md", "fxClass.lt-lg", "fxClass.lt-xl", "fxClass.gt-xs", "fxClass.gt-sm", "fxClass.gt-md", "fxClass.gt-lg"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
271
+ }
272
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ButtonToggleComponent, decorators: [{
273
+ type: Component,
274
+ args: [{ selector: 'button-toggle', standalone: true, imports: [FlexLayoutModule, MatIconModule, MatButtonModule, SafeHtmlPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button mat-stroked-button [style.border]=\"border() >= 0 ? border() : 'auto'\"\n [style.height]=\"border() <= 0 ? '40px' : 'auto'\" [style.minWidth.px]=\"width() > 0 ? width() : 'auto'\"\n [style.mxn-width.px]=\"width() > 0 ? width() : 'auto'\" [class]=\"cssClass()\" [attr.aria-label]=\"label()\"\n (click)=\"toggle()\" [class.button-on]=\"value() === true\" [fxClass.xs]=\"cssClassSmall()\">\n <div fxLayout=\"row\" fxLayoutGap=\"8px\" fxLayoutAlign=\"center center\" fxFill>\n @if(icon()) {\n <div fxFlex=\"24px\"><mat-icon style=\"display: block;\">{{icon()}}</mat-icon></div>\n }\n <div [innerHtml]=\"label() | safeHtml\"></div>\n </div>\n</button>", styles: [".button-on{background-color:var(--mat-switch-selected-focus-handle-color)!important;border-color:var(--mat-switch-selected-focus-handle-color)!important;font-weight:700}\n"] }]
275
+ }], propDecorators: { changed: [{ type: i0.Output, args: ["changed"] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], border: [{ type: i0.Input, args: [{ isSignal: true, alias: "border", required: false }] }], labelOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelOn", required: false }] }], labelOff: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelOff", required: false }] }], iconOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOn", required: false }] }], iconOff: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOff", required: false }] }], cssClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClass", required: false }] }], cssClassSmall: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClassSmall", required: false }] }] } });
276
+
277
+ class ChipsSelectorComponent {
278
+ get disabled() {
279
+ if (this.ngControl && this.ngControl.disabled != null) {
280
+ return this.ngControl.disabled;
281
+ }
282
+ return this._disabled;
283
+ }
284
+ set disabled(value) {
285
+ this._disabled = coerceBooleanProperty(value);
286
+ if (this.focused) {
287
+ this.focused = false;
288
+ this.stateChanges.next();
289
+ }
290
+ }
291
+ /** True when the label should float above the field (focused or has a value). */
292
+ get shouldLabelFloat() {
293
+ return this.focused || !this.empty;
294
+ }
295
+ set value(value) {
296
+ this.setValue(value, true);
297
+ }
298
+ /**
299
+ * Updates the internal state and selection mirrors.
300
+ * @param value - The new selection array.
301
+ * @param propagate - When `true`, notifies the registered onChange callback.
302
+ */
303
+ setValue(value, propagate) {
304
+ this._value = value;
305
+ this.selection = [];
306
+ this.singleSelection = undefined;
307
+ if (this._value) {
308
+ this.options().forEach(n => {
309
+ if (this._value?.findIndex((x) => x.value === n.value) !== -1) {
310
+ this.selection.push(n);
311
+ }
312
+ });
313
+ if (this.selection.length > 0) {
314
+ this.singleSelection = this.selection[0];
315
+ }
316
+ }
317
+ this.cdr.markForCheck();
318
+ if (propagate) {
319
+ this.propagateChange(this._value);
320
+ }
321
+ this.stateChanges.next();
322
+ if (this.changesEnabled) {
323
+ this.changed.emit(this._value);
324
+ }
325
+ }
326
+ /** The current value as an array of selected items. */
327
+ get value() {
328
+ return this._value;
329
+ }
330
+ /** True when no item is selected. */
331
+ get empty() {
332
+ return !this._value || this._value.length === 0;
333
+ }
334
+ /** True when the control has validation errors and has been touched. */
335
+ get errorState() {
336
+ return this.ngControl?.errors != null && (this.ngControl?.touched ?? false);
337
+ }
338
+ constructor(ngControl) {
339
+ this.ngControl = ngControl;
340
+ /** Emitted when the selection changes. Carries the new array of selected items, or `undefined` when cleared. */
341
+ this.changed = output();
342
+ this.containerId = `chips-selector-container--${SystemUtils.generateUUID()}`;
343
+ this.containerWidth = signal(-6, /* @ts-ignore */
344
+ ...(ngDevMode ? [{ debugName: "containerWidth" }] : /* istanbul ignore next */ []));
345
+ this.focused = false;
346
+ this.stateChanges = new Subject();
347
+ this.destroyRef = inject(DestroyRef);
348
+ this.changesEnabled = false;
349
+ this.destroyed = false;
350
+ this.widthRetries = 0;
351
+ /** Debounce bridge for `ResizeObserver` notifications. */
352
+ this.resize$ = new Subject();
353
+ /** List of available options to display as chips. */
354
+ this.options = input([], /* @ts-ignore */
355
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
356
+ /** Minimum width in pixels when collapsed. Use `-1` for automatic. */
357
+ this.collapsedWidth = input(-1, /* @ts-ignore */
358
+ ...(ngDevMode ? [{ debugName: "collapsedWidth" }] : /* istanbul ignore next */ []));
359
+ /** Display mode used when the selector is in collapsed state. */
360
+ this.collapsedDisplayMode = input('dropdown', /* @ts-ignore */
361
+ ...(ngDevMode ? [{ debugName: "collapsedDisplayMode" }] : /* istanbul ignore next */ []));
362
+ /** Pixel threshold below which the selector collapses. Use `-1` to disable. */
363
+ this.collapseAt = input(-1, /* @ts-ignore */
364
+ ...(ngDevMode ? [{ debugName: "collapseAt" }] : /* istanbul ignore next */ []));
365
+ /** When `true`, `collapseAt` is compared against the container width rather than the window width. */
366
+ this.collapseAtContainer = input(false, /* @ts-ignore */
367
+ ...(ngDevMode ? [{ debugName: "collapseAtContainer" }] : /* istanbul ignore next */ []));
368
+ this.collapsed = computed(() => {
369
+ const cw = this.containerWidth();
370
+ const mw = this.collapseAt();
371
+ return this.mode() === 'collapsed' || (mw !== -1 && cw > 0 && mw > 0 && cw < mw);
372
+ }, /* @ts-ignore */
373
+ ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
374
+ /** Label shown in the dropdown / above the chip list. */
375
+ this.label = input('', /* @ts-ignore */
376
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
377
+ /** When `true`, multiple chips can be selected simultaneously. */
378
+ this.multiple = input(false, /* @ts-ignore */
379
+ ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
380
+ /** When `true`, at least one item must remain selected. */
381
+ this.mustSelect = input(false, /* @ts-ignore */
382
+ ...(ngDevMode ? [{ debugName: "mustSelect" }] : /* istanbul ignore next */ []));
383
+ /** Layout mode: `'collapsed'` forces dropdown mode, `'dynamic'` collapses based on `collapseAt`. */
384
+ this.mode = input('dynamic', /* @ts-ignore */
385
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
386
+ /** When `true`, chips are stacked vertically instead of wrapping horizontally. */
387
+ this.stacked = input(false, /* @ts-ignore */
388
+ ...(ngDevMode ? [{ debugName: "stacked" }] : /* istanbul ignore next */ []));
389
+ /** Chips below this index receive extra padding to align with other UI elements. */
390
+ this.padAt = input(0, /* @ts-ignore */
391
+ ...(ngDevMode ? [{ debugName: "padAt" }] : /* istanbul ignore next */ []));
392
+ /** When `true`, the control is required. */
393
+ this.required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
394
+ /** Placeholder text shown when no value is selected. */
395
+ this.placeholder = input('', /* @ts-ignore */
396
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
397
+ this._disabled = false;
398
+ this.id = `chips-selector--${SystemUtils.generateUUID()}`;
399
+ this.describedBy = '';
400
+ this._value = [];
401
+ this.propagateChange = () => { };
402
+ this.propagateTouched = () => { };
403
+ this.renderer = inject(Renderer2);
404
+ this.cdr = inject(ChangeDetectorRef);
405
+ /** Currently selected items (may contain multiple entries when `multiple` is `true`). */
406
+ this.selection = [];
407
+ if (this.ngControl != null) {
408
+ this.ngControl.valueAccessor = this;
409
+ }
410
+ // Notify state changes whenever required or placeholder inputs change
411
+ effect(() => {
412
+ this.required();
413
+ this.placeholder();
414
+ this.stateChanges.next();
415
+ });
416
+ // React to container size changes to keep the collapsed state up to date.
417
+ // `auditTime` on the animation-frame scheduler coalesces ResizeObserver bursts
418
+ // without adding perceptible latency, and defers the layout read out of the
419
+ // observer callback to avoid "ResizeObserver loop" warnings.
420
+ this.resize$
421
+ .pipe(takeUntilDestroyed(this.destroyRef), auditTime(0, animationFrameScheduler))
422
+ .subscribe(() => {
423
+ if (this.collapseAt() > 0) {
424
+ this.updateContainerWidth();
425
+ }
426
+ });
427
+ afterNextRender(() => {
428
+ if (SystemUtils.isBrowser() && typeof ResizeObserver !== 'undefined') {
429
+ const elem = document.getElementById(this.containerId);
430
+ if (elem) {
431
+ this.resizeObserver = new ResizeObserver(() => this.resize$.next());
432
+ this.resizeObserver.observe(elem);
433
+ }
434
+ }
435
+ setTimeout(() => {
436
+ this.updateContainerWidth();
437
+ this.changesEnabled = true;
438
+ }, 250);
439
+ });
440
+ }
441
+ ngOnDestroy() {
442
+ this.destroyed = true;
443
+ this.resizeObserver?.disconnect();
444
+ this.stateChanges.complete();
445
+ }
446
+ /**
447
+ * Measures the container (or window) width and updates the `containerWidth` signal,
448
+ * retrying after 100 ms if the element is not yet laid out.
449
+ */
450
+ updateContainerWidth() {
451
+ if (this.destroyed)
452
+ return;
453
+ const elem = document.getElementById(this.containerId);
454
+ if (elem && elem.clientWidth > 0) {
455
+ this.widthRetries = 0;
456
+ this.containerWidth.set(this.collapseAtContainer()
457
+ ? elem.clientWidth
458
+ : window.innerWidth);
459
+ }
460
+ else if (this.widthRetries < 50) {
461
+ // Bounded retry (max ~5 s): the old unbounded recursion kept running
462
+ // forever, even after the component was destroyed.
463
+ this.widthRetries++;
464
+ setTimeout(() => this.updateContainerWidth(), 100);
465
+ }
466
+ }
467
+ /**
468
+ * Resolves the effective selection array for the current display mode.
469
+ * In single-select collapsed button mode the `singleSelection` item is wrapped in an array.
470
+ * @returns The array of currently selected items.
471
+ */
472
+ getSelection() {
473
+ const value = !this.multiple() && this.collapsed() && this.collapsedDisplayMode() === 'button'
474
+ ? this.singleSelection
475
+ : this.selection;
476
+ if (Array.isArray(value)) {
477
+ return value;
478
+ }
479
+ return value ? [value] : [];
480
+ }
481
+ /**
482
+ * Schedules a value update after a short delay, giving the template time to sync `ngModel`.
483
+ */
484
+ updateValue() {
485
+ setTimeout(() => {
486
+ this.setValue(this.getSelection(), true);
487
+ }, 250);
488
+ }
489
+ /**
490
+ * Returns `true` when the given item can be selected in the current mode.
491
+ * In single-select mode an already-selected item is not re-selectable.
492
+ * @param item - The item to check.
493
+ * @returns True when the item is selectable.
494
+ */
495
+ isSelectable(item) {
496
+ return this.multiple() || this.getSelection().findIndex(x => x.value === item.value) === -1;
497
+ }
498
+ /**
499
+ * Writes a new value to the component (called by the form layer).
500
+ * @param value - The new selection to display.
501
+ */
502
+ writeValue(value) {
503
+ const next = value;
504
+ if (this.value !== next) {
505
+ // Model -> view write: must NOT propagate back to the form (echo loop)
506
+ this.setValue(next, false);
507
+ }
508
+ }
509
+ /**
510
+ * Registers the on-change callback (called by the form layer).
511
+ * @param fn - Callback to invoke whenever the value changes.
512
+ */
513
+ registerOnChange(fn) {
514
+ this.propagateChange = fn;
515
+ }
516
+ /**
517
+ * Registers the on-touched callback (called by the form layer).
518
+ * @param fn - Callback to invoke when the control is touched.
519
+ */
520
+ registerOnTouched(fn) {
521
+ this.propagateTouched = fn;
522
+ }
523
+ /**
524
+ * Sets the ARIA described-by IDs for accessibility.
525
+ * @param ids - The list of element IDs to associate with this control.
526
+ */
527
+ setDescribedByIds(ids) {
528
+ this.describedBy = ids.join(' ');
529
+ }
530
+ /**
531
+ * Updates the disabled state when the Angular form layer changes it.
532
+ * @param isDisabled - Whether the control should be disabled.
533
+ */
534
+ setDisabledState(isDisabled) {
535
+ this._disabled = isDisabled;
536
+ if (isDisabled && this.focused) {
537
+ this.focused = false;
538
+ this.stateChanges.next();
539
+ }
540
+ if (!SystemUtils.isBrowser())
541
+ return;
542
+ const elem = document.getElementById(this.id);
543
+ if (elem) {
544
+ this.renderer.setProperty(elem, 'disabled', isDisabled);
545
+ }
546
+ }
547
+ /**
548
+ * Handles a click on the container element, focusing it and marking it as touched.
549
+ */
550
+ onContainerClick() {
551
+ if (!this.focused) {
552
+ if (!SystemUtils.isBrowser())
553
+ return;
554
+ const elem = document.getElementById(this.id);
555
+ if (elem) {
556
+ elem.focus();
557
+ this.propagateTouched();
558
+ }
559
+ }
560
+ }
561
+ /**
562
+ * Clears the current selection and stops the event from bubbling.
563
+ * @param e - The originating click event.
564
+ */
565
+ clear(e) {
566
+ this.setValue([], true);
567
+ e.stopPropagation();
568
+ }
569
+ /**
570
+ * Selects a single item, replacing any existing selection.
571
+ * @param item - The item to select. Does nothing when `undefined`.
572
+ */
573
+ select(item) {
574
+ if (item) {
575
+ this.setValue([item], true);
576
+ }
577
+ }
578
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ChipsSelectorComponent, deps: [{ token: i1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
579
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ChipsSelectorComponent, isStandalone: true, selector: "chips-selector", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, collapsedWidth: { classPropertyName: "collapsedWidth", publicName: "collapsedWidth", isSignal: true, isRequired: false, transformFunction: null }, collapsedDisplayMode: { classPropertyName: "collapsedDisplayMode", publicName: "collapsedDisplayMode", isSignal: true, isRequired: false, transformFunction: null }, collapseAt: { classPropertyName: "collapseAt", publicName: "collapseAt", isSignal: true, isRequired: false, transformFunction: null }, collapseAtContainer: { classPropertyName: "collapseAtContainer", publicName: "collapseAtContainer", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, mustSelect: { classPropertyName: "mustSelect", publicName: "mustSelect", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, padAt: { classPropertyName: "padAt", publicName: "padAt", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, host: { properties: { "id": "id", "class.floating": "shouldLabelFloat", "attr.aria-describedBy": "describedBy" } }, ngImport: i0, template: "<div [id]=\"containerId\" class=\"chips-selector\">\r\n @if(containerWidth() > 0) {\r\n @if(collapsed()) {\r\n @if(collapsedDisplayMode() === 'dropdown') {\r\n <mat-form-field [style.min-width]=\"collapsedWidth() > 0 ? collapsedWidth()+'px' : '100%'\" subscriptSizing=\"dynamic\">\r\n @if(label()) {\r\n <mat-label>{{label()}}</mat-label>\r\n }\r\n <mat-select [(ngModel)]=\"selection\" [multiple]=\"multiple()\" (selectionChange)=\"updateValue()\">\r\n <mat-select-trigger>\r\n @if (value && (value.length || 0) > 0) {\r\n {{value[0].shortName ?? value[0].name}}\r\n }\r\n @if (value && (value.length || 0) > 1) {\r\n <span class=\"collapsed-additional-selection\">\r\n (+{{(value.length || 0) - 1}} {{value.length === 2 ? 'altro' : 'altri'}})\r\n </span>\r\n }\r\n </mat-select-trigger>\r\n @for (o of options(); track $index) {\r\n <mat-option [value]=\"o\" [disabled]=\"o.disabled\">\r\n {{o.name}}\r\n @if(o.bag) {\r\n &nbsp; ({{o.bag}})\r\n }\r\n </mat-option>\r\n }\r\n </mat-select>\r\n @if (value && (value.length || 0) > 0) {\r\n <button matSuffix tabindex=\"-1\" mat-icon-button aria-label=\"Pulisci\" (click)=\"clear($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <button-selector [label]=\"label()\" [options]=\"options()\" [width]=\"collapsedWidth()\" [(ngModel)]=\"singleSelection\"\r\n name=\"value\" (selected)=\"updateValue()\"></button-selector>\r\n\r\n }\r\n } @else {\r\n <mat-chip-listbox [class]=\"stacked() ? 'mat-mdc-chip-set-stacked' : ''\" [multiple]=\"multiple()\"\r\n [(ngModel)]=\"selection\" (change)=\"updateValue()\">\r\n @for (o of options(); track $index; let i = $index) {\r\n <mat-chip-option [matBadge]=\"o.bag\" [matTooltip]=\"o.disabled === true ? 'Non disponibile' : (o.bagInfo ?? '')\" [selectable]=\"isSelectable(o)\" [value]=\"o\"\r\n [disabled]=\"o.disabled\" [class.chip-padded]=\"i < padAt()\">{{o.shortName ??\r\n o.name}}</mat-chip-option>\r\n }\r\n </mat-chip-listbox>\r\n }\r\n }\r\n</div>", styles: [".chips-selector{width:100%}.chips-selector .collapsed-additional-selection{opacity:.75;font-size:.75em}.chip-padded{margin-right:10px!important}.mdc-evolution-chip--disabled{pointer-events:auto!important}\n"], dependencies: [{ kind: "ngmodule", type: FlexLayoutModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i3$1.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i5$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i5$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i7.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: ButtonSelectorComponent, selector: "button-selector", inputs: ["disabled", "width", "border", "borderRadius", "label", "labelSelected", "options", "autoSelect"], outputs: ["changed", "selected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
580
+ }
581
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ChipsSelectorComponent, decorators: [{
582
+ type: Component,
583
+ args: [{ selector: 'chips-selector', standalone: true, imports: [FlexLayoutModule, FormsModule, MatFormFieldModule, MatSelectModule,
584
+ MatChipsModule, MatIconModule, MatButtonModule, MatBadgeModule, MatTooltipModule,
585
+ ButtonSelectorComponent
586
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
587
+ '[id]': 'id',
588
+ '[class.floating]': 'shouldLabelFloat',
589
+ '[attr.aria-describedBy]': 'describedBy',
590
+ }, template: "<div [id]=\"containerId\" class=\"chips-selector\">\r\n @if(containerWidth() > 0) {\r\n @if(collapsed()) {\r\n @if(collapsedDisplayMode() === 'dropdown') {\r\n <mat-form-field [style.min-width]=\"collapsedWidth() > 0 ? collapsedWidth()+'px' : '100%'\" subscriptSizing=\"dynamic\">\r\n @if(label()) {\r\n <mat-label>{{label()}}</mat-label>\r\n }\r\n <mat-select [(ngModel)]=\"selection\" [multiple]=\"multiple()\" (selectionChange)=\"updateValue()\">\r\n <mat-select-trigger>\r\n @if (value && (value.length || 0) > 0) {\r\n {{value[0].shortName ?? value[0].name}}\r\n }\r\n @if (value && (value.length || 0) > 1) {\r\n <span class=\"collapsed-additional-selection\">\r\n (+{{(value.length || 0) - 1}} {{value.length === 2 ? 'altro' : 'altri'}})\r\n </span>\r\n }\r\n </mat-select-trigger>\r\n @for (o of options(); track $index) {\r\n <mat-option [value]=\"o\" [disabled]=\"o.disabled\">\r\n {{o.name}}\r\n @if(o.bag) {\r\n &nbsp; ({{o.bag}})\r\n }\r\n </mat-option>\r\n }\r\n </mat-select>\r\n @if (value && (value.length || 0) > 0) {\r\n <button matSuffix tabindex=\"-1\" mat-icon-button aria-label=\"Pulisci\" (click)=\"clear($event)\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <button-selector [label]=\"label()\" [options]=\"options()\" [width]=\"collapsedWidth()\" [(ngModel)]=\"singleSelection\"\r\n name=\"value\" (selected)=\"updateValue()\"></button-selector>\r\n\r\n }\r\n } @else {\r\n <mat-chip-listbox [class]=\"stacked() ? 'mat-mdc-chip-set-stacked' : ''\" [multiple]=\"multiple()\"\r\n [(ngModel)]=\"selection\" (change)=\"updateValue()\">\r\n @for (o of options(); track $index; let i = $index) {\r\n <mat-chip-option [matBadge]=\"o.bag\" [matTooltip]=\"o.disabled === true ? 'Non disponibile' : (o.bagInfo ?? '')\" [selectable]=\"isSelectable(o)\" [value]=\"o\"\r\n [disabled]=\"o.disabled\" [class.chip-padded]=\"i < padAt()\">{{o.shortName ??\r\n o.name}}</mat-chip-option>\r\n }\r\n </mat-chip-listbox>\r\n }\r\n }\r\n</div>", styles: [".chips-selector{width:100%}.chips-selector .collapsed-additional-selection{opacity:.75;font-size:.75em}.chip-padded{margin-right:10px!important}.mdc-evolution-chip--disabled{pointer-events:auto!important}\n"] }]
591
+ }], ctorParameters: () => [{ type: i1.NgControl, decorators: [{
592
+ type: Optional
593
+ }, {
594
+ type: Self
595
+ }] }], propDecorators: { changed: [{ type: i0.Output, args: ["changed"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], collapsedWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedWidth", required: false }] }], collapsedDisplayMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedDisplayMode", required: false }] }], collapseAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseAt", required: false }] }], collapseAtContainer: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseAtContainer", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], mustSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "mustSelect", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], stacked: [{ type: i0.Input, args: [{ isSignal: true, alias: "stacked", required: false }] }], padAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "padAt", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{
596
+ type: Input
597
+ }] } });
598
+
599
+ class TreePickerComponent {
600
+ /** Returns true when the node can be selected: depth < maxDepth or explicitly listed in maxDepthOverrides. */
601
+ isSelectable(node) {
602
+ return this._isSelectableNode(node);
603
+ }
604
+ _isSelectableNode(node) {
605
+ const depth = this._maps().depthMap.get(node.id) ?? 0;
606
+ return depth < this.maxDepth() || this._overrideSubtreeSet().has(node.id);
607
+ }
608
+ constructor() {
609
+ /** Nested tree data to display. */
610
+ this.tree = input([], /* @ts-ignore */
611
+ ...(ngDevMode ? [{ debugName: "tree" }] : /* istanbul ignore next */ []));
612
+ /** Currently selected node ids. Supports two-way binding via [(selection)]. */
613
+ this.selection = model([], /* @ts-ignore */
614
+ ...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
615
+ /** When true, checkboxes and chip remove buttons are disabled (mirrors Material convention). */
616
+ this.disabled = input(false, /* @ts-ignore */
617
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
618
+ /** Description to display when no selection is made. */
619
+ this.descriptionEmpty = input('<span>Nessuna selezione: vengono inclusi <strong>tutti gli elementi</strong>.</span>', /* @ts-ignore */
620
+ ...(ngDevMode ? [{ debugName: "descriptionEmpty" }] : /* istanbul ignore next */ []));
621
+ /** Maximum number of tree levels to display (default: 3). */
622
+ this.maxDepth = input(3, /* @ts-ignore */
623
+ ...(ngDevMode ? [{ debugName: "maxDepth" }] : /* istanbul ignore next */ []));
624
+ /**
625
+ * List of node IDs at depth >= maxDepth that unlock selection for themselves
626
+ * and all their descendants, regardless of depth.
627
+ */
628
+ this.maxDepthOverrides = input([], /* @ts-ignore */
629
+ ...(ngDevMode ? [{ debugName: "maxDepthOverrides" }] : /* istanbul ignore next */ []));
630
+ /**
631
+ * Number of levels to auto-expand on load.
632
+ * 0 or undefined = only top level visible (no expansion);
633
+ * 1 = expand depth-0 nodes; 2 = expand depth-0 and depth-1 nodes; etc.
634
+ * Must be less than maxDepth.
635
+ */
636
+ this.minDepth = input(undefined, /* @ts-ignore */
637
+ ...(ngDevMode ? [{ debugName: "minDepth" }] : /* istanbul ignore next */ []));
638
+ /**
639
+ * Emits the count of visible selected nodes whenever the selection changes.
640
+ * Emits 0 when nothing is selected (meaning all items are implicitly included).
641
+ */
642
+ this.selectionCount = output();
643
+ /** Emits void whenever the user changes the selection (toggle, remove, clear). */
644
+ this.changed = output();
645
+ this._treeRef = viewChild((MatTree), /* @ts-ignore */
646
+ ...(ngDevMode ? [{ debugName: "_treeRef" }] : /* istanbul ignore next */ []));
647
+ this._elRef = inject(ElementRef);
648
+ /**
649
+ * Set of all node IDs selectable via overrides: each listed root and all its descendants.
650
+ * Recomputed whenever the tree data or the override list changes.
651
+ */
652
+ this._overrideSubtreeSet = computed(() => {
653
+ const overrideIds = new Set(this.maxDepthOverrides());
654
+ const maps = this._maps();
655
+ const result = new Set();
656
+ for (const id of overrideIds) {
657
+ const root = maps.nodeMap.get(id);
658
+ if (!root)
659
+ continue;
660
+ const addSubtree = (n) => {
661
+ result.add(n.id);
662
+ for (const child of (n.children ?? []))
663
+ addSubtree(child);
664
+ };
665
+ addSubtree(root);
666
+ }
667
+ return result;
668
+ }, /* @ts-ignore */
669
+ ...(ngDevMode ? [{ debugName: "_overrideSubtreeSet" }] : /* istanbul ignore next */ []));
670
+ /** All three maps rebuilt lazily as a single computed whenever taxonomy changes. */
671
+ this._maps = computed(() => {
672
+ const parentMap = new Map();
673
+ const depthMap = new Map();
674
+ const nodeMap = new Map();
675
+ const build = (nodes, parent, depth = 0) => {
676
+ for (const node of nodes) {
677
+ depthMap.set(node.id, depth);
678
+ nodeMap.set(node.id, node);
679
+ if (parent)
680
+ parentMap.set(node.id, parent);
681
+ if (node.children?.length)
682
+ build(node.children, node, depth + 1);
683
+ }
684
+ };
685
+ build(this.tree());
686
+ return { parentMap, depthMap, nodeMap };
687
+ }, /* @ts-ignore */
688
+ ...(ngDevMode ? [{ debugName: "_maps" }] : /* istanbul ignore next */ []));
689
+ /** O(1) set of selected ids, rebuilt only when selection changes. */
690
+ this._selectedSet = computed(() => new Set(this.selection()), /* @ts-ignore */
691
+ ...(ngDevMode ? [{ debugName: "_selectedSet" }] : /* istanbul ignore next */ []));
692
+ /** True when at least one node is explicitly selected. */
693
+ this.hasSelection = computed(() => this.selection().length > 0, /* @ts-ignore */
694
+ ...(ngDevMode ? [{ debugName: "hasSelection" }] : /* istanbul ignore next */ []));
695
+ /** Count of selected nodes within selectable levels (depth < maxDepth or in overrides), shown in the tab label. */
696
+ this.selectedVisibleCount = computed(() => this.selection().filter(id => {
697
+ const node = this._maps().nodeMap.get(id);
698
+ return node ? this._isSelectableNode(node) : false;
699
+ }).length, /* @ts-ignore */
700
+ ...(ngDevMode ? [{ debugName: "selectedVisibleCount" }] : /* istanbul ignore next */ []));
701
+ this.treeChildrenAccessor = (node) => {
702
+ return (node.children ?? []);
703
+ };
704
+ this.hasChild = (_, node) => !!(node.children?.length);
705
+ /** Current filter text. */
706
+ this.filterText = signal('', /* @ts-ignore */
707
+ ...(ngDevMode ? [{ debugName: "filterText" }] : /* istanbul ignore next */ []));
708
+ /** Nodes matching the current filter text, in nodeMap iteration order. */
709
+ this.filteredItems = signal([], /* @ts-ignore */
710
+ ...(ngDevMode ? [{ debugName: "filteredItems" }] : /* istanbul ignore next */ []));
711
+ /** Index of the currently highlighted filtered node (-1 = none). */
712
+ this.filterIndex = signal(-1, /* @ts-ignore */
713
+ ...(ngDevMode ? [{ debugName: "filterIndex" }] : /* istanbul ignore next */ []));
714
+ /** The currently highlighted filtered node, or null. */
715
+ this.filteredNode = computed(() => {
716
+ const idx = this.filterIndex();
717
+ return idx >= 0 ? (this.filteredItems()[idx] ?? null) : null;
718
+ }, /* @ts-ignore */
719
+ ...(ngDevMode ? [{ debugName: "filteredNode" }] : /* istanbul ignore next */ []));
720
+ // Expand nodes up to minDepth whenever new taxonomy data arrives
721
+ effect(() => {
722
+ const maps = this._maps();
723
+ const expandLevels = this.minDepth() ?? 0;
724
+ setTimeout(() => {
725
+ const tree = this._treeRef();
726
+ if (!tree)
727
+ return;
728
+ tree.collapseAll();
729
+ if (expandLevels <= 0)
730
+ return;
731
+ maps.depthMap.forEach((depth, id) => {
732
+ if (depth < expandLevels) {
733
+ const node = maps.nodeMap.get(id);
734
+ if (node)
735
+ tree.expand(node);
736
+ }
737
+ });
738
+ });
739
+ });
740
+ // Emit visible selection count on every selection change
741
+ effect(() => {
742
+ this.selectionCount.emit(this.selectedVisibleCount());
743
+ });
744
+ }
745
+ /** Expands all visible nodes in the tree. */
746
+ expandAll() {
747
+ this._treeRef()?.expandAll();
748
+ }
749
+ /** Collapses all nodes in the tree. */
750
+ collapseAll() {
751
+ this._treeRef()?.collapseAll();
752
+ }
753
+ /** Clears the entire selection. */
754
+ clearAll() {
755
+ this.selection.set([]);
756
+ this.changed.emit();
757
+ }
758
+ /** Searches nodes by text and moves to the first match. */
759
+ doFilter() {
760
+ const text = this.filterText().trim().toLowerCase();
761
+ if (text.length < 3) {
762
+ this.filteredItems.set([]);
763
+ this.filterIndex.set(-1);
764
+ return;
765
+ }
766
+ const matches = Array.from(this._maps().nodeMap.values())
767
+ .filter(n => n.name?.toLowerCase().includes(text));
768
+ this.filteredItems.set(matches);
769
+ const idx = matches.length > 0 ? 0 : -1;
770
+ this.filterIndex.set(idx);
771
+ if (idx >= 0)
772
+ this._scrollToFiltered(idx, matches);
773
+ }
774
+ /** Clears the filter and restores the original tree state. */
775
+ clearFilter() {
776
+ this.filterText.set('');
777
+ this.filteredItems.set([]);
778
+ this.filterIndex.set(-1);
779
+ }
780
+ /** Moves to the next matching node, cycling back to the first. */
781
+ nextFiltered() {
782
+ const items = this.filteredItems();
783
+ if (!items.length)
784
+ return;
785
+ const next = (this.filterIndex() + 1) % items.length;
786
+ this.filterIndex.set(next);
787
+ this._scrollToFiltered(next, items);
788
+ }
789
+ /** Returns true when the node is the currently highlighted filter match. */
790
+ isFilteredNode(node) {
791
+ return this.filteredNode()?.id === node.id;
792
+ }
793
+ /** Expands ancestors of the target node and scrolls it into view. */
794
+ _scrollToFiltered(index, items) {
795
+ const node = items[index];
796
+ if (!node)
797
+ return;
798
+ const tree = this._treeRef();
799
+ if (tree) {
800
+ let parent = this._maps().parentMap.get(node.id);
801
+ while (parent) {
802
+ tree.expand(parent);
803
+ parent = this._maps().parentMap.get(parent.id);
804
+ }
805
+ }
806
+ setTimeout(() => {
807
+ const el = this._elRef.nativeElement.querySelector(`[data-node-id="${node.id}"]`);
808
+ el?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
809
+ });
810
+ }
811
+ /**
812
+ * Returns true when the node is in the active selection.
813
+ * @param node - tree node to check
814
+ * @returns true if selected
815
+ */
816
+ isSelected(node) {
817
+ return this._selectedSet().has(node.id);
818
+ }
819
+ /**
820
+ * Returns true when a subset (but not all) of the node's descendants are selected,
821
+ * producing the indeterminate checkbox state.
822
+ * @param node - tree node to evaluate
823
+ * @returns true if the node is in a partial-selection (indeterminate) state
824
+ */
825
+ isIndeterminate(node) {
826
+ if (!node.children?.length)
827
+ return false;
828
+ const descendants = this._getSelectableDescendants(node);
829
+ const set = this._selectedSet();
830
+ const count = descendants.filter(d => set.has(d.id)).length;
831
+ return count > 0 && count < descendants.length;
832
+ }
833
+ /**
834
+ * Toggles the node and all its descendants; then syncs the ancestor chain.
835
+ * @param node - the node that was clicked
836
+ */
837
+ toggleNode(node) {
838
+ this.selection.update(current => {
839
+ const set = new Set(current);
840
+ if (set.has(node.id)) {
841
+ set.delete(node.id);
842
+ }
843
+ else {
844
+ set.add(node.id);
845
+ }
846
+ this._syncParentsInSet(node, set);
847
+ return Array.from(set);
848
+ });
849
+ this.changed.emit();
850
+ }
851
+ /**
852
+ * Deselects the node and all its descendants. Called by the chip remove button.
853
+ * @param node - the node to remove from the selection
854
+ */
855
+ removeNode(node) {
856
+ this.selection.update(current => {
857
+ const set = new Set(current);
858
+ set.delete(node.id);
859
+ this._syncParentsInSet(node, set);
860
+ return Array.from(set);
861
+ });
862
+ this.changed.emit();
863
+ }
864
+ /**
865
+ * Returns the INode for the given id, or undefined if not found.
866
+ * @param id - node id to look up
867
+ * @returns the matching INode
868
+ */
869
+ nodeById(id) {
870
+ return this._maps().nodeMap.get(id);
871
+ }
872
+ /**
873
+ * Returns true when the node at the given id is within the visible depth range
874
+ * and should appear in the chip list.
875
+ * @param id - node id to check
876
+ * @returns true if the node depth is less than maxDepth
877
+ */
878
+ isChipVisible(id) {
879
+ const node = this._maps().nodeMap.get(id);
880
+ return node ? this._isSelectableNode(node) : false;
881
+ }
882
+ /**
883
+ * Returns only the selectable descendants of node (depth < maxDepth or in overrides),
884
+ * used for indeterminate state and parent auto-selection logic.
885
+ * @param node - root of the subtree to traverse
886
+ * @returns flat array of selectable descendant INodes
887
+ */
888
+ _getSelectableDescendants(node) {
889
+ const result = [];
890
+ for (const child of (node.children ?? [])) {
891
+ const c = child;
892
+ if (this._isSelectableNode(c))
893
+ result.push(c);
894
+ result.push(...this._getSelectableDescendants(c));
895
+ }
896
+ return result;
897
+ }
898
+ /**
899
+ * Walks up the ancestor chain from node, selecting a parent only when all
900
+ * its descendants are in the set, deselecting it otherwise.
901
+ * @param node - starting node for the upward traversal
902
+ * @param set - mutable selection set updated in place
903
+ */
904
+ _syncParentsInSet(node, set) {
905
+ let parent = this._maps().parentMap.get(node.id);
906
+ while (parent) {
907
+ const descendants = this._getSelectableDescendants(parent);
908
+ if (descendants.length > 0 && descendants.every(d => set.has(d.id))) {
909
+ set.add(parent.id);
910
+ }
911
+ else {
912
+ set.delete(parent.id);
913
+ }
914
+ parent = this._maps().parentMap.get(parent.id);
915
+ }
916
+ }
917
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TreePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
918
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: TreePickerComponent, isStandalone: true, selector: "tree-picker", inputs: { tree: { classPropertyName: "tree", publicName: "tree", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, descriptionEmpty: { classPropertyName: "descriptionEmpty", publicName: "descriptionEmpty", isSignal: true, isRequired: false, transformFunction: null }, maxDepth: { classPropertyName: "maxDepth", publicName: "maxDepth", isSignal: true, isRequired: false, transformFunction: null }, maxDepthOverrides: { classPropertyName: "maxDepthOverrides", publicName: "maxDepthOverrides", isSignal: true, isRequired: false, transformFunction: null }, minDepth: { classPropertyName: "minDepth", publicName: "minDepth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection: "selectionChange", selectionCount: "selectionCount", changed: "changed" }, viewQueries: [{ propertyName: "_treeRef", first: true, predicate: (MatTree), descendants: true, isSignal: true }], ngImport: i0, template: "<mat-tab-group class=\"taxonomy-picker-tabs\" style=\"height:100%\">\r\n <mat-tab style=\"overflow-x: hidden !important; height: 100%\">\r\n <ng-template mat-tab-label>\r\n Seleziona\r\n <mat-icon\r\n style=\"font-size:16px;height:16px;width:16px;margin-left:4px;vertical-align:middle;color:var(--mat-sys-primary)\"\r\n [matTooltip]=\"'Nessuna selezione = tutti gli argomenti inclusi;\\r\\nOgni elemento selezionato include sempre tutti i suoi sottoelementi'\"\r\n matTooltipPosition=\"above\">\r\n info\r\n </mat-icon>\r\n </ng-template>\r\n <div fxLayout=\"column\" fxFill style=\"overflow: hidden; height: 100%;\">\r\n <div fxFlex>\r\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxLayoutAlign=\"start center\" fxFill>\r\n <div fxFlex fxHide.xs>\r\n <mat-form-field style=\"width:200px; padding: 8px 0px\" appearance=\"outline\"\r\n subscriptSizing=\"dynamic\">\r\n <mat-label>Cerca...</mat-label>\r\n <input type=\"text\" (keyup)=\"doFilter()\" matInput [ngModel]=\"filterText()\"\r\n (ngModelChange)=\"filterText.set($event)\"\r\n (keydown.enter)=\"$event.preventDefault(); $event.stopPropagation(); nextFiltered()\"\r\n (keydown.arrowDown)=\"$event.preventDefault(); $event.stopPropagation(); nextFiltered()\">\r\n @if (filterText()) {\r\n <button type=\"button\" type=\"button\" tabindex=\"-1\" matSuffix mat-icon-button\r\n aria-label=\"Clear\" (click)=\"clearFilter()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </mat-form-field>\r\n </div>\r\n @if (filteredItems().length > 0) {\r\n <div fxFlex=\"50px\" fxHide.xs fxLayoutAlign=\"end center\">\r\n <div class=\"small\">{{filterIndex() + 1}} / {{filteredItems().length}}</div>\r\n </div>\r\n <div fxFlex=\"48px\" fxHide.xs fxLayoutAlign=\"end center\">\r\n <button mat-icon-button (click)=\"nextFiltered()\">\r\n <mat-icon aria-label=\"Vai al prossimo\"\r\n matTooltip=\"Vai al prossimo\">arrow_downward</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n <div fxFlex=\"*\" fxLayoutAlign=\"end center\">\r\n <button mat-icon-button [matTooltip]=\"'Espandi tutto'\" (click)=\"expandAll()\">\r\n <mat-icon>unfold_more</mat-icon>\r\n </button>\r\n <button mat-icon-button [matTooltip]=\"'Comprimi tutto'\" (click)=\"collapseAll()\">\r\n <mat-icon>unfold_less</mat-icon>\r\n </button>\r\n <button mat-icon-button [matTooltip]=\"'Azzera selezione'\" [disabled]=\"!hasSelection()\"\r\n (click)=\"clearAll()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div fxFlex=\"*\" style=\"overflow-y: auto;\">\r\n <mat-tree [dataSource]=\"tree()\" [childrenAccessor]=\"treeChildrenAccessor\" class=\"tree\">\r\n <!-- Leaf node -->\r\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodePadding [matTreeNodePaddingIndent]=\"20\"\r\n class=\"tree-node\" [class.tree-node-filtered]=\"filteredNode()?.id === node.id\"\r\n [class.tree-node-no-select]=\"!isSelectable(node)\"\r\n [attr.data-node-id]=\"node.id\">\r\n <button mat-icon-button disabled style=\"visibility: hidden\"></button>\r\n @if (isSelectable(node)) {\r\n <mat-checkbox [checked]=\"isSelected(node)\" [disabled]=\"disabled()\" (change)=\"toggleNode(node)\">\r\n <span class=\"small\">{{node.name}}</span>\r\n </mat-checkbox>\r\n } @else {\r\n <div class=\"tree-node-label-only\">\r\n <span class=\"small\">{{node.name}}</span>\r\n </div>\r\n }\r\n </mat-tree-node>\r\n <!-- Expandable node with children -->\r\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding\r\n [matTreeNodePaddingIndent]=\"20\" #treeNode=\"matTreeNode\" class=\"tree-node\"\r\n [class.tree-node-filtered]=\"filteredNode()?.id === node.id\"\r\n [class.tree-node-no-select]=\"!isSelectable(node)\"\r\n [attr.data-node-id]=\"node.id\">\r\n <button mat-icon-button matTreeNodeToggle>\r\n <mat-icon>{{treeNode.isExpanded ? 'expand_more' : 'chevron_right'}}</mat-icon>\r\n </button>\r\n @if (isSelectable(node)) {\r\n <mat-checkbox [checked]=\"isSelected(node)\" [indeterminate]=\"isIndeterminate(node)\"\r\n [disabled]=\"disabled()\" (change)=\"toggleNode(node)\">\r\n <span class=\"small\">{{node.name}}</span>\r\n </mat-checkbox>\r\n } @else {\r\n <div class=\"tree-node-label-only\">\r\n <span class=\"small\">{{node.name}}</span>\r\n </div>\r\n }\r\n </mat-tree-node>\r\n </mat-tree>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n <mat-tab [label]=\"hasSelection() ? 'Selezionati (' + selectedVisibleCount() + ')' : 'Selezionati (tutti)'\"\r\n style=\"height: 100%;\">\r\n <div fxLayout=\"column\" fxFill style=\"overflow: hidden; height: 100%;\">\r\n <div fxFlex>\r\n <div fxLayout=\"row\" fxLayoutAlign=\"start center\" fxLayoutGap=\"8px\" style=\"padding:12px\">\r\n @if (!hasSelection()) {\r\n <mat-icon>info</mat-icon>\r\n <span [innerHTML]=\"descriptionEmpty() | safeHtml\"></span>\r\n } @else {\r\n <div fxFlex=\"*\" fxLayoutAlign=\"end\">\r\n <button mat-button color=\"warn\" style=\"margin-left:auto\" (click)=\"clearAll()\">\r\n <mat-icon>deselect</mat-icon> Azzera tutto\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n <div fxFlex=\"*\" style=\"overflow-y: auto; padding-bottom: 12px;\">\r\n <mat-chip-set>\r\n @for (id of selection(); track id) {\r\n @let node = nodeById(id);\r\n @if (node && isChipVisible(id)) {\r\n <mat-chip (removed)=\"removeNode(node)\" style=\"max-width: 280px;\" [matTooltip]=\"node.name\">\r\n {{node.name}}\r\n @if (!disabled()) {\r\n <button matChipRemove matTooltip=\"Elimina\"><mat-icon>cancel</mat-icon></button>\r\n }\r\n </mat-chip>\r\n }\r\n }\r\n </mat-chip-set>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n</mat-tab-group>", styles: [".tree-picker-tabs ::ng-deep .mat-mdc-tab-body-wrapper{flex:1 1 auto;height:100%}.tree{padding:8px 0 16px;background-color:transparent!important}.tree-node{min-height:36px!important;padding-right:12px;margin-right:0}.tree-node .small-icon-button{width:2rem!important;height:2rem!important;padding:0!important;display:inline-flex!important;align-items:center;justify-content:center}.tree-node .small-icon-button .mat-mdc-button-touch-target{width:2rem!important;height:2rem!important}.tree-node:not(.tree-node-no-select):hover{cursor:pointer;background-color:var(--mat-menu-item-hover-state-layer-color, transparent);border-radius:24px}.tree-node-filtered ::ng-deep .mdc-label,.tree-node-filtered ::ng-deep .mat-mdc-checkbox label{font-weight:700;color:var(--ars-color-accent, #7894ae)!important}.tree-node-filtered .tree-node-label-only{font-weight:700;color:var(--ars-color-accent, #7894ae);opacity:1}.tree-node-activated ::ng-deep .mdc-label,.tree-node-activated ::ng-deep .mat-mdc-checkbox label{font-weight:700;color:var(--ars-color-secondary, #4a635f)!important}.tree-node-label-only{display:flex;flex-direction:column;justify-content:center;padding-left:30px;opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i1$1.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "directive", type: i1$1.MatTreeNodePadding, selector: "[matTreeNodePadding]", inputs: ["matTreeNodePadding", "matTreeNodePaddingIndent"] }, { kind: "directive", type: i1$1.MatTreeNodeToggle, selector: "[matTreeNodeToggle]", inputs: ["matTreeNodeToggleRecursive"] }, { kind: "component", type: i1$1.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i1$1.MatTreeNode, selector: "mat-tree-node", inputs: ["tabIndex", "disabled"], outputs: ["activation", "expandedChange"], exportAs: ["matTreeNode"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i2$2.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i4.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i5$1.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: i5$1.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i5$1.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FlexLayoutModule }, { kind: "directive", type: i2.FxLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg] ", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i2.FxFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg] ", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i2.FxShowHideDirective, selector: " [fxShow], [fxHide], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg] ", inputs: ["fxShow", "fxShow.xs", "fxShow.sm", "fxShow.md", "fxShow.lg", "fxShow.xl", "fxShow.lt-sm", "fxShow.lt-md", "fxShow.lt-lg", "fxShow.lt-xl", "fxShow.gt-xs", "fxShow.gt-sm", "fxShow.gt-md", "fxShow.gt-lg", "fxHide", "fxHide.xs", "fxHide.sm", "fxHide.md", "fxHide.lg", "fxHide.xl", "fxHide.lt-sm", "fxHide.lt-md", "fxHide.lt-lg", "fxHide.lt-xl", "fxHide.gt-xs", "fxHide.gt-sm", "fxHide.gt-md", "fxHide.gt-lg"] }, { kind: "directive", type: i2.FxLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg] ", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i2.FxLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg] ", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i2.FxFlexFillDirective, selector: " [fxFlexFill], [fxFill], [fxFlexFill.xs], [fxFlexFill.sm], [fxFlexFill.md], [fxFlexFill.lg], [fxFlexFill.xl], [fxFlexFill.lt-sm], [fxFlexFill.lt-md], [fxFlexFill.lt-lg], [fxFlexFill.lt-xl], [fxFlexFill.gt-xs], [fxFlexFill.gt-sm], [fxFlexFill.gt-md], [fxFlexFill.gt-lg] ", inputs: ["fxFlexFill", "fxFill", "fxFlexFill.xs", "fxFlexFill.sm", "fxFlexFill.md", "fxFlexFill.lg", "fxFlexFill.xl", "fxFlexFill.lt-sm", "fxFlexFill.lt-md", "fxFlexFill.lt-lg", "fxFlexFill.lt-xl", "fxFlexFill.gt-xs", "fxFlexFill.gt-sm", "fxFlexFill.gt-md", "fxFlexFill.gt-lg"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
919
+ }
920
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TreePickerComponent, decorators: [{
921
+ type: Component,
922
+ args: [{ selector: 'tree-picker', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatTreeModule, MatCheckboxModule, MatIconModule, MatTabsModule, MatChipsModule,
923
+ MatButtonModule, MatTooltipModule, MatFormFieldModule, MatInputModule, FormsModule, FlexLayoutModule, SafeHtmlPipe], template: "<mat-tab-group class=\"taxonomy-picker-tabs\" style=\"height:100%\">\r\n <mat-tab style=\"overflow-x: hidden !important; height: 100%\">\r\n <ng-template mat-tab-label>\r\n Seleziona\r\n <mat-icon\r\n style=\"font-size:16px;height:16px;width:16px;margin-left:4px;vertical-align:middle;color:var(--mat-sys-primary)\"\r\n [matTooltip]=\"'Nessuna selezione = tutti gli argomenti inclusi;\\r\\nOgni elemento selezionato include sempre tutti i suoi sottoelementi'\"\r\n matTooltipPosition=\"above\">\r\n info\r\n </mat-icon>\r\n </ng-template>\r\n <div fxLayout=\"column\" fxFill style=\"overflow: hidden; height: 100%;\">\r\n <div fxFlex>\r\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxLayoutAlign=\"start center\" fxFill>\r\n <div fxFlex fxHide.xs>\r\n <mat-form-field style=\"width:200px; padding: 8px 0px\" appearance=\"outline\"\r\n subscriptSizing=\"dynamic\">\r\n <mat-label>Cerca...</mat-label>\r\n <input type=\"text\" (keyup)=\"doFilter()\" matInput [ngModel]=\"filterText()\"\r\n (ngModelChange)=\"filterText.set($event)\"\r\n (keydown.enter)=\"$event.preventDefault(); $event.stopPropagation(); nextFiltered()\"\r\n (keydown.arrowDown)=\"$event.preventDefault(); $event.stopPropagation(); nextFiltered()\">\r\n @if (filterText()) {\r\n <button type=\"button\" type=\"button\" tabindex=\"-1\" matSuffix mat-icon-button\r\n aria-label=\"Clear\" (click)=\"clearFilter()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </mat-form-field>\r\n </div>\r\n @if (filteredItems().length > 0) {\r\n <div fxFlex=\"50px\" fxHide.xs fxLayoutAlign=\"end center\">\r\n <div class=\"small\">{{filterIndex() + 1}} / {{filteredItems().length}}</div>\r\n </div>\r\n <div fxFlex=\"48px\" fxHide.xs fxLayoutAlign=\"end center\">\r\n <button mat-icon-button (click)=\"nextFiltered()\">\r\n <mat-icon aria-label=\"Vai al prossimo\"\r\n matTooltip=\"Vai al prossimo\">arrow_downward</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n <div fxFlex=\"*\" fxLayoutAlign=\"end center\">\r\n <button mat-icon-button [matTooltip]=\"'Espandi tutto'\" (click)=\"expandAll()\">\r\n <mat-icon>unfold_more</mat-icon>\r\n </button>\r\n <button mat-icon-button [matTooltip]=\"'Comprimi tutto'\" (click)=\"collapseAll()\">\r\n <mat-icon>unfold_less</mat-icon>\r\n </button>\r\n <button mat-icon-button [matTooltip]=\"'Azzera selezione'\" [disabled]=\"!hasSelection()\"\r\n (click)=\"clearAll()\">\r\n <mat-icon>deselect</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div fxFlex=\"*\" style=\"overflow-y: auto;\">\r\n <mat-tree [dataSource]=\"tree()\" [childrenAccessor]=\"treeChildrenAccessor\" class=\"tree\">\r\n <!-- Leaf node -->\r\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodePadding [matTreeNodePaddingIndent]=\"20\"\r\n class=\"tree-node\" [class.tree-node-filtered]=\"filteredNode()?.id === node.id\"\r\n [class.tree-node-no-select]=\"!isSelectable(node)\"\r\n [attr.data-node-id]=\"node.id\">\r\n <button mat-icon-button disabled style=\"visibility: hidden\"></button>\r\n @if (isSelectable(node)) {\r\n <mat-checkbox [checked]=\"isSelected(node)\" [disabled]=\"disabled()\" (change)=\"toggleNode(node)\">\r\n <span class=\"small\">{{node.name}}</span>\r\n </mat-checkbox>\r\n } @else {\r\n <div class=\"tree-node-label-only\">\r\n <span class=\"small\">{{node.name}}</span>\r\n </div>\r\n }\r\n </mat-tree-node>\r\n <!-- Expandable node with children -->\r\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding\r\n [matTreeNodePaddingIndent]=\"20\" #treeNode=\"matTreeNode\" class=\"tree-node\"\r\n [class.tree-node-filtered]=\"filteredNode()?.id === node.id\"\r\n [class.tree-node-no-select]=\"!isSelectable(node)\"\r\n [attr.data-node-id]=\"node.id\">\r\n <button mat-icon-button matTreeNodeToggle>\r\n <mat-icon>{{treeNode.isExpanded ? 'expand_more' : 'chevron_right'}}</mat-icon>\r\n </button>\r\n @if (isSelectable(node)) {\r\n <mat-checkbox [checked]=\"isSelected(node)\" [indeterminate]=\"isIndeterminate(node)\"\r\n [disabled]=\"disabled()\" (change)=\"toggleNode(node)\">\r\n <span class=\"small\">{{node.name}}</span>\r\n </mat-checkbox>\r\n } @else {\r\n <div class=\"tree-node-label-only\">\r\n <span class=\"small\">{{node.name}}</span>\r\n </div>\r\n }\r\n </mat-tree-node>\r\n </mat-tree>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n <mat-tab [label]=\"hasSelection() ? 'Selezionati (' + selectedVisibleCount() + ')' : 'Selezionati (tutti)'\"\r\n style=\"height: 100%;\">\r\n <div fxLayout=\"column\" fxFill style=\"overflow: hidden; height: 100%;\">\r\n <div fxFlex>\r\n <div fxLayout=\"row\" fxLayoutAlign=\"start center\" fxLayoutGap=\"8px\" style=\"padding:12px\">\r\n @if (!hasSelection()) {\r\n <mat-icon>info</mat-icon>\r\n <span [innerHTML]=\"descriptionEmpty() | safeHtml\"></span>\r\n } @else {\r\n <div fxFlex=\"*\" fxLayoutAlign=\"end\">\r\n <button mat-button color=\"warn\" style=\"margin-left:auto\" (click)=\"clearAll()\">\r\n <mat-icon>deselect</mat-icon> Azzera tutto\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n <div fxFlex=\"*\" style=\"overflow-y: auto; padding-bottom: 12px;\">\r\n <mat-chip-set>\r\n @for (id of selection(); track id) {\r\n @let node = nodeById(id);\r\n @if (node && isChipVisible(id)) {\r\n <mat-chip (removed)=\"removeNode(node)\" style=\"max-width: 280px;\" [matTooltip]=\"node.name\">\r\n {{node.name}}\r\n @if (!disabled()) {\r\n <button matChipRemove matTooltip=\"Elimina\"><mat-icon>cancel</mat-icon></button>\r\n }\r\n </mat-chip>\r\n }\r\n }\r\n </mat-chip-set>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n</mat-tab-group>", styles: [".tree-picker-tabs ::ng-deep .mat-mdc-tab-body-wrapper{flex:1 1 auto;height:100%}.tree{padding:8px 0 16px;background-color:transparent!important}.tree-node{min-height:36px!important;padding-right:12px;margin-right:0}.tree-node .small-icon-button{width:2rem!important;height:2rem!important;padding:0!important;display:inline-flex!important;align-items:center;justify-content:center}.tree-node .small-icon-button .mat-mdc-button-touch-target{width:2rem!important;height:2rem!important}.tree-node:not(.tree-node-no-select):hover{cursor:pointer;background-color:var(--mat-menu-item-hover-state-layer-color, transparent);border-radius:24px}.tree-node-filtered ::ng-deep .mdc-label,.tree-node-filtered ::ng-deep .mat-mdc-checkbox label{font-weight:700;color:var(--ars-color-accent, #7894ae)!important}.tree-node-filtered .tree-node-label-only{font-weight:700;color:var(--ars-color-accent, #7894ae);opacity:1}.tree-node-activated ::ng-deep .mdc-label,.tree-node-activated ::ng-deep .mat-mdc-checkbox label{font-weight:700;color:var(--ars-color-secondary, #4a635f)!important}.tree-node-label-only{display:flex;flex-direction:column;justify-content:center;padding-left:30px;opacity:.7}\n"] }]
924
+ }], ctorParameters: () => [], propDecorators: { tree: [{ type: i0.Input, args: [{ isSignal: true, alias: "tree", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], descriptionEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptionEmpty", required: false }] }], maxDepth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDepth", required: false }] }], maxDepthOverrides: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDepthOverrides", required: false }] }], minDepth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDepth", required: false }] }], selectionCount: [{ type: i0.Output, args: ["selectionCount"] }], changed: [{ type: i0.Output, args: ["changed"] }], _treeRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatTree), { isSignal: true }] }] } });
925
+
926
+ /**
927
+ * A blank calendar header that hides the month/year navigation controls.
928
+ * Used when an inline calendar should render without any navigation UI.
929
+ */
930
+ class CalendarEmptyHeader {
931
+ constructor() {
932
+ this.destroyRef = inject(DestroyRef);
933
+ this.calendar = inject((MatCalendar));
934
+ this.changeDetector = inject(ChangeDetectorRef);
935
+ // Re-run change detection whenever the calendar's internal state changes
936
+ // (e.g. active date, selected date) so the blank header stays in sync.
937
+ this.calendar.stateChanges
938
+ .pipe(takeUntilDestroyed(this.destroyRef))
939
+ .subscribe(() => this.changeDetector.markForCheck());
940
+ }
941
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: CalendarEmptyHeader, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
942
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.3", type: CalendarEmptyHeader, isStandalone: true, selector: "ng-component", ngImport: i0, template: '<div></div>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
943
+ }
944
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: CalendarEmptyHeader, decorators: [{
945
+ type: Component,
946
+ args: [{
947
+ template: '<div></div>',
948
+ standalone: true,
949
+ changeDetection: ChangeDetectionStrategy.OnPush
950
+ }]
951
+ }], ctorParameters: () => [] });
952
+
953
+ /*
954
+ * Public API Surface of @arsedizioni/ars-utils/ui.controls
955
+ */
956
+
957
+ /**
958
+ * Generated bundle index. Do not edit.
959
+ */
960
+
961
+ export { ButtonSelectorComponent, ButtonToggleComponent, CalendarEmptyHeader, ChipsSelectorComponent, TreePickerComponent };
962
+ //# sourceMappingURL=arsedizioni-ars-utils-ui.controls.mjs.map