@yuuvis/client-framework 2.14.0 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/common/lib/common.module.d.ts +4 -2
  2. package/common/lib/components/index.d.ts +1 -0
  3. package/common/lib/components/scroll-buttons/scroll-buttons.component.d.ts +25 -0
  4. package/common/lib/directives/index.d.ts +1 -0
  5. package/common/lib/directives/scroll-buttons.directive.d.ts +20 -0
  6. package/fesm2022/yuuvis-client-framework-autocomplete.mjs +13 -4
  7. package/fesm2022/yuuvis-client-framework-autocomplete.mjs.map +1 -1
  8. package/fesm2022/yuuvis-client-framework-common.mjs +249 -7
  9. package/fesm2022/yuuvis-client-framework-common.mjs.map +1 -1
  10. package/fesm2022/yuuvis-client-framework-forms.mjs +4 -4
  11. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  12. package/fesm2022/yuuvis-client-framework-object-preview.mjs +1 -1
  13. package/fesm2022/yuuvis-client-framework-object-preview.mjs.map +1 -1
  14. package/fesm2022/yuuvis-client-framework-object-relationship.mjs +1 -1
  15. package/fesm2022/yuuvis-client-framework-object-relationship.mjs.map +1 -1
  16. package/fesm2022/yuuvis-client-framework-popout.mjs +9 -3
  17. package/fesm2022/yuuvis-client-framework-popout.mjs.map +1 -1
  18. package/fesm2022/yuuvis-client-framework-split-view.mjs +107 -8
  19. package/fesm2022/yuuvis-client-framework-split-view.mjs.map +1 -1
  20. package/fesm2022/yuuvis-client-framework-widget-grid.mjs +7 -1
  21. package/fesm2022/yuuvis-client-framework-widget-grid.mjs.map +1 -1
  22. package/lib/assets/i18n/de.json +2 -0
  23. package/lib/assets/i18n/en.json +2 -0
  24. package/package.json +5 -5
  25. package/popout/index.d.ts +1 -0
  26. package/popout/lib/fullscreen.directive.d.ts +4 -0
  27. package/popout/lib/popout.module.d.ts +2 -1
  28. package/split-view/lib/split-view.component.d.ts +91 -9
  29. package/widget-grid/lib/widget-grid-workspaces/widget-grid-workspaces.interface.d.ts +1 -1
  30. package/widget-grid/lib/widget-grid.component.d.ts +1 -1
  31. package/widget-grid/lib/widget-grid.interface.d.ts +2 -1
@@ -11,9 +11,11 @@ import * as i9 from "./directives/drag-scroll.directive";
11
11
  import * as i10 from "./directives/noop-value-accessor.directive";
12
12
  import * as i11 from "./directives/autofocus-child.directive";
13
13
  import * as i12 from "./directives/autofocus-delayed.directive";
14
- import * as i13 from "./components/confirm/confirm.component";
14
+ import * as i13 from "./directives/scroll-buttons.directive";
15
+ import * as i14 from "./components/confirm/confirm.component";
16
+ import * as i15 from "./components/scroll-buttons/scroll-buttons.component";
15
17
  export declare class YuvCommonModule {
16
18
  static ɵfac: i0.ɵɵFactoryDeclaration<YuvCommonModule, never>;
17
- static ɵmod: i0.ɵɵNgModuleDeclaration<YuvCommonModule, never, [typeof i1.BusyOverlayDirective, typeof i2.FocusWithinDirective, typeof i3.FileDropZoneDirective, typeof i4.ClickDoubleDirective, typeof i5.LightDismissDirective, typeof i6.ContainerSizeDirective, typeof i7.LongPressDirective, typeof i8.DragSelectDirective, typeof i9.DragScrollDirective, typeof i10.NoopValueAccessorDirective, typeof i11.AutofocusChildDirective, typeof i12.AutofocusDelayedDirective, typeof i13.ConfirmComponent], [typeof i1.BusyOverlayDirective, typeof i2.FocusWithinDirective, typeof i3.FileDropZoneDirective, typeof i4.ClickDoubleDirective, typeof i5.LightDismissDirective, typeof i6.ContainerSizeDirective, typeof i7.LongPressDirective, typeof i8.DragSelectDirective, typeof i9.DragScrollDirective, typeof i10.NoopValueAccessorDirective, typeof i11.AutofocusChildDirective, typeof i12.AutofocusDelayedDirective, typeof i13.ConfirmComponent]>;
19
+ static ɵmod: i0.ɵɵNgModuleDeclaration<YuvCommonModule, never, [typeof i1.BusyOverlayDirective, typeof i2.FocusWithinDirective, typeof i3.FileDropZoneDirective, typeof i4.ClickDoubleDirective, typeof i5.LightDismissDirective, typeof i6.ContainerSizeDirective, typeof i7.LongPressDirective, typeof i8.DragSelectDirective, typeof i9.DragScrollDirective, typeof i10.NoopValueAccessorDirective, typeof i11.AutofocusChildDirective, typeof i12.AutofocusDelayedDirective, typeof i13.ScrollButtonsDirective, typeof i14.ConfirmComponent, typeof i15.ScrollButtonsComponent], [typeof i1.BusyOverlayDirective, typeof i2.FocusWithinDirective, typeof i3.FileDropZoneDirective, typeof i4.ClickDoubleDirective, typeof i5.LightDismissDirective, typeof i6.ContainerSizeDirective, typeof i7.LongPressDirective, typeof i8.DragSelectDirective, typeof i9.DragScrollDirective, typeof i10.NoopValueAccessorDirective, typeof i11.AutofocusChildDirective, typeof i12.AutofocusDelayedDirective, typeof i13.ScrollButtonsDirective, typeof i14.ConfirmComponent, typeof i15.ScrollButtonsComponent]>;
18
20
  static ɵinj: i0.ɵɵInjectorDeclaration<YuvCommonModule>;
19
21
  }
@@ -5,3 +5,4 @@ export * from './retention-badge/retention-badge.component';
5
5
  export * from './confirm/confirm.interface';
6
6
  export * from './confirm/confirm.service';
7
7
  export * from './busy-overlay/busy-overlay.component';
8
+ export * from './scroll-buttons/scroll-buttons.component';
@@ -0,0 +1,25 @@
1
+ import { ElementRef } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Wrapper component that adds left/right scroll buttons when its content overflows horizontally.
5
+ * Buttons appear only when there is overflow in the respective direction.
6
+ *
7
+ * @example
8
+ * <yuv-scroll-buttons>
9
+ * <mat-chip-grid>...</mat-chip-grid>
10
+ * </yuv-scroll-buttons>
11
+ */
12
+ export declare class ScrollButtonsComponent {
13
+ #private;
14
+ scrollContainer: import("@angular/core").Signal<ElementRef<HTMLElement>>;
15
+ /** How many pixels to scroll per button click. */
16
+ scrollAmount: import("@angular/core").InputSignal<number>;
17
+ showLeftButton: import("@angular/core").WritableSignal<boolean>;
18
+ showRightButton: import("@angular/core").WritableSignal<boolean>;
19
+ constructor();
20
+ onScroll(): void;
21
+ scrollLeft(): void;
22
+ scrollRight(): void;
23
+ static ɵfac: i0.ɵɵFactoryDeclaration<ScrollButtonsComponent, never>;
24
+ static ɵcmp: i0.ɵɵComponentDeclaration<ScrollButtonsComponent, "yuv-scroll-buttons", never, { "scrollAmount": { "alias": "scrollAmount"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
25
+ }
@@ -10,3 +10,4 @@ export * from './focus-within.directive';
10
10
  export * from './light-dismiss.directive';
11
11
  export * from './longpress.directive';
12
12
  export * from './noop-value-accessor.directive';
13
+ export * from './scroll-buttons.directive';
@@ -0,0 +1,20 @@
1
+ import * as i0 from "@angular/core";
2
+ /**
3
+ * Directive that adds left/right scroll buttons around the host element when its content overflows horizontally.
4
+ * The directive restructures the DOM by wrapping the host inside a scroll container with navigation buttons.
5
+ *
6
+ * @example
7
+ * <mat-chip-grid yuvScrollButtons>...</mat-chip-grid>
8
+ *
9
+ * @example
10
+ * <div yuvScrollButtons [yuvScrollButtonsAmount]="200">...</div>
11
+ */
12
+ export declare class ScrollButtonsDirective {
13
+ #private;
14
+ private readonly translate;
15
+ /** How many pixels to scroll per button click. */
16
+ yuvScrollButtonsAmount: import("@angular/core").InputSignal<number>;
17
+ constructor();
18
+ static ɵfac: i0.ɵɵFactoryDeclaration<ScrollButtonsDirective, never>;
19
+ static ɵdir: i0.ɵɵDirectiveDeclaration<ScrollButtonsDirective, "[yuvScrollButtons]", never, { "yuvScrollButtonsAmount": { "alias": "yuvScrollButtonsAmount"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
20
+ }
@@ -17,7 +17,7 @@ import * as i4 from '@angular/material/input';
17
17
  import { MatInputModule } from '@angular/material/input';
18
18
  import * as i5 from '@angular/material/progress-spinner';
19
19
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
20
- import { AbstractMatFormField, injectNgControl } from '@yuuvis/client-framework/common';
20
+ import { AbstractMatFormField, injectNgControl, ScrollButtonsDirective } from '@yuuvis/client-framework/common';
21
21
  import { filter, debounceTime } from 'rxjs/operators';
22
22
 
23
23
  class AutocompleteComponent extends AbstractMatFormField {
@@ -203,13 +203,22 @@ class AutocompleteComponent extends AbstractMatFormField {
203
203
  super.onNgOnDestroy();
204
204
  }
205
205
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
206
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: AutocompleteComponent, isStandalone: true, selector: "yuv-autocomplete", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, distinctValues: { classPropertyName: "distinctValues", publicName: "distinctValues", isSignal: true, isRequired: false, transformFunction: null }, addOnBlur: { classPropertyName: "addOnBlur", publicName: "addOnBlur", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxItems: { classPropertyName: "maxItems", publicName: "maxItems", isSignal: true, isRequired: false, transformFunction: null }, forceSelection: { classPropertyName: "forceSelection", publicName: "forceSelection", isSignal: true, isRequired: false, transformFunction: null }, autocompleteValues: { classPropertyName: "autocompleteValues", publicName: "autocompleteValues", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { autocompleteFnc: "autocompleteFnc", acBlur: "acBlur" }, host: { attributes: { "attr.aria-disabled": "disabled" } }, providers: [{ provide: MatFormFieldControl, useExisting: AutocompleteComponent }], queries: [{ propertyName: "chipTemplate", first: true, predicate: ["chipTemplate"], descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "optionTemplate", first: true, predicate: ["optionTemplate"], descendants: true, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "matAutocomplete", first: true, predicate: ["auto"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (multiple()) {\n <mat-chip-grid #chipGrid [attr.aria-label]=\"ariaLabel()\" [formControl]=\"chipsControl\">\n @for (v of value; track $index) {\n <mat-chip-row (removed)=\"removeItem(v)\">\n {{ v.label || v.value || v }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n } \n <input\n [disabled]=\"!!chipsInputDisabled()\"\n type=\"text\"\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"add($event)\"\n />\n </mat-chip-grid>\n} @else {\n <input type=\"text\" matInput \n (blur)=\"onInputBlur()\" \n [placeholder]=\"placeholder || ''\" [attr.aria-label]=\"ariaLabel()\" [formControl]=\"inputControl\" [matAutocomplete]=\"auto\" />\n}\n@if (busy()) {\n <mat-spinner [diameter]=\"16\"></mat-spinner>\n}\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"acOptionSelected($event)\"\n (optionActivated)=\"acOptionActivated($event)\"\n (closed)=\"acPanelClosed()\"\n [displayWith]=\"displayFn\"\n>\n @for (option of _acValues(); track option.label) {\n <mat-option [value]=\"option\">\n <ng-container *ngTemplateOutlet=\"optionTemplate() || null; context: { $implicit: option }\"></ng-container>\n @if (!optionTemplate()) {\n {{ option.label }}\n }\n </mat-option>\n }\n</mat-autocomplete>\n", styles: [":host{display:inline-flex;position:relative}:host:has(mat-chip-grid){overflow-x:auto;scrollbar-width:none}:host input{background-color:transparent;border:0;width:100%;min-height:calc(var(--mdc-chip-container-height, 32px) + 4px);font-family:var(--mdc-chip-label-text-font, var(--mat-sys-label-large-font));line-height:var(--mdc-chip-label-text-line-height, var(--mat-sys-label-large-line-height));font-size:var(--mdc-chip-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-chip-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-chip-label-text-tracking, var(--mat-sys-label-large-tracking))}:host mat-spinner{align-self:center;position:absolute;inset-inline-end:0}:host mat-chip-grid{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i2.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i2.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i2.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.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: MatProgressSpinnerModule }, { kind: "component", type: i5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i6.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i6.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
206
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: AutocompleteComponent, isStandalone: true, selector: "yuv-autocomplete", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, distinctValues: { classPropertyName: "distinctValues", publicName: "distinctValues", isSignal: true, isRequired: false, transformFunction: null }, addOnBlur: { classPropertyName: "addOnBlur", publicName: "addOnBlur", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxItems: { classPropertyName: "maxItems", publicName: "maxItems", isSignal: true, isRequired: false, transformFunction: null }, forceSelection: { classPropertyName: "forceSelection", publicName: "forceSelection", isSignal: true, isRequired: false, transformFunction: null }, autocompleteValues: { classPropertyName: "autocompleteValues", publicName: "autocompleteValues", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { autocompleteFnc: "autocompleteFnc", acBlur: "acBlur" }, host: { attributes: { "attr.aria-disabled": "disabled" } }, providers: [{ provide: MatFormFieldControl, useExisting: AutocompleteComponent }], queries: [{ propertyName: "chipTemplate", first: true, predicate: ["chipTemplate"], descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "optionTemplate", first: true, predicate: ["optionTemplate"], descendants: true, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "matAutocomplete", first: true, predicate: ["auto"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (multiple()) {\n <mat-chip-grid yuvScrollButtons #chipGrid [attr.aria-label]=\"ariaLabel()\" [formControl]=\"chipsControl\">\n @for (v of value; track $index) {\n <mat-chip-row (removed)=\"removeItem(v)\">\n {{ v.label || v.value || v }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n [disabled]=\"!!chipsInputDisabled()\"\n type=\"text\"\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"add($event)\"\n />\n </mat-chip-grid>\n} @else {\n <input\n type=\"text\"\n matInput\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [attr.aria-label]=\"ariaLabel()\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n />\n}\n@if (busy()) {\n <mat-spinner [diameter]=\"16\"></mat-spinner>\n}\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"acOptionSelected($event)\"\n (optionActivated)=\"acOptionActivated($event)\"\n (closed)=\"acPanelClosed()\"\n [displayWith]=\"displayFn\"\n>\n @for (option of _acValues(); track option.label) {\n <mat-option [value]=\"option\">\n <ng-container *ngTemplateOutlet=\"optionTemplate() || null; context: { $implicit: option }\"></ng-container>\n @if (!optionTemplate()) {\n {{ option.label }}\n }\n </mat-option>\n }\n</mat-autocomplete>\n", styles: [":host{display:inline-flex;position:relative}:host:has(mat-chip-grid){min-width:0}:host input{background-color:transparent;border:0;width:100%;min-height:calc(var(--mdc-chip-container-height, 32px) + 4px);font-family:var(--mdc-chip-label-text-font, var(--mat-sys-label-large-font));line-height:var(--mdc-chip-label-text-line-height, var(--mat-sys-label-large-line-height));font-size:var(--mdc-chip-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-chip-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-chip-label-text-tracking, var(--mat-sys-label-large-tracking))}:host mat-spinner{align-self:center;position:absolute;inset-inline-end:0}:host mat-chip-grid{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i2.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i2.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i2.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.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: MatProgressSpinnerModule }, { kind: "component", type: i5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i6.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i6.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: ScrollButtonsDirective, selector: "[yuvScrollButtons]", inputs: ["yuvScrollButtonsAmount"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
207
207
  }
208
208
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteComponent, decorators: [{
209
209
  type: Component,
210
- args: [{ selector: 'yuv-autocomplete', imports: [CommonModule, MatChipsModule, MatIconModule, MatInputModule, MatProgressSpinnerModule, MatAutocompleteModule, ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: MatFormFieldControl, useExisting: AutocompleteComponent }], host: {
210
+ args: [{ selector: 'yuv-autocomplete', imports: [
211
+ CommonModule,
212
+ MatChipsModule,
213
+ MatIconModule,
214
+ MatInputModule,
215
+ MatProgressSpinnerModule,
216
+ MatAutocompleteModule,
217
+ ReactiveFormsModule,
218
+ ScrollButtonsDirective
219
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: MatFormFieldControl, useExisting: AutocompleteComponent }], host: {
211
220
  'attr.aria-disabled': 'disabled'
212
- }, template: "@if (multiple()) {\n <mat-chip-grid #chipGrid [attr.aria-label]=\"ariaLabel()\" [formControl]=\"chipsControl\">\n @for (v of value; track $index) {\n <mat-chip-row (removed)=\"removeItem(v)\">\n {{ v.label || v.value || v }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n } \n <input\n [disabled]=\"!!chipsInputDisabled()\"\n type=\"text\"\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"add($event)\"\n />\n </mat-chip-grid>\n} @else {\n <input type=\"text\" matInput \n (blur)=\"onInputBlur()\" \n [placeholder]=\"placeholder || ''\" [attr.aria-label]=\"ariaLabel()\" [formControl]=\"inputControl\" [matAutocomplete]=\"auto\" />\n}\n@if (busy()) {\n <mat-spinner [diameter]=\"16\"></mat-spinner>\n}\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"acOptionSelected($event)\"\n (optionActivated)=\"acOptionActivated($event)\"\n (closed)=\"acPanelClosed()\"\n [displayWith]=\"displayFn\"\n>\n @for (option of _acValues(); track option.label) {\n <mat-option [value]=\"option\">\n <ng-container *ngTemplateOutlet=\"optionTemplate() || null; context: { $implicit: option }\"></ng-container>\n @if (!optionTemplate()) {\n {{ option.label }}\n }\n </mat-option>\n }\n</mat-autocomplete>\n", styles: [":host{display:inline-flex;position:relative}:host:has(mat-chip-grid){overflow-x:auto;scrollbar-width:none}:host input{background-color:transparent;border:0;width:100%;min-height:calc(var(--mdc-chip-container-height, 32px) + 4px);font-family:var(--mdc-chip-label-text-font, var(--mat-sys-label-large-font));line-height:var(--mdc-chip-label-text-line-height, var(--mat-sys-label-large-line-height));font-size:var(--mdc-chip-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-chip-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-chip-label-text-tracking, var(--mat-sys-label-large-tracking))}:host mat-spinner{align-self:center;position:absolute;inset-inline-end:0}:host mat-chip-grid{width:100%}\n"] }]
221
+ }, template: "@if (multiple()) {\n <mat-chip-grid yuvScrollButtons #chipGrid [attr.aria-label]=\"ariaLabel()\" [formControl]=\"chipsControl\">\n @for (v of value; track $index) {\n <mat-chip-row (removed)=\"removeItem(v)\">\n {{ v.label || v.value || v }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n [disabled]=\"!!chipsInputDisabled()\"\n type=\"text\"\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"add($event)\"\n />\n </mat-chip-grid>\n} @else {\n <input\n type=\"text\"\n matInput\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [attr.aria-label]=\"ariaLabel()\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n />\n}\n@if (busy()) {\n <mat-spinner [diameter]=\"16\"></mat-spinner>\n}\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"acOptionSelected($event)\"\n (optionActivated)=\"acOptionActivated($event)\"\n (closed)=\"acPanelClosed()\"\n [displayWith]=\"displayFn\"\n>\n @for (option of _acValues(); track option.label) {\n <mat-option [value]=\"option\">\n <ng-container *ngTemplateOutlet=\"optionTemplate() || null; context: { $implicit: option }\"></ng-container>\n @if (!optionTemplate()) {\n {{ option.label }}\n }\n </mat-option>\n }\n</mat-autocomplete>\n", styles: [":host{display:inline-flex;position:relative}:host:has(mat-chip-grid){min-width:0}:host input{background-color:transparent;border:0;width:100%;min-height:calc(var(--mdc-chip-container-height, 32px) + 4px);font-family:var(--mdc-chip-label-text-font, var(--mat-sys-label-large-font));line-height:var(--mdc-chip-label-text-line-height, var(--mat-sys-label-large-line-height));font-size:var(--mdc-chip-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-chip-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-chip-label-text-tracking, var(--mat-sys-label-large-tracking))}:host mat-spinner{align-self:center;position:absolute;inset-inline-end:0}:host mat-chip-grid{width:100%}\n"] }]
213
222
  }] });
214
223
 
215
224
  class YuvAutocompleteModule {
@@ -1 +1 @@
1
- {"version":3,"file":"yuuvis-client-framework-autocomplete.mjs","sources":["../../../../../libs/yuuvis/client-framework/autocomplete/src/lib/autocomplete.component.ts","../../../../../libs/yuuvis/client-framework/autocomplete/src/lib/autocomplete.component.html","../../../../../libs/yuuvis/client-framework/autocomplete/src/lib/autocomplete.module.ts","../../../../../libs/yuuvis/client-framework/autocomplete/src/yuuvis-client-framework-autocomplete.ts"],"sourcesContent":["import { COMMA, ENTER } from '@angular/cdk/keycodes';\nimport { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n DestroyRef,\n effect,\n inject,\n input,\n OnDestroy,\n OnInit,\n output,\n signal,\n TemplateRef,\n viewChild\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor, FormControl, ReactiveFormsModule } from '@angular/forms';\nimport { MatAutocomplete, MatAutocompleteActivatedEvent, MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';\nimport { MatChipInputEvent, MatChipsModule } from '@angular/material/chips';\nimport { MatFormFieldControl } from '@angular/material/form-field';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { AbstractMatFormField, injectNgControl } from '@yuuvis/client-framework/common';\nimport { debounceTime, filter } from 'rxjs/operators';\nimport { AutocompleteItem } from './autocomplete.interface';\n\n@Component({\n selector: 'yuv-autocomplete',\n imports: [CommonModule, MatChipsModule, MatIconModule, MatInputModule, MatProgressSpinnerModule, MatAutocompleteModule, ReactiveFormsModule],\n templateUrl: './autocomplete.component.html',\n styleUrl: './autocomplete.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: MatFormFieldControl, useExisting: AutocompleteComponent }],\n host: {\n 'attr.aria-disabled': 'disabled'\n }\n})\nexport class AutocompleteComponent extends AbstractMatFormField<AutocompleteItem[]> implements ControlValueAccessor, OnInit, OnDestroy {\n #dRef = inject(DestroyRef);\n\n ariaLabel = input<string>('');\n\n matAutocomplete = viewChild.required<MatAutocomplete>('auto');\n /**\n * Template to be used for rendering selected items in multiselect (multiple=\"true\") mode\n */\n chipTemplate = contentChild('chipTemplate', { read: TemplateRef });\n optionTemplate = contentChild('optionTemplate', { read: TemplateRef });\n\n /**\n * Show a loading spinner\n */\n busy = input<boolean>(false);\n /**\n * Enable multiple values\n */\n multiple = input<boolean>(false);\n /**\n * Force distinct values (only applicable for multiselect)\n */\n distinctValues = input<boolean>(true);\n /**\n * Add user inputs to the list of values when the user leaves the\n * control without entering (only applicable for multiselect)\n */\n addOnBlur = input<boolean>(false);\n /**\n * Minimum number of characters entered to trigger suggestions\n */\n minLength = input<number>(2);\n /**\n * Maximum number of items when multiple is true. -1 means no limit.\n */\n maxItems = input<number>(-1);\n /**\n * Setting this to `true` will not allow values that are not contained in the suggestions list. The input\n * will be cleared on blur if no value from the list has been selected. Also values are only emitted when a\n * list item has been selected (usually every key stroke is changing the form controls value)\n */\n forceSelection = input<boolean>(false);\n\n _acValues = signal<AutocompleteItem[]>([]);\n autocompleteValues = input<AutocompleteItem[]>([]);\n #acValueEffect = effect(() => {\n const acv =\n this.multiple() && this.distinctValues()\n ? this.autocompleteValues().filter((v) => !(this.value || []).some((i) => i.label === v.label))\n : this.autocompleteValues();\n this._acValues.set(acv);\n });\n autocompleteFnc = output<string>();\n acBlur = output<void>();\n\n // value = signal<AutocompleteItem[]>([]);\n chipsInputDisabled = computed(() => this.multiple() && this.maxItems() !== -1 && this.value && this.value.length >= this.maxItems());\n chipsControl = new FormControl<AutocompleteItem[]>([]);\n inputControl = new FormControl<AutocompleteItem | string>('', {\n nonNullable: true\n });\n\n override ngControl = injectNgControl(this);\n\n displayFn(i: AutocompleteItem): string {\n return i?.label;\n }\n\n #activeAutocompleteValue = signal<AutocompleteItem | null>(null);\n\n acOptionSelected(event: MatAutocompleteSelectedEvent): void {\n if (this.multiple()) {\n this.value = [...(this.value || []), event.option.value];\n this.inputControl.setValue('');\n } else {\n this.value = event.option.value;\n }\n this._onChange(this.value);\n event.option.deselect();\n this._acValues.set([]);\n }\n\n acOptionActivated(event: MatAutocompleteActivatedEvent): void {\n if (event.option) this.#activeAutocompleteValue.set(event.option.value);\n }\n\n acPanelClosed() {\n this.#activeAutocompleteValue.set(null);\n this._acValues.set([]);\n }\n\n // multiple selection\n readonly separatorKeysCodes: number[] = [ENTER, COMMA];\n\n // triggered when the user presses enter or comma\n add(event: MatChipInputEvent): void {\n if (this.#activeAutocompleteValue()) return;\n let hasChanged = false;\n const value = (event.value || '').trim();\n const match = this.autocompleteValues().find((i) => i.label === value);\n if (this.forceSelection() && match) {\n this.value = this.multiple() ? [...(this.value || []), match] : [match];\n hasChanged = true;\n }\n\n const isDistinct = !(this.value || []).some((i) => i.label === value);\n if ((!this.distinctValues() || isDistinct) && value.length > 0) {\n this.value = [...(this.value || []), { label: value, value }];\n hasChanged = true;\n }\n\n if (this.forceSelection() && !match) {\n this.value = (this.value || []).filter((v) => v.label !== value) || [];\n }\n hasChanged && this._onChange(this.value);\n // Clear the input value\n this.inputControl.setValue('');\n this.matAutocomplete().showPanel = false;\n }\n\n onInputBlur() {\n if (!this.multiple()) return;\n // need to timeout because clicking on the option will trigger the blur event before the click event\n // and the input value will be cleared before the option is selected\n setTimeout(() => {\n const iv = this.inputControl.value as string;\n if (iv && iv.length > 0 && this.addOnBlur()) {\n const match = this.autocompleteValues().find((i) => i.label === iv);\n if (this.forceSelection() && match) {\n this.value = this.multiple() ? [...(this.value || []), match] : [match];\n this._onChange(this.value);\n } else if (!this.forceSelection()) {\n const v = { label: iv, value: iv };\n this.value = this.multiple() ? [...(this.value || []), v] : [v];\n this._onChange(this.value);\n }\n }\n this.inputControl.setValue('');\n this._acValues.set([]);\n this.acBlur.emit();\n }, 500);\n }\n\n removeItem(item: AutocompleteItem) {\n this.value = (this.value || []).filter((i) => i !== item);\n this._onChange(this.value);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private _onChange: (value: readonly AutocompleteItem[] | null) => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private _onTouched = () => {};\n\n writeValue(value: readonly AutocompleteItem[] | AutocompleteItem): void {\n if (!this.multiple()) {\n this.value = [value as AutocompleteItem];\n this.inputControl.patchValue(value as AutocompleteItem, { emitEvent: false });\n } else {\n this.value = structuredClone(value) as AutocompleteItem[];\n }\n }\n registerOnChange(fn: (value: readonly AutocompleteItem[] | null) => void): void {\n this._onChange = fn;\n }\n // eslint-disable-next-line @typescript-eslint/ban-types\n registerOnTouched(fn: () => {}): void {\n this._onTouched = fn;\n }\n\n setDisabledState?(isDisabled: boolean) {\n if (isDisabled) {\n this.inputControl.disable();\n this.chipsControl.disable();\n } else {\n this.inputControl.enable();\n this.chipsControl.enable();\n }\n this.disabled = isDisabled;\n }\n\n ngOnInit(): void {\n this.inputControl.valueChanges\n .pipe(\n filter((value) => !!value && (value as string).length >= this.minLength()),\n debounceTime(300),\n takeUntilDestroyed(this.#dRef)\n )\n .subscribe((value) => {\n this.autocompleteFnc.emit((value as string) || '');\n });\n }\n\n ngOnDestroy(): void {\n super.onNgOnDestroy();\n }\n}\n","@if (multiple()) {\n <mat-chip-grid #chipGrid [attr.aria-label]=\"ariaLabel()\" [formControl]=\"chipsControl\">\n @for (v of value; track $index) {\n <mat-chip-row (removed)=\"removeItem(v)\">\n {{ v.label || v.value || v }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n } \n <input\n [disabled]=\"!!chipsInputDisabled()\"\n type=\"text\"\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"add($event)\"\n />\n </mat-chip-grid>\n} @else {\n <input type=\"text\" matInput \n (blur)=\"onInputBlur()\" \n [placeholder]=\"placeholder || ''\" [attr.aria-label]=\"ariaLabel()\" [formControl]=\"inputControl\" [matAutocomplete]=\"auto\" />\n}\n@if (busy()) {\n <mat-spinner [diameter]=\"16\"></mat-spinner>\n}\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"acOptionSelected($event)\"\n (optionActivated)=\"acOptionActivated($event)\"\n (closed)=\"acPanelClosed()\"\n [displayWith]=\"displayFn\"\n>\n @for (option of _acValues(); track option.label) {\n <mat-option [value]=\"option\">\n <ng-container *ngTemplateOutlet=\"optionTemplate() || null; context: { $implicit: option }\"></ng-container>\n @if (!optionTemplate()) {\n {{ option.label }}\n }\n </mat-option>\n }\n</mat-autocomplete>\n","import { NgModule } from '@angular/core';\nimport { AutocompleteComponent } from './autocomplete.component';\n\n@NgModule({\n imports: [AutocompleteComponent],\n exports: [AutocompleteComponent]\n})\nexport class YuvAutocompleteModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"yuuvis-client-framework-autocomplete.mjs","sources":["../../../../../libs/yuuvis/client-framework/autocomplete/src/lib/autocomplete.component.ts","../../../../../libs/yuuvis/client-framework/autocomplete/src/lib/autocomplete.component.html","../../../../../libs/yuuvis/client-framework/autocomplete/src/lib/autocomplete.module.ts","../../../../../libs/yuuvis/client-framework/autocomplete/src/yuuvis-client-framework-autocomplete.ts"],"sourcesContent":["import { COMMA, ENTER } from '@angular/cdk/keycodes';\nimport { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n DestroyRef,\n effect,\n inject,\n input,\n OnDestroy,\n OnInit,\n output,\n signal,\n TemplateRef,\n viewChild\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor, FormControl, ReactiveFormsModule } from '@angular/forms';\nimport {\n MatAutocomplete,\n MatAutocompleteActivatedEvent,\n MatAutocompleteModule,\n MatAutocompleteSelectedEvent\n} from '@angular/material/autocomplete';\nimport { MatChipInputEvent, MatChipsModule } from '@angular/material/chips';\nimport { MatFormFieldControl } from '@angular/material/form-field';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { AbstractMatFormField, injectNgControl, ScrollButtonsDirective } from '@yuuvis/client-framework/common';\nimport { debounceTime, filter } from 'rxjs/operators';\nimport { AutocompleteItem } from './autocomplete.interface';\n\n@Component({\n selector: 'yuv-autocomplete',\n imports: [\n CommonModule,\n MatChipsModule,\n MatIconModule,\n MatInputModule,\n MatProgressSpinnerModule,\n MatAutocompleteModule,\n ReactiveFormsModule,\n ScrollButtonsDirective\n ],\n templateUrl: './autocomplete.component.html',\n styleUrl: './autocomplete.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: MatFormFieldControl, useExisting: AutocompleteComponent }],\n host: {\n 'attr.aria-disabled': 'disabled'\n }\n})\nexport class AutocompleteComponent\n extends AbstractMatFormField<AutocompleteItem[]>\n implements ControlValueAccessor, OnInit, OnDestroy\n{\n #dRef = inject(DestroyRef);\n\n ariaLabel = input<string>('');\n\n matAutocomplete = viewChild.required<MatAutocomplete>('auto');\n /**\n * Template to be used for rendering selected items in multiselect (multiple=\"true\") mode\n */\n chipTemplate = contentChild('chipTemplate', { read: TemplateRef });\n optionTemplate = contentChild('optionTemplate', { read: TemplateRef });\n\n /**\n * Show a loading spinner\n */\n busy = input<boolean>(false);\n /**\n * Enable multiple values\n */\n multiple = input<boolean>(false);\n /**\n * Force distinct values (only applicable for multiselect)\n */\n distinctValues = input<boolean>(true);\n /**\n * Add user inputs to the list of values when the user leaves the\n * control without entering (only applicable for multiselect)\n */\n addOnBlur = input<boolean>(false);\n /**\n * Minimum number of characters entered to trigger suggestions\n */\n minLength = input<number>(2);\n /**\n * Maximum number of items when multiple is true. -1 means no limit.\n */\n maxItems = input<number>(-1);\n /**\n * Setting this to `true` will not allow values that are not contained in the suggestions list. The input\n * will be cleared on blur if no value from the list has been selected. Also values are only emitted when a\n * list item has been selected (usually every key stroke is changing the form controls value)\n */\n forceSelection = input<boolean>(false);\n\n _acValues = signal<AutocompleteItem[]>([]);\n autocompleteValues = input<AutocompleteItem[]>([]);\n #acValueEffect = effect(() => {\n const acv =\n this.multiple() && this.distinctValues()\n ? this.autocompleteValues().filter((v) => !(this.value || []).some((i) => i.label === v.label))\n : this.autocompleteValues();\n this._acValues.set(acv);\n });\n autocompleteFnc = output<string>();\n acBlur = output<void>();\n\n // value = signal<AutocompleteItem[]>([]);\n chipsInputDisabled = computed(\n () => this.multiple() && this.maxItems() !== -1 && this.value && this.value.length >= this.maxItems()\n );\n chipsControl = new FormControl<AutocompleteItem[]>([]);\n inputControl = new FormControl<AutocompleteItem | string>('', {\n nonNullable: true\n });\n\n override ngControl = injectNgControl(this);\n\n displayFn(i: AutocompleteItem): string {\n return i?.label;\n }\n\n #activeAutocompleteValue = signal<AutocompleteItem | null>(null);\n\n acOptionSelected(event: MatAutocompleteSelectedEvent): void {\n if (this.multiple()) {\n this.value = [...(this.value || []), event.option.value];\n this.inputControl.setValue('');\n } else {\n this.value = event.option.value;\n }\n this._onChange(this.value);\n event.option.deselect();\n this._acValues.set([]);\n }\n\n acOptionActivated(event: MatAutocompleteActivatedEvent): void {\n if (event.option) this.#activeAutocompleteValue.set(event.option.value);\n }\n\n acPanelClosed() {\n this.#activeAutocompleteValue.set(null);\n this._acValues.set([]);\n }\n\n // multiple selection\n readonly separatorKeysCodes: number[] = [ENTER, COMMA];\n\n // triggered when the user presses enter or comma\n add(event: MatChipInputEvent): void {\n if (this.#activeAutocompleteValue()) return;\n let hasChanged = false;\n const value = (event.value || '').trim();\n const match = this.autocompleteValues().find((i) => i.label === value);\n if (this.forceSelection() && match) {\n this.value = this.multiple() ? [...(this.value || []), match] : [match];\n hasChanged = true;\n }\n\n const isDistinct = !(this.value || []).some((i) => i.label === value);\n if ((!this.distinctValues() || isDistinct) && value.length > 0) {\n this.value = [...(this.value || []), { label: value, value }];\n hasChanged = true;\n }\n\n if (this.forceSelection() && !match) {\n this.value = (this.value || []).filter((v) => v.label !== value) || [];\n }\n hasChanged && this._onChange(this.value);\n // Clear the input value\n this.inputControl.setValue('');\n this.matAutocomplete().showPanel = false;\n }\n\n onInputBlur() {\n if (!this.multiple()) return;\n // need to timeout because clicking on the option will trigger the blur event before the click event\n // and the input value will be cleared before the option is selected\n setTimeout(() => {\n const iv = this.inputControl.value as string;\n if (iv && iv.length > 0 && this.addOnBlur()) {\n const match = this.autocompleteValues().find((i) => i.label === iv);\n if (this.forceSelection() && match) {\n this.value = this.multiple() ? [...(this.value || []), match] : [match];\n this._onChange(this.value);\n } else if (!this.forceSelection()) {\n const v = { label: iv, value: iv };\n this.value = this.multiple() ? [...(this.value || []), v] : [v];\n this._onChange(this.value);\n }\n }\n this.inputControl.setValue('');\n this._acValues.set([]);\n this.acBlur.emit();\n }, 500);\n }\n\n removeItem(item: AutocompleteItem) {\n this.value = (this.value || []).filter((i) => i !== item);\n this._onChange(this.value);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private _onChange: (value: readonly AutocompleteItem[] | null) => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private _onTouched = () => {};\n\n writeValue(value: readonly AutocompleteItem[] | AutocompleteItem): void {\n if (!this.multiple()) {\n this.value = [value as AutocompleteItem];\n this.inputControl.patchValue(value as AutocompleteItem, { emitEvent: false });\n } else {\n this.value = structuredClone(value) as AutocompleteItem[];\n }\n }\n registerOnChange(fn: (value: readonly AutocompleteItem[] | null) => void): void {\n this._onChange = fn;\n }\n // eslint-disable-next-line @typescript-eslint/ban-types\n registerOnTouched(fn: () => {}): void {\n this._onTouched = fn;\n }\n\n setDisabledState?(isDisabled: boolean) {\n if (isDisabled) {\n this.inputControl.disable();\n this.chipsControl.disable();\n } else {\n this.inputControl.enable();\n this.chipsControl.enable();\n }\n this.disabled = isDisabled;\n }\n\n ngOnInit(): void {\n this.inputControl.valueChanges\n .pipe(\n filter((value) => !!value && (value as string).length >= this.minLength()),\n debounceTime(300),\n takeUntilDestroyed(this.#dRef)\n )\n .subscribe((value) => {\n this.autocompleteFnc.emit((value as string) || '');\n });\n }\n\n ngOnDestroy(): void {\n super.onNgOnDestroy();\n }\n}\n","@if (multiple()) {\n <mat-chip-grid yuvScrollButtons #chipGrid [attr.aria-label]=\"ariaLabel()\" [formControl]=\"chipsControl\">\n @for (v of value; track $index) {\n <mat-chip-row (removed)=\"removeItem(v)\">\n {{ v.label || v.value || v }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n [disabled]=\"!!chipsInputDisabled()\"\n type=\"text\"\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"add($event)\"\n />\n </mat-chip-grid>\n} @else {\n <input\n type=\"text\"\n matInput\n (blur)=\"onInputBlur()\"\n [placeholder]=\"placeholder || ''\"\n [attr.aria-label]=\"ariaLabel()\"\n [formControl]=\"inputControl\"\n [matAutocomplete]=\"auto\"\n />\n}\n@if (busy()) {\n <mat-spinner [diameter]=\"16\"></mat-spinner>\n}\n<mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"acOptionSelected($event)\"\n (optionActivated)=\"acOptionActivated($event)\"\n (closed)=\"acPanelClosed()\"\n [displayWith]=\"displayFn\"\n>\n @for (option of _acValues(); track option.label) {\n <mat-option [value]=\"option\">\n <ng-container *ngTemplateOutlet=\"optionTemplate() || null; context: { $implicit: option }\"></ng-container>\n @if (!optionTemplate()) {\n {{ option.label }}\n }\n </mat-option>\n }\n</mat-autocomplete>\n","import { NgModule } from '@angular/core';\nimport { AutocompleteComponent } from './autocomplete.component';\n\n@NgModule({\n imports: [AutocompleteComponent],\n exports: [AutocompleteComponent]\n})\nexport class YuvAutocompleteModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, ChangeDetectionStrategy, Component, inject, ElementRef, Input, Directive, computed, output, signal, EnvironmentInjector, ViewContainerRef, effect, EventEmitter, HostListener, Output, NgZone, contentChildren, Injectable, HostBinding, forwardRef, NgModule, InjectionToken, makeEnvironmentProviders, RendererFactory2 } from '@angular/core';
2
+ import { input, ChangeDetectionStrategy, Component, inject, DestroyRef, viewChild, signal, afterNextRender, ElementRef, Input, Directive, computed, output, EnvironmentInjector, ViewContainerRef, effect, EventEmitter, HostListener, Output, NgZone, contentChildren, Injectable, HostBinding, forwardRef, Renderer2, NgModule, InjectionToken, makeEnvironmentProviders, RendererFactory2 } from '@angular/core';
3
3
  import { CommonModule, DOCUMENT } from '@angular/common';
4
4
  import { MatButtonModule } from '@angular/material/button';
5
5
  import * as i2 from '@angular/material/dialog';
@@ -8,9 +8,9 @@ import * as i1 from '@ngx-translate/core';
8
8
  import { TranslateModule, TranslateService } from '@ngx-translate/core';
9
9
  import { YmtButtonDirective, YmtIconButtonDirective } from '@yuuvis/material';
10
10
  import { TranslateModule as TranslateModule$1, AppCacheService, RetentionService, LocaleDatePipe } from '@yuuvis/client-core';
11
- import { MatProgressSpinner } from '@angular/material/progress-spinner';
12
11
  import * as i1$1 from '@angular/material/icon';
13
12
  import { MatIconModule } from '@angular/material/icon';
13
+ import { MatProgressSpinner } from '@angular/material/progress-spinner';
14
14
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
15
15
  import { Subject, fromEvent, merge, timer, of, forkJoin, map as map$1 } from 'rxjs';
16
16
  import { debounceTime, tap, filter, switchMap, map, takeUntil } from 'rxjs/operators';
@@ -70,6 +70,63 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
70
70
  args: [{ selector: 'yuv-confirm', imports: [CommonModule, MatButtonModule, TranslateModule$1, MatDialogModule, DialogComponent, YmtButtonDirective], template: "<yuv-dialog [headertitel]=\"dialogData.title || ''\">\n <main>{{ dialogData.message }}</main>\n <footer>\n @if (!dialogData.hideCancelButton) {\n <button ymtButton=\"secondary\" mat-dialog-close type=\"button\">\n {{ dialogData.cancelLabel || ('yuv.confirm.cancel' | translate) }}\n </button>\n }\n <button ymtButton=\"primary\" type=\"button\" [mat-dialog-close]=\"true\">{{ dialogData.confirmLabel || ('yuv.confirm.confirm' | translate) }}</button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:contents}:host main{padding:var(--ymt-spacing-m)}\n"] }]
71
71
  }] });
72
72
 
73
+ const DEFAULT_SCROLL_AMOUNT$1 = 150;
74
+ /**
75
+ * Wrapper component that adds left/right scroll buttons when its content overflows horizontally.
76
+ * Buttons appear only when there is overflow in the respective direction.
77
+ *
78
+ * @example
79
+ * <yuv-scroll-buttons>
80
+ * <mat-chip-grid>...</mat-chip-grid>
81
+ * </yuv-scroll-buttons>
82
+ */
83
+ class ScrollButtonsComponent {
84
+ #destroyRef;
85
+ #resizeObserver;
86
+ constructor() {
87
+ this.#destroyRef = inject(DestroyRef);
88
+ this.scrollContainer = viewChild.required('scrollContainer');
89
+ /** How many pixels to scroll per button click. */
90
+ this.scrollAmount = input(DEFAULT_SCROLL_AMOUNT$1);
91
+ this.showLeftButton = signal(false);
92
+ this.showRightButton = signal(false);
93
+ afterNextRender(() => {
94
+ const element = this.scrollContainer().nativeElement;
95
+ this.#resizeObserver = new ResizeObserver(() => this.#checkOverflow());
96
+ this.#resizeObserver.observe(element);
97
+ // Also observe mutations to detect when children (chips) are added/removed
98
+ const mutationObserver = new MutationObserver(() => this.#checkOverflow());
99
+ mutationObserver.observe(element, { childList: true, subtree: true });
100
+ this.#destroyRef.onDestroy(() => {
101
+ this.#resizeObserver?.disconnect();
102
+ mutationObserver.disconnect();
103
+ });
104
+ this.#checkOverflow();
105
+ });
106
+ }
107
+ onScroll() {
108
+ this.#checkOverflow();
109
+ }
110
+ scrollLeft() {
111
+ this.scrollContainer().nativeElement.scrollBy({ left: -this.scrollAmount(), behavior: 'smooth' });
112
+ }
113
+ scrollRight() {
114
+ this.scrollContainer().nativeElement.scrollBy({ left: this.scrollAmount(), behavior: 'smooth' });
115
+ }
116
+ #checkOverflow() {
117
+ const element = this.scrollContainer().nativeElement;
118
+ const threshold = 1; // account for sub-pixel rounding
119
+ this.showLeftButton.set(element.scrollLeft > threshold);
120
+ this.showRightButton.set(element.scrollLeft + element.clientWidth < element.scrollWidth - threshold);
121
+ }
122
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ScrollButtonsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
123
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: ScrollButtonsComponent, isStandalone: true, selector: "yuv-scroll-buttons", inputs: { scrollAmount: { classPropertyName: "scrollAmount", publicName: "scrollAmount", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (showLeftButton()) {\n <button\n class=\"scroll-btn scroll-btn--left\"\n (click)=\"scrollLeft()\"\n [attr.aria-label]=\"'yuv.object-form-element.scroll.button.left' | translate\"\n >\n <mat-icon>chevron_left</mat-icon>\n </button>\n}\n<div class=\"scroll-content\" #scrollContainer (scroll)=\"onScroll()\">\n <ng-content />\n</div>\n@if (showRightButton()) {\n <button\n class=\"scroll-btn scroll-btn--right\"\n (click)=\"scrollRight()\"\n [attr.aria-label]=\"'yuv.object-form-element.scroll.button.right' | translate\"\n >\n <mat-icon>chevron_right</mat-icon>\n </button>\n}\n", styles: [":host{display:flex;align-items:center;flex:1;min-width:0}.scroll-content{flex:1;overflow-x:auto;scrollbar-width:none;min-width:0}.scroll-content ::ng-deep mat-chip-grid .mdc-evolution-chip-set__chips{flex-wrap:nowrap}.scroll-content ::ng-deep mat-chip-grid mat-chip-row{flex-shrink:0;max-width:none}.scroll-content ::ng-deep mat-chip-grid mat-chip-row .mdc-evolution-chip__cell--primary{max-width:none}.scroll-content ::ng-deep mat-chip-grid mat-chip-row .mdc-evolution-chip__text-label,.scroll-content ::ng-deep mat-chip-grid mat-chip-row .mat-mdc-chip-action-label{white-space:nowrap}.scroll-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:0;color:var(--ymv-text-color-subtle);width:var(--ymv-sizing-m);height:var(--ymv-sizing-m);background-color:var(--ymv-surface-hover)}.scroll-btn:hover,.scroll-btn:focus-visible{color:var(--ymv-text-color)}.scroll-btn:focus-visible{outline:2px solid var(--ymv-primary-color);outline-offset:-2px}.scroll-btn mat-icon{font-size:20px;width:20px;height:20px}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
124
+ }
125
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ScrollButtonsComponent, decorators: [{
126
+ type: Component,
127
+ args: [{ selector: 'yuv-scroll-buttons', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatIconModule, TranslateModule], template: "@if (showLeftButton()) {\n <button\n class=\"scroll-btn scroll-btn--left\"\n (click)=\"scrollLeft()\"\n [attr.aria-label]=\"'yuv.object-form-element.scroll.button.left' | translate\"\n >\n <mat-icon>chevron_left</mat-icon>\n </button>\n}\n<div class=\"scroll-content\" #scrollContainer (scroll)=\"onScroll()\">\n <ng-content />\n</div>\n@if (showRightButton()) {\n <button\n class=\"scroll-btn scroll-btn--right\"\n (click)=\"scrollRight()\"\n [attr.aria-label]=\"'yuv.object-form-element.scroll.button.right' | translate\"\n >\n <mat-icon>chevron_right</mat-icon>\n </button>\n}\n", styles: [":host{display:flex;align-items:center;flex:1;min-width:0}.scroll-content{flex:1;overflow-x:auto;scrollbar-width:none;min-width:0}.scroll-content ::ng-deep mat-chip-grid .mdc-evolution-chip-set__chips{flex-wrap:nowrap}.scroll-content ::ng-deep mat-chip-grid mat-chip-row{flex-shrink:0;max-width:none}.scroll-content ::ng-deep mat-chip-grid mat-chip-row .mdc-evolution-chip__cell--primary{max-width:none}.scroll-content ::ng-deep mat-chip-grid mat-chip-row .mdc-evolution-chip__text-label,.scroll-content ::ng-deep mat-chip-grid mat-chip-row .mat-mdc-chip-action-label{white-space:nowrap}.scroll-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:0;color:var(--ymv-text-color-subtle);width:var(--ymv-sizing-m);height:var(--ymv-sizing-m);background-color:var(--ymv-surface-hover)}.scroll-btn:hover,.scroll-btn:focus-visible{color:var(--ymv-text-color)}.scroll-btn:focus-visible{outline:2px solid var(--ymv-primary-color);outline-offset:-2px}.scroll-btn mat-icon{font-size:20px;width:20px;height:20px}\n"] }]
128
+ }], ctorParameters: () => [] });
129
+
73
130
  /**
74
131
  * Directive putting focus on a 'focusable' child element.
75
132
  * By default the first focusable child will receive focus.
@@ -995,6 +1052,188 @@ function injectNgControl(cva) {
995
1052
  throw new Error('...');
996
1053
  }
997
1054
 
1055
+ const DEFAULT_SCROLL_AMOUNT = 150;
1056
+ const THRESHOLD = 1;
1057
+ /**
1058
+ * Directive that adds left/right scroll buttons around the host element when its content overflows horizontally.
1059
+ * The directive restructures the DOM by wrapping the host inside a scroll container with navigation buttons.
1060
+ *
1061
+ * @example
1062
+ * <mat-chip-grid yuvScrollButtons>...</mat-chip-grid>
1063
+ *
1064
+ * @example
1065
+ * <div yuvScrollButtons [yuvScrollButtonsAmount]="200">...</div>
1066
+ */
1067
+ class ScrollButtonsDirective {
1068
+ #renderer;
1069
+ #elRef;
1070
+ #destroyRef;
1071
+ #leftBtn;
1072
+ #rightBtn;
1073
+ #scrollContent;
1074
+ constructor() {
1075
+ this.#renderer = inject(Renderer2);
1076
+ this.#elRef = inject(ElementRef);
1077
+ this.translate = inject(TranslateService);
1078
+ this.#destroyRef = inject(DestroyRef);
1079
+ /** How many pixels to scroll per button click. */
1080
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1081
+ this.yuvScrollButtonsAmount = input(DEFAULT_SCROLL_AMOUNT);
1082
+ afterNextRender(() => this.#init());
1083
+ }
1084
+ #init() {
1085
+ const host = this.#elRef.nativeElement;
1086
+ const parent = host.parentNode;
1087
+ const renderer = this.#renderer;
1088
+ // Create wrapper
1089
+ const wrapper = renderer.createElement('div');
1090
+ this.#applyStyles(wrapper, {
1091
+ display: 'flex',
1092
+ 'align-items': 'center',
1093
+ flex: '1',
1094
+ 'min-width': '0'
1095
+ });
1096
+ // Create scroll content container
1097
+ this.#scrollContent = renderer.createElement('div');
1098
+ this.#applyStyles(this.#scrollContent, {
1099
+ flex: '1',
1100
+ 'overflow-x': 'auto',
1101
+ 'scrollbar-width': 'none',
1102
+ 'min-width': '0'
1103
+ });
1104
+ // Create buttons
1105
+ this.#leftBtn = this.#createButton('chevron_left');
1106
+ this.#rightBtn = this.#createButton('chevron_right');
1107
+ // Restructure DOM: replace host with wrapper, move host into scroll content
1108
+ renderer.insertBefore(parent, wrapper, host);
1109
+ renderer.appendChild(this.#scrollContent, host);
1110
+ renderer.appendChild(wrapper, this.#leftBtn);
1111
+ renderer.appendChild(wrapper, this.#scrollContent);
1112
+ renderer.appendChild(wrapper, this.#rightBtn);
1113
+ // Apply chip-specific overrides
1114
+ this.#applyChipOverrides(host);
1115
+ // Hide buttons initially
1116
+ this.#setButtonVisible(this.#leftBtn, false);
1117
+ this.#setButtonVisible(this.#rightBtn, false);
1118
+ // Set up listeners
1119
+ this.#scrollContent.addEventListener('scroll', () => this.#checkOverflow(), { passive: true });
1120
+ const resizeObserver = new ResizeObserver(() => this.#checkOverflow());
1121
+ resizeObserver.observe(this.#scrollContent);
1122
+ const mutationObserver = new MutationObserver(() => this.#checkOverflow());
1123
+ mutationObserver.observe(this.#scrollContent, { childList: true, subtree: true });
1124
+ this.#leftBtn.addEventListener('click', () => {
1125
+ this.#scrollContent.scrollBy({ left: -this.yuvScrollButtonsAmount(), behavior: 'smooth' });
1126
+ });
1127
+ this.#rightBtn.addEventListener('click', () => {
1128
+ this.#scrollContent.scrollBy({ left: this.yuvScrollButtonsAmount(), behavior: 'smooth' });
1129
+ });
1130
+ this.#destroyRef.onDestroy(() => {
1131
+ resizeObserver.disconnect();
1132
+ mutationObserver.disconnect();
1133
+ });
1134
+ this.#checkOverflow();
1135
+ }
1136
+ #createButton(icon) {
1137
+ const btn = this.#renderer.createElement('button');
1138
+ btn.setAttribute('aria-label', icon === 'chevron_left'
1139
+ ? this.translate.instant('yuv.object-form-element.scroll.button.left')
1140
+ : this.translate.instant('yuv.object-form-element.scroll.button.right'));
1141
+ this.#applyStyles(btn, {
1142
+ 'flex-shrink': '0',
1143
+ display: 'inline-flex',
1144
+ 'align-items': 'center',
1145
+ 'justify-content': 'center',
1146
+ background: 'none',
1147
+ border: 'none',
1148
+ cursor: 'pointer',
1149
+ padding: '0',
1150
+ color: 'var(--ymt-text-color-subtle)',
1151
+ width: 'var(--ymt-sizing-m)',
1152
+ height: 'var(--ymt-sizing-m)',
1153
+ backgroundColor: 'var(--ymt-surface-hover)'
1154
+ });
1155
+ const iconEl = this.#renderer.createElement('span');
1156
+ iconEl.classList.add('material-symbols-sharp');
1157
+ this.#applyStyles(iconEl, {
1158
+ 'font-size': '1.25rem', //calc(var(--ymt-sizing-s) * 0.8)
1159
+ width: 'var(--ymt-sizing-s)',
1160
+ height: 'var(--ymt-sizing-s)'
1161
+ });
1162
+ iconEl.textContent = icon;
1163
+ this.#renderer.appendChild(btn, iconEl);
1164
+ const highlight = () => {
1165
+ btn.style.color = 'var(--ymt-text-color)';
1166
+ };
1167
+ const reset = () => {
1168
+ btn.style.color = 'var(--ymt-text-color-subtle)';
1169
+ };
1170
+ btn.addEventListener('mouseenter', highlight);
1171
+ btn.addEventListener('mouseleave', reset);
1172
+ btn.addEventListener('focusin', highlight);
1173
+ btn.addEventListener('focusout', reset);
1174
+ // Focus-visible outline via CSS class
1175
+ btn.addEventListener('focus', () => {
1176
+ if (btn.matches(':focus-visible')) {
1177
+ btn.style.outline = '2px solid var(--ymt-primary-color)';
1178
+ btn.style.outlineOffset = '-2px';
1179
+ }
1180
+ });
1181
+ btn.addEventListener('blur', () => {
1182
+ btn.style.outline = '';
1183
+ btn.style.outlineOffset = '';
1184
+ });
1185
+ return btn;
1186
+ }
1187
+ #applyChipOverrides(host) {
1188
+ const chipSet = host.querySelector('.mdc-evolution-chip-set__chips');
1189
+ if (chipSet) {
1190
+ chipSet.style.flexWrap = 'nowrap';
1191
+ }
1192
+ // Use MutationObserver to apply overrides to chip rows as they appear
1193
+ const applyRowOverrides = () => {
1194
+ host.querySelectorAll('mat-chip-row, .mat-mdc-chip-row').forEach((row) => {
1195
+ const rowElement = row;
1196
+ rowElement.style.flexShrink = '0';
1197
+ rowElement.style.maxWidth = 'none';
1198
+ const primaryCell = rowElement.querySelector('.mdc-evolution-chip__cell--primary');
1199
+ if (primaryCell) {
1200
+ primaryCell.style.maxWidth = 'none';
1201
+ }
1202
+ rowElement
1203
+ .querySelectorAll('.mdc-evolution-chip__text-label, .mat-mdc-chip-action-label')
1204
+ .forEach((label) => {
1205
+ label.style.whiteSpace = 'nowrap';
1206
+ });
1207
+ });
1208
+ };
1209
+ applyRowOverrides();
1210
+ const observer = new MutationObserver(() => applyRowOverrides());
1211
+ observer.observe(host, { childList: true, subtree: true });
1212
+ this.#destroyRef.onDestroy(() => observer.disconnect());
1213
+ }
1214
+ #setButtonVisible(btn, visible) {
1215
+ btn.style.display = visible ? 'inline-flex' : 'none';
1216
+ }
1217
+ #checkOverflow() {
1218
+ const scrollElement = this.#scrollContent;
1219
+ this.#setButtonVisible(this.#leftBtn, scrollElement.scrollLeft > THRESHOLD);
1220
+ this.#setButtonVisible(this.#rightBtn, scrollElement.scrollLeft + scrollElement.clientWidth < scrollElement.scrollWidth - THRESHOLD);
1221
+ }
1222
+ #applyStyles(element, styles) {
1223
+ Object.entries(styles).forEach(([prop, value]) => {
1224
+ this.#renderer.setStyle(element, prop, value);
1225
+ });
1226
+ }
1227
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ScrollButtonsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1228
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.20", type: ScrollButtonsDirective, isStandalone: true, selector: "[yuvScrollButtons]", inputs: { yuvScrollButtonsAmount: { classPropertyName: "yuvScrollButtonsAmount", publicName: "yuvScrollButtonsAmount", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
1229
+ }
1230
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ScrollButtonsDirective, decorators: [{
1231
+ type: Directive,
1232
+ args: [{
1233
+ selector: '[yuvScrollButtons]'
1234
+ }]
1235
+ }], ctorParameters: () => [] });
1236
+
998
1237
  const directives = [
999
1238
  BusyOverlayDirective,
1000
1239
  FocusWithinDirective,
@@ -1007,9 +1246,10 @@ const directives = [
1007
1246
  DragScrollDirective,
1008
1247
  NoopValueAccessorDirective,
1009
1248
  AutofocusChildDirective,
1010
- AutofocusDelayedDirective
1249
+ AutofocusDelayedDirective,
1250
+ ScrollButtonsDirective
1011
1251
  ];
1012
- const components = [ConfirmComponent];
1252
+ const components = [ConfirmComponent, ScrollButtonsComponent];
1013
1253
  class YuvCommonModule {
1014
1254
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: YuvCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1015
1255
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.20", ngImport: i0, type: YuvCommonModule, imports: [BusyOverlayDirective,
@@ -1023,7 +1263,8 @@ class YuvCommonModule {
1023
1263
  DragScrollDirective,
1024
1264
  NoopValueAccessorDirective,
1025
1265
  AutofocusChildDirective,
1026
- AutofocusDelayedDirective, ConfirmComponent], exports: [BusyOverlayDirective,
1266
+ AutofocusDelayedDirective,
1267
+ ScrollButtonsDirective, ConfirmComponent, ScrollButtonsComponent], exports: [BusyOverlayDirective,
1027
1268
  FocusWithinDirective,
1028
1269
  FileDropZoneDirective,
1029
1270
  ClickDoubleDirective,
@@ -1034,7 +1275,8 @@ class YuvCommonModule {
1034
1275
  DragScrollDirective,
1035
1276
  NoopValueAccessorDirective,
1036
1277
  AutofocusChildDirective,
1037
- AutofocusDelayedDirective, ConfirmComponent] }); }
1278
+ AutofocusDelayedDirective,
1279
+ ScrollButtonsDirective, ConfirmComponent, ScrollButtonsComponent] }); }
1038
1280
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: YuvCommonModule, imports: [components] }); }
1039
1281
  }
1040
1282
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: YuvCommonModule, decorators: [{
@@ -1584,5 +1826,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
1584
1826
  * Generated bundle index. Do not edit.
1585
1827
  */
1586
1828
 
1587
- export { AbstractMatFormField, AutofocusChildDirective, AutofocusDelayedDirective, BusyOverlayComponent, BusyOverlayDirective, ClickDoubleDirective, ConfirmComponent, ConfirmService, ContainerSizeDirective, DEFAULT_THEME, DEFAULT_THEME_KEY, DialogComponent, DialogSize, DragScrollDirective, DragSelectDirective, DragSelectItemDirective, FileDropZoneDirective, FocusWithinDirective, FormTranslateService, HIGH_CONTRAST_THEME, HIGH_CONTRAST_THEME_KEY, HaloFocusComponent, LayoutSettingsService, LightDismissDirective, LongPressDirective, NoopValueAccessorDirective, RetentionBadgeComponent, ThemeService, ThemeStorageKeys, YUV_CUSTOM_THEME, YuvCommonModule, getFirstFocusableChild, getFocusableChildren, injectNgControl, provideYuvCustomTheme };
1829
+ export { AbstractMatFormField, AutofocusChildDirective, AutofocusDelayedDirective, BusyOverlayComponent, BusyOverlayDirective, ClickDoubleDirective, ConfirmComponent, ConfirmService, ContainerSizeDirective, DEFAULT_THEME, DEFAULT_THEME_KEY, DialogComponent, DialogSize, DragScrollDirective, DragSelectDirective, DragSelectItemDirective, FileDropZoneDirective, FocusWithinDirective, FormTranslateService, HIGH_CONTRAST_THEME, HIGH_CONTRAST_THEME_KEY, HaloFocusComponent, LayoutSettingsService, LightDismissDirective, LongPressDirective, NoopValueAccessorDirective, RetentionBadgeComponent, ScrollButtonsComponent, ScrollButtonsDirective, ThemeService, ThemeStorageKeys, YUV_CUSTOM_THEME, YuvCommonModule, getFirstFocusableChild, getFocusableChildren, injectNgControl, provideYuvCustomTheme };
1588
1830
  //# sourceMappingURL=yuuvis-client-framework-common.mjs.map