@c8y/ngx-components 1023.14.148 → 1023.14.152

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.
@@ -13016,21 +13016,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
13016
13016
  class MessageBannerService {
13017
13017
  constructor() {
13018
13018
  this.MESSAGE_BANNER = 'messageBanner';
13019
+ this.DISMISSED_BANNERS_KEY = 'c8y.dismissedMessageBanners';
13019
13020
  this.options = inject(OptionsService);
13020
13021
  this.showBanner$ = new Subject();
13022
+ this.isPreview = false;
13021
13023
  }
13022
13024
  settings$() {
13023
13025
  return this.options.get$(this.MESSAGE_BANNER);
13024
13026
  }
13025
- showBanner() {
13027
+ showBanner(isPreview = false) {
13028
+ this.isPreview = isPreview;
13026
13029
  this.showBanner$.next(true);
13027
13030
  }
13028
- dismiss() {
13031
+ dismiss(bannerId, acknowledge) {
13029
13032
  this.showBanner$.next(false);
13033
+ if (!this.isPreview && bannerId && acknowledge) {
13034
+ this.markBannerAsDismissed(bannerId);
13035
+ }
13036
+ this.isPreview = false;
13030
13037
  }
13031
13038
  currentValue() {
13032
13039
  return this.options.get(this.MESSAGE_BANNER);
13033
13040
  }
13041
+ /**
13042
+ * Checks if a banner with the given ID has been dismissed before.
13043
+ */
13044
+ isBannerDismissed(bannerId) {
13045
+ if (!bannerId) {
13046
+ return false;
13047
+ }
13048
+ const dismissed = localStorage.getItem(this.DISMISSED_BANNERS_KEY);
13049
+ if (!dismissed) {
13050
+ return false;
13051
+ }
13052
+ const dismissedIds = JSON.parse(dismissed);
13053
+ return dismissedIds.includes(bannerId);
13054
+ }
13055
+ /**
13056
+ * Marks a banner as dismissed in localStorage.
13057
+ */
13058
+ markBannerAsDismissed(bannerId) {
13059
+ const dismissed = localStorage.getItem(this.DISMISSED_BANNERS_KEY);
13060
+ const dismissedIds = dismissed ? JSON.parse(dismissed) : [];
13061
+ if (!dismissedIds.includes(bannerId)) {
13062
+ dismissedIds.push(bannerId);
13063
+ localStorage.setItem(this.DISMISSED_BANNERS_KEY, JSON.stringify(dismissedIds));
13064
+ }
13065
+ }
13034
13066
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: MessageBannerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
13035
13067
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: MessageBannerService, providedIn: 'root' }); }
13036
13068
  }
@@ -13046,18 +13078,22 @@ class MessageBannerComponent {
13046
13078
  ngOnInit() {
13047
13079
  this.settings$ = this.messageBannerService.settings$().pipe(shareReplay(1));
13048
13080
  this.showBanner$ = this.settings$.pipe(filter(Boolean), take(1), switchMap(settings => {
13049
- return this.messageBannerService.showBanner$.pipe(startWith(settings?.messageBannerEnabled));
13081
+ const wasDismissed = settings?.messageBannerId
13082
+ ? this.messageBannerService.isBannerDismissed(settings.messageBannerId)
13083
+ : false;
13084
+ const shouldShow = settings?.messageBannerEnabled && !wasDismissed;
13085
+ return this.messageBannerService.showBanner$.pipe(startWith(shouldShow));
13050
13086
  }));
13051
13087
  }
13052
- dismiss() {
13053
- this.messageBannerService.dismiss();
13088
+ dismiss(settings, acknowledge) {
13089
+ this.messageBannerService.dismiss(settings?.messageBannerId, acknowledge);
13054
13090
  }
13055
13091
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: MessageBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
13056
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: MessageBannerComponent, isStandalone: true, selector: "c8y-message-banner", ngImport: i0, template: "<ng-container *ngIf=\"settings$ | async as settings\">\n <div *ngIf=\"showBanner$ | async\">\n <div\n class=\"alert d-flex\"\n [class]=\"'alert-' + settings.messageBannerType\"\n >\n <span\n class=\"flex-grow\"\n [innerHTML]=\"settings.messageBannerContent | translate | markdownToHtml | async\"\n ></span>\n <button\n class=\"close a-s-start\"\n [attr.aria-label]=\"'Close' | translate\"\n type=\"button\"\n (click)=\"dismiss()\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n <span class=\"sr-only\">Close</span>\n </button>\n </div>\n </div>\n</ng-container>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: MarkdownToHtmlPipe, name: "markdownToHtml" }] }); }
13092
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: MessageBannerComponent, isStandalone: true, selector: "c8y-message-banner", ngImport: i0, template: "@if (settings$ | async; as settings) {\n @if (showBanner$ | async) {\n <div>\n <div\n class=\"alert\"\n [class]=\"'alert-' + settings.messageBannerType\"\n >\n <div\n class=\"flex-grow\"\n [innerHTML]=\"settings.messageBannerContent | translate | markdownToHtml | async\"\n ></div>\n <div class=\"d-flex\">\n <button\n class=\"btn btn-default m-l-auto\"\n [title]=\"'Acknowledge and close' | translate\"\n type=\"button\"\n (click)=\"dismiss(settings, true)\"\n >\n {{ 'Acknowledge and close' | translate }}\n </button>\n <button\n class=\"btn btn-default m-l-8\"\n [title]=\"'Close' | translate\"\n type=\"button\"\n (click)=\"dismiss(settings, false)\"\n >\n {{ 'Close' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n}\n", dependencies: [{ kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: MarkdownToHtmlPipe, name: "markdownToHtml" }] }); }
13057
13093
  }
13058
13094
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: MessageBannerComponent, decorators: [{
13059
13095
  type: Component,
13060
- args: [{ selector: 'c8y-message-banner', standalone: true, imports: [NgIf, IconDirective, C8yTranslatePipe, AsyncPipe, MarkdownToHtmlPipe], template: "<ng-container *ngIf=\"settings$ | async as settings\">\n <div *ngIf=\"showBanner$ | async\">\n <div\n class=\"alert d-flex\"\n [class]=\"'alert-' + settings.messageBannerType\"\n >\n <span\n class=\"flex-grow\"\n [innerHTML]=\"settings.messageBannerContent | translate | markdownToHtml | async\"\n ></span>\n <button\n class=\"close a-s-start\"\n [attr.aria-label]=\"'Close' | translate\"\n type=\"button\"\n (click)=\"dismiss()\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n <span class=\"sr-only\">Close</span>\n </button>\n </div>\n </div>\n</ng-container>\n" }]
13096
+ args: [{ selector: 'c8y-message-banner', standalone: true, imports: [IconDirective, C8yTranslatePipe, AsyncPipe, MarkdownToHtmlPipe], template: "@if (settings$ | async; as settings) {\n @if (showBanner$ | async) {\n <div>\n <div\n class=\"alert\"\n [class]=\"'alert-' + settings.messageBannerType\"\n >\n <div\n class=\"flex-grow\"\n [innerHTML]=\"settings.messageBannerContent | translate | markdownToHtml | async\"\n ></div>\n <div class=\"d-flex\">\n <button\n class=\"btn btn-default m-l-auto\"\n [title]=\"'Acknowledge and close' | translate\"\n type=\"button\"\n (click)=\"dismiss(settings, true)\"\n >\n {{ 'Acknowledge and close' | translate }}\n </button>\n <button\n class=\"btn btn-default m-l-8\"\n [title]=\"'Close' | translate\"\n type=\"button\"\n (click)=\"dismiss(settings, false)\"\n >\n {{ 'Close' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n}\n" }]
13061
13097
  }] });
13062
13098
 
13063
13099
  /**
@@ -19324,8 +19360,9 @@ class SelectComponent {
19324
19360
  * @ignore
19325
19361
  * @param selectKeyboardService The service to handle keyboard navigation.
19326
19362
  */
19327
- constructor(selectKeyboardService) {
19363
+ constructor(selectKeyboardService, translateService) {
19328
19364
  this.selectKeyboardService = selectKeyboardService;
19365
+ this.translateService = translateService;
19329
19366
  /**
19330
19367
  * Placeholder text to be displayed in the select.
19331
19368
  */
@@ -19405,6 +19442,12 @@ class SelectComponent {
19405
19442
  noMatchHighlightFirst: this.filterItems
19406
19443
  };
19407
19444
  }
19445
+ /**
19446
+ * @ignore
19447
+ */
19448
+ ngOnInit() {
19449
+ this.updateDisplayPlaceholder();
19450
+ }
19408
19451
  /**
19409
19452
  * @ignore
19410
19453
  */
@@ -19449,6 +19492,9 @@ class SelectComponent {
19449
19492
  noMatchHighlightFirst: changes.filterItems?.currentValue || this.filterItems
19450
19493
  };
19451
19494
  }
19495
+ if (changes.placeholder || changes.required) {
19496
+ this.updateDisplayPlaceholder();
19497
+ }
19452
19498
  }
19453
19499
  /**
19454
19500
  * @ignore
@@ -19597,7 +19643,21 @@ class SelectComponent {
19597
19643
  this.onChange(this.multi ? this._selected : this._selected[0]);
19598
19644
  }
19599
19645
  }
19600
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SelectComponent, deps: [{ token: SelectKeyboardService }], target: i0.ɵɵFactoryTarget.Component }); }
19646
+ /** Computes translated placeholder, appending a "(required)" hint when required. */
19647
+ updateDisplayPlaceholder() {
19648
+ const translatedPlaceholder = this.placeholder
19649
+ ? this.translateService.instant(this.placeholder)
19650
+ : this.placeholder;
19651
+ if (!this.required) {
19652
+ this.displayPlaceholder = translatedPlaceholder;
19653
+ return;
19654
+ }
19655
+ const requiredText = `(${this.translateService.instant(gettext$1('required'))})`;
19656
+ this.displayPlaceholder = translatedPlaceholder?.trim()
19657
+ ? `${translatedPlaceholder} ${requiredText}`
19658
+ : requiredText;
19659
+ }
19660
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SelectComponent, deps: [{ token: SelectKeyboardService }, { token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
19601
19661
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: SelectComponent, isStandalone: true, selector: "c8y-select", inputs: { placeholder: "placeholder", items: "items", selected: "selected", container: "container", multi: "multi", canSelectWithSpace: "canSelectWithSpace", disabled: "disabled", autoClose: "autoClose", insideClick: "insideClick", required: "required", canDeselect: "canDeselect", name: "name", icon: "icon", filterItems: "filterItems" }, outputs: { onSelect: "onSelect", onDeselect: "onDeselect", onIconClick: "onIconClick" }, host: { classAttribute: "c8y-select-v2" }, providers: [
19602
19662
  {
19603
19663
  provide: NG_VALUE_ACCESSOR,
@@ -19610,7 +19670,7 @@ class SelectComponent {
19610
19670
  multi: true
19611
19671
  },
19612
19672
  SelectKeyboardService
19613
- ], queries: [{ propertyName: "projectedSelectedItems", first: true, predicate: SelectedItemsDirective, descendants: true }, { propertyName: "projectedSelectableItems", predicate: SelectItemDirective }], viewQueries: [{ propertyName: "searchControl", first: true, predicate: ["searchControl"], descendants: true }, { propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "list", predicate: ListItemComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n [isDisabled]=\"disabled\"\n [insideClick]=\"insideClick\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n dropdownToggle\n (click)=\"open()\"\n>\n <div\n class=\"input-group input-group-dropdown\"\n role=\"button\"\n >\n <div\n class=\"form-control text-truncate\"\n [ngClass]=\"{\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0,\n 'text-truncate': !multi,\n 'inner-scroll d-flex a-i-center': multi\n }\"\n >\n <!-- rendering of selected items (with content projection) -->\n @if (projectedSelectedItems) {\n <div class=\"selected-items\">\n @for (selectedItem of selected; track selectedItem) {\n <ng-container\n *ngTemplateOutlet=\"\n projectedSelectedItems.templateRef;\n context: { $implicit: selectedItem }\n \"\n ></ng-container>\n }\n </div>\n @if (selected.length === 0 && !searchHasFocus && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ placeholder | translate }}\n </i>\n }\n } @else {\n <div class=\"selected-items\">\n @if (!multi) {\n <!-- hidden is needed, otherwise the propagation does not work correctly -->\n <span [hidden]=\"!searchHasFocus || !preselectedItem || filterItems\">\n {{ preselectedItem?.label | translate }}\n </span>\n <span [hidden]=\"searchHasFocus || selected.length !== 1\">\n {{ selected[0]?.label | translate }}\n </span>\n }\n @if (selected.length === 0 && !preselectedItem && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ placeholder | translate }}\n </i>\n }\n @if (multi) {\n <span class=\"m-r-4\">{{ searchControl.value }}</span>\n @for (selectedItem of selected; track selectedItem) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ selectedItem.label | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"\n $event.preventDefault(); $event.stopPropagation(); deselect(selectedItem)\n \"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.label | translate }}\n </span>\n }\n }\n </div>\n }\n </div>\n\n <input\n class=\"form-control text-truncate\"\n type=\"text\"\n autocomplete=\"off\"\n #searchControl\n [ngClass]=\"{\n 'p-absolute': true,\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0\n }\"\n [required]=\"required\"\n (blur)=\"doBlur()\"\n (focus)=\"doFocus()\"\n [name]=\"name\"\n [disabled]=\"disabled\"\n />\n\n <span class=\"input-group-btn\">\n <!-- this button is displayed only if we have something selected and are allowed to deselect -->\n @if (canDeselect && selected.length > 0) {\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"$event.preventDefault(); $event.stopPropagation(); deselectAll()\"\n data-cy=\"deselect-all-button\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"select-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal dropdown-menu--select\"\n [style.width]=\"container === 'body' ? searchControl.parentNode.clientWidth + 'px' : undefined\"\n role=\"menu\"\n data-cy=\"select--dropdown-menu\"\n *dropdownMenu\n >\n <!-- rendering of items (default) -->\n @for (item of filterItems ? (items | filterBy: searchControl.value) : items; track item) {\n <c8y-li\n style=\"cursor: pointer\"\n [selectable]=\"true\"\n [dense]=\"true\"\n [active]=\"!multi && item.value === selected[0]?.value\"\n (click)=\"select(item)\"\n >\n <span [attr.data-search-label]=\"item.label | translate\"></span>\n @if (multi) {\n <c8y-li-checkbox\n [selected]=\"selected.indexOf(item) > -1\"\n (click)=\"$event.preventDefault()\"\n ></c8y-li-checkbox>\n }\n @if (!item.template) {\n <c8y-li-body>\n {{ item.label | translate }}\n </c8y-li-body>\n }\n <ng-container\n *ngTemplateOutlet=\"item?.template\"\n ngProjectAs=\"c8y-li-body\"\n ></ng-container>\n </c8y-li>\n }\n <ng-content select=\"div\"></ng-content>\n </c8y-list-group>\n</div>\n", dependencies: [{ kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$3.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$3.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$3.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: FilterByPipe, name: "filterBy" }] }); }
19673
+ ], queries: [{ propertyName: "projectedSelectedItems", first: true, predicate: SelectedItemsDirective, descendants: true }, { propertyName: "projectedSelectableItems", predicate: SelectItemDirective }], viewQueries: [{ propertyName: "searchControl", first: true, predicate: ["searchControl"], descendants: true }, { propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "list", predicate: ListItemComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n [isDisabled]=\"disabled\"\n [insideClick]=\"insideClick\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n dropdownToggle\n (click)=\"open()\"\n>\n <div\n class=\"input-group input-group-dropdown\"\n role=\"button\"\n >\n <div\n class=\"form-control text-truncate\"\n [ngClass]=\"{\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0,\n 'text-truncate': !multi,\n 'inner-scroll d-flex a-i-center': multi\n }\"\n >\n <!-- rendering of selected items (with content projection) -->\n @if (projectedSelectedItems) {\n <div class=\"selected-items\">\n @for (selectedItem of selected; track selectedItem) {\n <ng-container\n *ngTemplateOutlet=\"\n projectedSelectedItems.templateRef;\n context: { $implicit: selectedItem }\n \"\n ></ng-container>\n }\n </div>\n @if (selected.length === 0 && !searchHasFocus && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n } @else {\n <div class=\"selected-items\">\n @if (!multi) {\n <!-- hidden is needed, otherwise the propagation does not work correctly -->\n <span [hidden]=\"!searchHasFocus || !preselectedItem || filterItems\">\n {{ preselectedItem?.label | translate }}\n </span>\n <span [hidden]=\"searchHasFocus || selected.length !== 1\">\n {{ selected[0]?.label | translate }}\n </span>\n }\n @if (selected.length === 0 && !preselectedItem && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n @if (multi) {\n <span class=\"m-r-4\">{{ searchControl.value }}</span>\n @for (selectedItem of selected; track selectedItem) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ selectedItem.label | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"\n $event.preventDefault(); $event.stopPropagation(); deselect(selectedItem)\n \"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.label | translate }}\n </span>\n }\n }\n </div>\n }\n </div>\n\n <input\n class=\"form-control text-truncate\"\n type=\"text\"\n autocomplete=\"off\"\n #searchControl\n [ngClass]=\"{\n 'p-absolute': true,\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0\n }\"\n [required]=\"required\"\n (blur)=\"doBlur()\"\n (focus)=\"doFocus()\"\n [name]=\"name\"\n [disabled]=\"disabled\"\n />\n\n <span class=\"input-group-btn\">\n <!-- this button is displayed only if we have something selected and are allowed to deselect -->\n @if (canDeselect && selected.length > 0) {\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"$event.preventDefault(); $event.stopPropagation(); deselectAll()\"\n data-cy=\"deselect-all-button\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"select-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal dropdown-menu--select\"\n [style.width]=\"container === 'body' ? searchControl.parentNode.clientWidth + 'px' : undefined\"\n role=\"menu\"\n data-cy=\"select--dropdown-menu\"\n *dropdownMenu\n >\n <!-- rendering of items (default) -->\n @for (item of filterItems ? (items | filterBy: searchControl.value) : items; track item) {\n <c8y-li\n style=\"cursor: pointer\"\n [selectable]=\"true\"\n [dense]=\"true\"\n [active]=\"!multi && item.value === selected[0]?.value\"\n (click)=\"select(item)\"\n >\n <span [attr.data-search-label]=\"item.label | translate\"></span>\n @if (multi) {\n <c8y-li-checkbox\n [selected]=\"selected.indexOf(item) > -1\"\n (click)=\"$event.preventDefault()\"\n ></c8y-li-checkbox>\n }\n @if (!item.template) {\n <c8y-li-body>\n {{ item.label | translate }}\n </c8y-li-body>\n }\n <ng-container\n *ngTemplateOutlet=\"item?.template\"\n ngProjectAs=\"c8y-li-body\"\n ></ng-container>\n </c8y-li>\n }\n <ng-content select=\"div\"></ng-content>\n </c8y-list-group>\n</div>\n", dependencies: [{ kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$3.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$3.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$3.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: FilterByPipe, name: "filterBy" }] }); }
19614
19674
  }
19615
19675
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: SelectComponent, decorators: [{
19616
19676
  type: Component,
@@ -19638,8 +19698,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
19638
19698
  ListItemBodyComponent,
19639
19699
  C8yTranslatePipe,
19640
19700
  FilterByPipe
19641
- ], template: "<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n [isDisabled]=\"disabled\"\n [insideClick]=\"insideClick\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n dropdownToggle\n (click)=\"open()\"\n>\n <div\n class=\"input-group input-group-dropdown\"\n role=\"button\"\n >\n <div\n class=\"form-control text-truncate\"\n [ngClass]=\"{\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0,\n 'text-truncate': !multi,\n 'inner-scroll d-flex a-i-center': multi\n }\"\n >\n <!-- rendering of selected items (with content projection) -->\n @if (projectedSelectedItems) {\n <div class=\"selected-items\">\n @for (selectedItem of selected; track selectedItem) {\n <ng-container\n *ngTemplateOutlet=\"\n projectedSelectedItems.templateRef;\n context: { $implicit: selectedItem }\n \"\n ></ng-container>\n }\n </div>\n @if (selected.length === 0 && !searchHasFocus && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ placeholder | translate }}\n </i>\n }\n } @else {\n <div class=\"selected-items\">\n @if (!multi) {\n <!-- hidden is needed, otherwise the propagation does not work correctly -->\n <span [hidden]=\"!searchHasFocus || !preselectedItem || filterItems\">\n {{ preselectedItem?.label | translate }}\n </span>\n <span [hidden]=\"searchHasFocus || selected.length !== 1\">\n {{ selected[0]?.label | translate }}\n </span>\n }\n @if (selected.length === 0 && !preselectedItem && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ placeholder | translate }}\n </i>\n }\n @if (multi) {\n <span class=\"m-r-4\">{{ searchControl.value }}</span>\n @for (selectedItem of selected; track selectedItem) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ selectedItem.label | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"\n $event.preventDefault(); $event.stopPropagation(); deselect(selectedItem)\n \"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.label | translate }}\n </span>\n }\n }\n </div>\n }\n </div>\n\n <input\n class=\"form-control text-truncate\"\n type=\"text\"\n autocomplete=\"off\"\n #searchControl\n [ngClass]=\"{\n 'p-absolute': true,\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0\n }\"\n [required]=\"required\"\n (blur)=\"doBlur()\"\n (focus)=\"doFocus()\"\n [name]=\"name\"\n [disabled]=\"disabled\"\n />\n\n <span class=\"input-group-btn\">\n <!-- this button is displayed only if we have something selected and are allowed to deselect -->\n @if (canDeselect && selected.length > 0) {\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"$event.preventDefault(); $event.stopPropagation(); deselectAll()\"\n data-cy=\"deselect-all-button\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"select-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal dropdown-menu--select\"\n [style.width]=\"container === 'body' ? searchControl.parentNode.clientWidth + 'px' : undefined\"\n role=\"menu\"\n data-cy=\"select--dropdown-menu\"\n *dropdownMenu\n >\n <!-- rendering of items (default) -->\n @for (item of filterItems ? (items | filterBy: searchControl.value) : items; track item) {\n <c8y-li\n style=\"cursor: pointer\"\n [selectable]=\"true\"\n [dense]=\"true\"\n [active]=\"!multi && item.value === selected[0]?.value\"\n (click)=\"select(item)\"\n >\n <span [attr.data-search-label]=\"item.label | translate\"></span>\n @if (multi) {\n <c8y-li-checkbox\n [selected]=\"selected.indexOf(item) > -1\"\n (click)=\"$event.preventDefault()\"\n ></c8y-li-checkbox>\n }\n @if (!item.template) {\n <c8y-li-body>\n {{ item.label | translate }}\n </c8y-li-body>\n }\n <ng-container\n *ngTemplateOutlet=\"item?.template\"\n ngProjectAs=\"c8y-li-body\"\n ></ng-container>\n </c8y-li>\n }\n <ng-content select=\"div\"></ng-content>\n </c8y-list-group>\n</div>\n" }]
19642
- }], ctorParameters: () => [{ type: SelectKeyboardService }], propDecorators: { placeholder: [{
19701
+ ], template: "<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n [isDisabled]=\"disabled\"\n [insideClick]=\"insideClick\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n dropdownToggle\n (click)=\"open()\"\n>\n <div\n class=\"input-group input-group-dropdown\"\n role=\"button\"\n >\n <div\n class=\"form-control text-truncate\"\n [ngClass]=\"{\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0,\n 'text-truncate': !multi,\n 'inner-scroll d-flex a-i-center': multi\n }\"\n >\n <!-- rendering of selected items (with content projection) -->\n @if (projectedSelectedItems) {\n <div class=\"selected-items\">\n @for (selectedItem of selected; track selectedItem) {\n <ng-container\n *ngTemplateOutlet=\"\n projectedSelectedItems.templateRef;\n context: { $implicit: selectedItem }\n \"\n ></ng-container>\n }\n </div>\n @if (selected.length === 0 && !searchHasFocus && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n } @else {\n <div class=\"selected-items\">\n @if (!multi) {\n <!-- hidden is needed, otherwise the propagation does not work correctly -->\n <span [hidden]=\"!searchHasFocus || !preselectedItem || filterItems\">\n {{ preselectedItem?.label | translate }}\n </span>\n <span [hidden]=\"searchHasFocus || selected.length !== 1\">\n {{ selected[0]?.label | translate }}\n </span>\n }\n @if (selected.length === 0 && !preselectedItem && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n @if (multi) {\n <span class=\"m-r-4\">{{ searchControl.value }}</span>\n @for (selectedItem of selected; track selectedItem) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ selectedItem.label | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"\n $event.preventDefault(); $event.stopPropagation(); deselect(selectedItem)\n \"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.label | translate }}\n </span>\n }\n }\n </div>\n }\n </div>\n\n <input\n class=\"form-control text-truncate\"\n type=\"text\"\n autocomplete=\"off\"\n #searchControl\n [ngClass]=\"{\n 'p-absolute': true,\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0\n }\"\n [required]=\"required\"\n (blur)=\"doBlur()\"\n (focus)=\"doFocus()\"\n [name]=\"name\"\n [disabled]=\"disabled\"\n />\n\n <span class=\"input-group-btn\">\n <!-- this button is displayed only if we have something selected and are allowed to deselect -->\n @if (canDeselect && selected.length > 0) {\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"$event.preventDefault(); $event.stopPropagation(); deselectAll()\"\n data-cy=\"deselect-all-button\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"select-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal dropdown-menu--select\"\n [style.width]=\"container === 'body' ? searchControl.parentNode.clientWidth + 'px' : undefined\"\n role=\"menu\"\n data-cy=\"select--dropdown-menu\"\n *dropdownMenu\n >\n <!-- rendering of items (default) -->\n @for (item of filterItems ? (items | filterBy: searchControl.value) : items; track item) {\n <c8y-li\n style=\"cursor: pointer\"\n [selectable]=\"true\"\n [dense]=\"true\"\n [active]=\"!multi && item.value === selected[0]?.value\"\n (click)=\"select(item)\"\n >\n <span [attr.data-search-label]=\"item.label | translate\"></span>\n @if (multi) {\n <c8y-li-checkbox\n [selected]=\"selected.indexOf(item) > -1\"\n (click)=\"$event.preventDefault()\"\n ></c8y-li-checkbox>\n }\n @if (!item.template) {\n <c8y-li-body>\n {{ item.label | translate }}\n </c8y-li-body>\n }\n <ng-container\n *ngTemplateOutlet=\"item?.template\"\n ngProjectAs=\"c8y-li-body\"\n ></ng-container>\n </c8y-li>\n }\n <ng-content select=\"div\"></ng-content>\n </c8y-list-group>\n</div>\n" }]
19702
+ }], ctorParameters: () => [{ type: SelectKeyboardService }, { type: i1$1.TranslateService }], propDecorators: { placeholder: [{
19643
19703
  type: Input
19644
19704
  }], items: [{
19645
19705
  type: Input