@energycap/components 0.46.20-trusted-publishing.20260916-1514 → 0.46.21

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.
@@ -4157,6 +4157,7 @@ class PopupContainerDirective {
4157
4157
  });
4158
4158
  }
4159
4159
  if (!this.popperRef) {
4160
+ this.previouslyFocusedElement = this.document.activeElement;
4160
4161
  // Add the popper template as an embedded view since PopperJS
4161
4162
  // manipulates DOM elements.
4162
4163
  this.popupViewRef = this.viewContainer.createEmbeddedView(this.popup);
@@ -4180,12 +4181,31 @@ class PopupContainerDirective {
4180
4181
  this.globalCloseSubscription = undefined;
4181
4182
  }
4182
4183
  if (this.popperRef && this.popupViewRef) {
4184
+ // Determine this before destroying the view: once destroyed, the popup's
4185
+ // DOM nodes are gone and `document.activeElement` will already have fallen
4186
+ // back to <body>, so containment can no longer be checked afterward.
4187
+ const shouldRestoreFocus = this.isFocusInsidePopup() || this.document.activeElement === this.document.body;
4183
4188
  this.popupViewRef.destroy();
4184
4189
  this.popperRef.destroy();
4185
4190
  this.popperRef = undefined;
4186
4191
  this.popperStatusChange.emit('hidden');
4192
+ if (shouldRestoreFocus && this.previouslyFocusedElement?.focus) {
4193
+ this.previouslyFocusedElement.focus();
4194
+ }
4187
4195
  }
4188
4196
  }
4197
+ /**
4198
+ * Whether the current `document.activeElement` is contained within the popup's DOM.
4199
+ *
4200
+ * @memberof PopupContainerDirective
4201
+ */
4202
+ isFocusInsidePopup() {
4203
+ if (!this.popupViewRef) {
4204
+ return false;
4205
+ }
4206
+ const activeElement = this.document.activeElement;
4207
+ return this.popupViewRef.rootNodes.some(node => node.contains && node.contains(activeElement));
4208
+ }
4189
4209
  /**
4190
4210
  * Updates the popup container position
4191
4211
  */
@@ -8908,6 +8928,20 @@ class MultiselectComponent extends FormControlBase {
8908
8928
  get maxSelectionsReached() {
8909
8929
  return this.maxSelections > 0 && this.selectedItems.length >= this.maxSelections;
8910
8930
  }
8931
+ /**
8932
+ * Number of options currently shown in the menu, excluding the select-all row. Disabled items count
8933
+ * because they are displayed; this drives the "N of M" footer.
8934
+ */
8935
+ get visibleOptionCount() {
8936
+ return MenuComponent.getSelectableItems(this.filteredOptions.filter(item => item !== this.selectAllItem)).length;
8937
+ }
8938
+ /**
8939
+ * Whether the "N of M" footer is shown: only when totalRecords is known and exceeds what is displayed
8940
+ */
8941
+ get showTotalRecordsFooter() {
8942
+ const shown = this.visibleOptionCount;
8943
+ return !!this.totalRecords && shown > 0 && this.totalRecords > shown;
8944
+ }
8911
8945
  /**
8912
8946
  * Whether all currently visible selectable options are selected
8913
8947
  */
@@ -8998,6 +9032,12 @@ class MultiselectComponent extends FormControlBase {
8998
9032
  * @default 0
8999
9033
  */
9000
9034
  this.maxSelections = 0;
9035
+ /**
9036
+ * When false, the "Select all" row is left out of the menu. Use it for lists where selecting everything has
9037
+ * no meaning, for example recipients that already offer an explicit "Everyone" entry.
9038
+ * @default true
9039
+ */
9040
+ this.showSelectAll = true;
9001
9041
  /**
9002
9042
  * Notify parent when the filter text changes
9003
9043
  */
@@ -9084,6 +9124,9 @@ class MultiselectComponent extends FormControlBase {
9084
9124
  if (changes.placeholder) {
9085
9125
  this.updatePlaceholderText();
9086
9126
  }
9127
+ if (changes.showSelectAll && !changes.showSelectAll.firstChange) {
9128
+ this.resetOptions();
9129
+ }
9087
9130
  if (changes.readonly) {
9088
9131
  this.synchronizeDisabledAttributes();
9089
9132
  this.updateTagDismissability();
@@ -9145,16 +9188,32 @@ class MultiselectComponent extends FormControlBase {
9145
9188
  };
9146
9189
  }
9147
9190
  this.popup.popperOptions = popperOptions;
9148
- this.popup.popperStatusChange.pipe(takeUntil(this.componentDestroyed)).subscribe((event) => {
9149
- this.menuStatus = event;
9150
- if (event === 'hidden') {
9151
- this.filterFormModel.setValue('');
9152
- this.resetOptions();
9153
- }
9154
- if (event === 'visible' && this.filterInput) {
9155
- setTimeout(() => this.filterInput.nativeElement.focus(), 0);
9156
- }
9157
- });
9191
+ this.popup.popperStatusChange.pipe(takeUntil(this.componentDestroyed)).subscribe((event) => this.onPopupStatusChange(event));
9192
+ }
9193
+ /**
9194
+ * React to the popup opening or closing. Closing clears the filter so the menu reopens unfiltered.
9195
+ */
9196
+ onPopupStatusChange(event) {
9197
+ this.menuStatus = event;
9198
+ if (event === 'hidden') {
9199
+ this.clearFilter();
9200
+ }
9201
+ if (event === 'visible' && this.filterInput) {
9202
+ setTimeout(() => this.filterInput.nativeElement.focus(), 0);
9203
+ }
9204
+ }
9205
+ /**
9206
+ * Clear the filter text and un-filter the options. Consumers that load options from the `search` output only
9207
+ * know about the text the user typed, so when text is being cleared they are told with an empty search too;
9208
+ * otherwise the menu would reopen on their last, still-filtered result set.
9209
+ */
9210
+ clearFilter() {
9211
+ const hadFilterText = !!this.filterFormModel.value;
9212
+ this.filterFormModel.setValue('');
9213
+ this.resetOptions();
9214
+ if (hadFilterText && this.search.observers.length > 0) {
9215
+ this.search.emit('');
9216
+ }
9158
9217
  }
9159
9218
  /**
9160
9219
  * Show and hide the popup menu
@@ -9186,6 +9245,10 @@ class MultiselectComponent extends FormControlBase {
9186
9245
  this.toggleSelectAll();
9187
9246
  return;
9188
9247
  }
9248
+ // Disabled items are displayed for context but can never be toggled from the menu
9249
+ if (item.disabled) {
9250
+ return;
9251
+ }
9189
9252
  const index = this.selectedItems.findIndex(selected => this.isSameItem(selected, item));
9190
9253
  if (index > -1) {
9191
9254
  // Deselect
@@ -9263,8 +9326,7 @@ class MultiselectComponent extends FormControlBase {
9263
9326
  this.updateTags();
9264
9327
  this.buildCheckboxFormControls();
9265
9328
  // Clear the filter and reset the dropdown
9266
- this.filterFormModel.setValue('');
9267
- this.resetOptions();
9329
+ this.clearFilter();
9268
9330
  if (this.popup) {
9269
9331
  this.popup.update();
9270
9332
  }
@@ -9366,10 +9428,11 @@ class MultiselectComponent extends FormControlBase {
9366
9428
  this.updateTags();
9367
9429
  }
9368
9430
  /**
9369
- * Get selectable items from the current filtered options, excluding the select-all item
9431
+ * Get selectable items from the current filtered options, excluding the select-all item and any
9432
+ * disabled items. Select all and the allSelected check operate on this set so disabled items are skipped.
9370
9433
  */
9371
9434
  getVisibleSelectableItems() {
9372
- return MenuComponent.getSelectableItems(this.filteredOptions.filter(item => item !== this.selectAllItem));
9435
+ return MenuComponent.getSelectableItems(this.filteredOptions.filter(item => item !== this.selectAllItem)).filter(item => !item.disabled);
9373
9436
  }
9374
9437
  /**
9375
9438
  * Get all options including any custom items added by the user
@@ -9384,7 +9447,8 @@ class MultiselectComponent extends FormControlBase {
9384
9447
  */
9385
9448
  resetOptions(options) {
9386
9449
  const baseOptions = options || this.getAllOptions();
9387
- this.filteredOptions = baseOptions.length > 0 ? [this.selectAllItem, ...baseOptions] : [];
9450
+ const leadingItems = this.showSelectAll ? [this.selectAllItem] : [];
9451
+ this.filteredOptions = baseOptions.length > 0 ? [...leadingItems, ...baseOptions] : [];
9388
9452
  this.selectableItems = MenuComponent.getSelectableItems(this.filteredOptions);
9389
9453
  this.selectAllItem.checked = this.allSelected;
9390
9454
  this.highlightedItemIndex = -1;
@@ -9550,16 +9614,47 @@ class MultiselectComponent extends FormControlBase {
9550
9614
  this.effectivePlaceholder = this.searchPlaceholder;
9551
9615
  }
9552
9616
  }
9617
+ /**
9618
+ * Keep a checkbox control aligned with the effective disabled state of its MenuItem.
9619
+ * This covers both the raw item.disabled flag and the maxSelections lockout state.
9620
+ */
9621
+ syncCheckboxDisabledState(control, item) {
9622
+ const isSelected = this.selectedItems.some(selected => this.isSameItem(selected, item));
9623
+ /**
9624
+ * The actual checkbox state must reflect both the MenuItem's own disabled flag and the
9625
+ * maxSelections lockout rule. An item can be explicitly disabled at any time, and the
9626
+ * current selection can also cause a previously enabled item to become temporarily disabled
9627
+ * once the max selection limit is reached. We intentionally keep the selection check
9628
+ * separate from the raw disabled flag so selected items remain enabled while other items
9629
+ * are blocked, and we compute it from the live selectedItems collection instead of trusting
9630
+ * any stale cached control state. This prevents the control from staying enabled after a
9631
+ * rerender or property mutation when the same MenuItem instance is reused.
9632
+ */
9633
+ const shouldBeDisabled = !!item.disabled || (this.maxSelections > 0 && this.maxSelectionsReached && !isSelected);
9634
+ if (control.disabled !== shouldBeDisabled) {
9635
+ if (shouldBeDisabled) {
9636
+ control.disable({ emitEvent: false });
9637
+ }
9638
+ else {
9639
+ control.enable({ emitEvent: false });
9640
+ }
9641
+ }
9642
+ }
9553
9643
  /**
9554
9644
  * Get or create a FormControl for a menu item's checkbox.
9555
- * The control value is kept in sync with the item's checked state.
9645
+ * The control value is kept in sync with the item's checked state, and the control is created
9646
+ * disabled when the item itself is disabled so the rendered checkbox cannot be toggled.
9556
9647
  */
9557
9648
  getCheckboxFormControl(item) {
9558
9649
  let control = this.checkboxFormControls.get(item);
9559
9650
  if (!control) {
9560
- control = new UntypedFormControl(!!item.checked);
9651
+ control = new UntypedFormControl({
9652
+ value: !!item.checked,
9653
+ disabled: !!item.disabled || (this.maxSelections > 0 && this.maxSelectionsReached && !this.selectedItems.some(selected => this.isSameItem(selected, item)))
9654
+ });
9561
9655
  this.checkboxFormControls.set(item, control);
9562
9656
  }
9657
+ this.syncCheckboxDisabledState(control, item);
9563
9658
  return control;
9564
9659
  }
9565
9660
  /**
@@ -9573,8 +9668,10 @@ class MultiselectComponent extends FormControlBase {
9573
9668
  if (control.value !== shouldBeChecked) {
9574
9669
  control.setValue(shouldBeChecked);
9575
9670
  }
9671
+ this.syncCheckboxDisabledState(control, item);
9576
9672
  });
9577
9673
  this.ignoreCheckboxChanges = false;
9674
+ this.updateMaxSelectionsDisabledState();
9578
9675
  }
9579
9676
  /**
9580
9677
  * Build checkbox FormControls for all current options and subscribe to their
@@ -9624,38 +9721,20 @@ class MultiselectComponent extends FormControlBase {
9624
9721
  * Enable or disable individual checkbox FormControls based on whether the max selections
9625
9722
  * limit has been reached. When the limit is reached, unselected items are disabled to
9626
9723
  * indicate they cannot be selected. The select all checkbox is always left enabled since
9627
- * it can be used to deselect items.
9724
+ * it can be used to deselect items. Items flagged `disabled` on the MenuItem stay disabled
9725
+ * regardless of the limit.
9628
9726
  */
9629
9727
  updateMaxSelectionsDisabledState() {
9630
- if (this.maxSelections <= 0) {
9631
- this.checkboxFormControls.forEach((control) => {
9632
- if (control.disabled) {
9633
- control.enable({ emitEvent: false });
9634
- }
9635
- });
9636
- return;
9637
- }
9638
- const limitReached = this.maxSelectionsReached;
9639
9728
  this.checkboxFormControls.forEach((control, item) => {
9640
- const isSelected = this.selectedItems.some(selected => this.isSameItem(selected, item));
9641
- if (limitReached && !isSelected) {
9642
- if (control.enabled) {
9643
- control.disable({ emitEvent: false });
9644
- }
9645
- }
9646
- else {
9647
- if (control.disabled) {
9648
- control.enable({ emitEvent: false });
9649
- }
9650
- }
9729
+ this.syncCheckboxDisabledState(control, item);
9651
9730
  });
9652
9731
  }
9653
9732
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MultiselectComponent, deps: [{ token: ValidationMessageService }, { token: FormGroupHelper }, { token: i3.TranslateService }, { token: ScrollService }], target: i0.ɵɵFactoryTarget.Component }); }
9654
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MultiselectComponent, isStandalone: false, selector: "ec-multiselect", inputs: { options: "options", menuPosition: "menuPosition", popupFixed: "popupFixed", placeholder: "placeholder", tagType: "tagType", hideNoMatches: "hideNoMatches", noMatchesText: "noMatchesText", truncateItems: "truncateItems", allowCustom: "allowCustom", maxSelections: "maxSelections" }, outputs: { search: "search", selectionChanged: "selectionChanged" }, host: { listeners: { "window:resize": "onResize()" } }, viewQueries: [{ propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }, { propertyName: "checkboxMenuTemplate", first: true, predicate: ["checkboxMenuTemplate"], descendants: true, static: true }, { propertyName: "popup", first: true, predicate: PopupContainerDirective, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"control control-label-{{labelPosition}}\"\n [ngClass]=\"{'invalid': formModel.touched && formModel.invalid,\n 'is-readonly': readonly,\n 'is-disabled': formModel.disabled}\">\n\n @if (label) {\n <label [attr.id]=\"id + '_label'\" [attr.for]=\"id + '_filter'\">\n <span>{{label | translate}}</span>\n @if (validationErrors.length > 0 && formModel.touched && formModel.invalid) {\n <span>&nbsp;{{validationErrors}}</span>\n }\n @if (helpPopover) {\n <ec-help-popover id=\"{{id}}_helpPopover\"\n class=\"d-inline-block my-n3 mx-n1\"\n text=\"{{helpPopover | translate}}\"\n contentPosition=\"{{helpPopoverPosition}}\">\n </ec-help-popover>\n }\n </label>\n }\n\n <div class=\"textbox-group control-input\"\n *ecPopup=\"dropdownmenu\">\n <div class=\"multiselect-input\"\n [attr.id]=\"id + '_input_container'\"\n role=\"combobox\"\n [attr.aria-expanded]=\"menuStatus === 'visible'\"\n aria-haspopup=\"listbox\"\n [attr.aria-owns]=\"id + '_menu_list'\"\n [class.is-focused]=\"menuStatus === 'visible'\"\n [class.is-disabled]=\"formModel.disabled\"\n [class.is-empty]=\"selectedItems.length === 0\"\n [class.is-required]=\"required\"\n [class.has-selections]=\"selectedItems.length > 0\"\n (click)=\"toggleMenu($event)\">\n\n <!-- Selected tags -->\n @if (selectedTags.length > 0) {\n <ec-tags\n id=\"{{id}}_tags\"\n [tags]=\"selectedTags\"\n [wrap]=\"true\"\n [isCondensed]=\"false\"\n [isSubtle]=\"true\"\n (tagClosed)=\"removeTag($event)\"\n (click)=\"$event.stopPropagation()\">\n </ec-tags>\n }\n\n <!-- Filter input -->\n <input\n #filterInput\n class=\"multiselect-filter-input\"\n type=\"text\"\n [id]=\"id + '_filter'\"\n [formControl]=\"filterFormModel\"\n [placeholder]=\"effectivePlaceholder\"\n [tabindex]=\"tabindex\"\n (input)=\"onFilterInput()\"\n (keydown)=\"keyNavigate($event)\"\n (focusout)=\"onBlur()\"\n (click)=\"menuStatus === 'visible' ? $event.stopPropagation() : null\"\n autocomplete=\"off\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"menuStatus === 'visible' ? id + '_menu_list' : null\"\n [attr.aria-activedescendant]=\"activeDescendantId\"\n [attr.aria-labelledby]=\"label ? id + '_label' : null\"\n [attr.aria-label]=\"!label ? effectivePlaceholder : null\"\n [attr.aria-describedby]=\"selectedItems.length > 0 ? id + '_selection_status' : null\" />\n\n <i class=\"ec-icon icon-required\"></i>\n <i class=\"ec-icon icon-invalid\"></i>\n </div>\n\n <!-- Live region for selection announcements -->\n <span [id]=\"id + '_selection_status'\"\n class=\"sr-only\"\n aria-live=\"polite\"\n aria-atomic=\"true\">\n {{ 'Multiselect_LiveRegion_Status_SC' | translate:{ count: selectedItems.length } }}\n </span>\n\n <!-- Clear button -->\n @if (selectedItems.length > 0 && !formModel.disabled && !readonly) {\n <ec-button class=\"multiselect-clear-btn\"\n [id]=\"id + '_clear'\"\n icon=\"icon-cancel\"\n type=\"secondary\"\n [tabindex]=\"0\"\n attr.aria-label=\"{{'ClearAllSelections_SC' | translate}}\"\n (click)=\"clearAll(); $event.stopPropagation()\">\n </ec-button>\n }\n\n <!-- Toggle button -->\n <ec-button class=\"textbox-group-btn-right\"\n [id]=\"id + '_button'\"\n [disabled]=\"formModel.disabled\"\n icon=\"icon-caret-down\"\n [tabindex]=\"0\"\n type=\"secondary\"\n [attr.aria-label]=\"'Toggle dropdown'\"\n [attr.aria-expanded]=\"menuStatus === 'visible'\"\n (click)=\"toggleMenu($event)\"\n [class.active]=\"menuStatus === 'visible'\">\n </ec-button>\n </div>\n</div>\n\n<ng-template #dropdownmenu>\n <div class=\"popup\"\n ecOverlay\n role=\"listbox\"\n [attr.id]=\"id + '_listbox'\"\n [attr.aria-label]=\"label ? (label | translate) : effectivePlaceholder\"\n aria-multiselectable=\"true\"\n [status]=\"pending ? 'pending' : 'hasData'\">\n\n <ec-menu id=\"{{id}}_menu\"\n [class.border-top-0]=\"!filteredOptions.length && hideNoMatches && !showAddCustomOption\"\n [templateType]=\"'checkAndLabel'\"\n [customMenuTemplate]=\"checkboxMenuTemplate\"\n [showNoItems]=\"!hideNoMatches && !showAddCustomOption\"\n [noDataText]=\"noMatchesText\"\n [items]=\"filteredOptions\"\n [selected]=\"highlightedItem\"\n (selectedChanged)=\"onItemSelected($event)\"\n [truncateItems]=\"truncateItems\"\n [maintainSelectedItem]=\"false\">\n </ec-menu>\n\n @if (showAddCustomOption) {\n <div class=\"add-custom-option\"\n role=\"option\"\n attr.aria-label=\"{{'AddCustomItem_TC' | translate:{ customItem: filterFormModel.value } }}\"\n tabindex=\"-1\"\n (click)=\"addCustomItem()\">\n <i class=\"ec-icon icon-plus pr-2\" aria-hidden=\"true\"></i>\n <span class=\"label\">{{ 'AddCustomItem_TC' | translate:{ customItem: filterFormModel.value } }}</span>\n </div>\n }\n </div>\n</ng-template>\n\n<!-- Custom checkbox menu item template -->\n<ng-template #checkboxMenuTemplate let-item>\n <div class=\"d-flex\"\n role=\"option\"\n [attr.aria-selected]=\"!!item.checked\"\n [attr.aria-label]=\"item.label\">\n @if (item === selectAllItem) {\n <ec-checkbox\n id=\"{{id}}_selectAll_checkbox\"\n class=\"m-0 pr-3\"\n [formModel]=\"selectAllFormControl\"\n [dependentCheckboxesGroup]=\"selectAllDependentGroup\"\n [label]=\"item.label\"\n (click)=\"$event.stopPropagation()\">\n </ec-checkbox>\n } @else {\n @if (item.display !== 'heading' && item.display !== 'heading-divided-section') {\n <ec-checkbox\n id=\"{{item.id || id + '_checkbox_' + item.label}}\"\n class=\"m-0 pr-3\"\n [formModel]=\"getCheckboxFormControl(item)\"\n [attr.aria-label]=\"item.label\"\n [label]=\"item.label\"\n [icon]=\"item.icon\"\n (click)=\"$event.stopPropagation()\">\n </ec-checkbox>\n } @else {\n <span>{{item.label}}</span>\n }\n }\n </div>\n</ng-template>\n", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:hover:not(:disabled):not(:focus),:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:hover:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:hover:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:2px solid transparent;outline-offset:2px}:host textarea:focus-visible,:host input:focus-visible,:host select:focus-visible{outline-color:var(--ec-border-color-focus)}:host .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.control.invalid .multiselect-input{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid)}.control.invalid .multiselect-input.is-focused{border-color:var(--ec-form-control-background-color-invalid)}.control.invalid .multiselect-input .icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}.control.invalid .multiselect-input .icon-required{display:none}.control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}.control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}.control.invalid:not(.open) .multiselect-clear-btn ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}.control.invalid:not(.open) .multiselect-clear-btn ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}.control.invalid:not(.open) .textbox-group:hover .multiselect-input:not(.is-focused){border-color:var(--ec-form-control-border-color-hover)}.control.invalid:not(.open) .textbox-group:hover .multiselect-clear-btn ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-hover)}.control.invalid:not(.open) .textbox-group:hover .textbox-group-btn-right ::ng-deep button:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}.control{position:relative}.control.is-disabled:not(.is-readonly) .multiselect-input{opacity:var(--ec-form-control-opacity-disabled);background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);pointer-events:none}.control.is-readonly .multiselect-input{border-right:1px solid var(--ec-form-control-border-color-readonly);border-top-right-radius:var(--ec-border-radius);border-bottom-right-radius:var(--ec-border-radius);background-color:var(--ec-form-control-background-color-readonly);border-color:var(--ec-form-control-border-color-readonly);color:var(--ec-form-control-color-readonly);cursor:default}.control.is-readonly .multiselect-input .multiselect-filter-input{color:var(--ec-form-control-color-readonly)}.control.is-readonly .multiselect-input .multiselect-filter-input::placeholder{color:var(--ec-form-control-color-readonly)}.control.is-readonly ec-button{display:none}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover .multiselect-input:not(.is-focused){border-color:var(--ec-form-control-border-color-hover)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover .multiselect-clear-btn{--ec-button-border-color-secondary: var(--ec-form-control-border-color-hover)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover ec-button.textbox-group-btn-right{--ec-button-border-color-secondary: var(--ec-form-control-border-color-hover)}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}.textbox-group{align-items:stretch}.multiselect-input{display:flex;flex-wrap:wrap;align-items:center;min-height:2rem;max-height:6rem;overflow-y:auto;padding:0 .5rem;background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-top-left-radius:var(--ec-border-radius);border-bottom-left-radius:var(--ec-border-radius);border-right:0;cursor:text;flex:1 1;box-sizing:border-box;position:relative}.multiselect-input .icon-required,.multiselect-input .icon-invalid{display:none;color:var(--ec-form-control-border-color-invalid)}.multiselect-input.is-required.is-empty{padding-left:1.75rem}.multiselect-input.is-required.is-empty .icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}.multiselect-input.is-focused{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);z-index:1}.multiselect-filter-input{border:0;outline:none;background:transparent;flex:1 1 100%;min-width:4rem;height:1.625rem;padding:0;font-size:var(--ec-form-control-font-size);color:var(--ec-form-control-color);line-height:1.25rem;overflow:hidden;text-overflow:ellipsis}.multiselect-filter-input::placeholder{color:var(--ec-form-control-color-placeholder);text-overflow:ellipsis}.has-selections:not(.is-focused) .multiselect-filter-input{width:0;min-width:0;flex:0 0 0;height:0;overflow:hidden;padding:0;margin:0}.popup{background-color:var(--ec-background-color);border-radius:var(--ec-border-radius-card);box-shadow:var(--ec-box-shadow-overlay);margin-top:.25rem;overflow:hidden;z-index:var(--ec-z-index-popup)}ec-menu{display:block}ec-menu ::ng-deep ul{max-height:30vh}ec-menu ::ng-deep ul li{white-space:nowrap}ec-menu ::ng-deep ul li.is-checked .icon-check{opacity:1;color:var(--ec-color-interactive)}ec-menu ::ng-deep ul li.select-all-item{font-weight:600}.multiselect-clear-btn{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-border-color-secondary-focus: var(--ec-form-control-border-color);--ec-button-color-icon-secondary: var(--ec-color-icon)}.multiselect-clear-btn ::ng-deep button{height:100%;border-left:0;border-right:0;border-radius:0;padding:0 .375rem}.multiselect-clear-btn ::ng-deep button:hover{background-color:var(--ec-background-color-hover)}.multiselect-clear-btn ::ng-deep button .ec-icon{font-size:.75rem}ec-button.textbox-group-btn-right{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-border-color-secondary-focus: var(--ec-form-control-border-color);--ec-button-color-icon-secondary: var(--ec-color-icon)}ec-button.textbox-group-btn-right ::ng-deep button{height:100%;border-top-right-radius:var(--ec-border-radius);border-bottom-right-radius:var(--ec-border-radius)}.open .textbox-group ec-textbox{--ec-form-control-box-shadow-focus: none;--ec-form-control-border-color-focus: var(--ec-form-control-border-color)}.open .textbox-group ec-button{--ec-button-box-shadow-focus-secondary: none;--ec-button-background-color-secondary: var(--ec-background-color-selected)}.add-custom-option{display:flex;align-items:center;padding:.5rem .75rem;cursor:pointer;border-top:1px solid var(--ec-form-control-border-color, #ccc);color:var(--ec-color-text);font-size:.875rem}.add-custom-option:hover{background-color:var(--ec-color-background-hover, #f5f5f5)}.add-custom-option .label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "lockButton", "icon", "iconColor", "label", "ariaLabel", "ariaExpanded", "ariaHaspopup", "ariaActivedescendant", "ariaControls", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: ViewOverlayComponent, selector: "[ecOverlay]", inputs: ["status", "message", "action", "noDataTemplate", "displayAsMask", "overlayClassList"] }, { kind: "component", type: MenuComponent, selector: "ec-menu", inputs: ["id", "items", "selected", "parent", "templateType", "customMenuTemplate", "title", "showNoItems", "noDataText", "enableKeyNav", "rolePattern", "highlightedItem", "maintainSelectedItem", "truncateItems", "preserveIconSpace", "dropdownToggleButton"], outputs: ["selectedChanged", "highlightedItemChange", "menuClosed"] }, { kind: "directive", type: PopupContainerDirective, selector: "[ecPopup]", inputs: ["ecPopup", "options"] }, { kind: "component", type: CheckboxComponent, selector: "ec-checkbox", inputs: ["name", "icon", "dependentCheckboxesGroup", "ignoreDisabledDependents"] }, { kind: "component", type: TagsComponent, selector: "ec-tags", inputs: ["id", "tags", "wrap", "isCondensed", "isSubtle", "highlightText", "highlightNormalizePattern"], outputs: ["tagClosed"] }, { kind: "component", type: HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] }); }
9733
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MultiselectComponent, isStandalone: false, selector: "ec-multiselect", inputs: { options: "options", menuPosition: "menuPosition", popupFixed: "popupFixed", placeholder: "placeholder", tagType: "tagType", hideNoMatches: "hideNoMatches", noMatchesText: "noMatchesText", truncateItems: "truncateItems", allowCustom: "allowCustom", maxSelections: "maxSelections", totalRecords: "totalRecords", showSelectAll: "showSelectAll", customMenuTemplate: "customMenuTemplate" }, outputs: { search: "search", selectionChanged: "selectionChanged" }, host: { listeners: { "window:resize": "onResize()" } }, viewQueries: [{ propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }, { propertyName: "checkboxMenuTemplate", first: true, predicate: ["checkboxMenuTemplate"], descendants: true, static: true }, { propertyName: "popup", first: true, predicate: PopupContainerDirective, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"control control-label-{{labelPosition}}\"\n [ngClass]=\"{'invalid': formModel.touched && formModel.invalid,\n 'is-readonly': readonly,\n 'is-disabled': formModel.disabled,\n 'open': menuStatus === 'visible'}\">\n\n @if (label) {\n <label [attr.id]=\"id + '_label'\" [attr.for]=\"id + '_filter'\">\n <span>{{label | translate}}</span>\n @if (validationErrors.length > 0 && formModel.touched && formModel.invalid) {\n <span>&nbsp;{{validationErrors}}</span>\n }\n @if (helpPopover) {\n <ec-help-popover id=\"{{id}}_helpPopover\"\n class=\"d-inline-block my-n3 mx-n1\"\n text=\"{{helpPopover | translate}}\"\n contentPosition=\"{{helpPopoverPosition}}\">\n </ec-help-popover>\n }\n </label>\n }\n\n <div class=\"textbox-group control-input\"\n *ecPopup=\"dropdownmenu\">\n <div class=\"multiselect-input\"\n [attr.id]=\"id + '_input_container'\"\n role=\"combobox\"\n [attr.aria-expanded]=\"menuStatus === 'visible'\"\n aria-haspopup=\"listbox\"\n [attr.aria-owns]=\"id + '_menu_list'\"\n [class.is-focused]=\"menuStatus === 'visible'\"\n [class.is-disabled]=\"formModel.disabled\"\n [class.is-empty]=\"selectedItems.length === 0\"\n [class.is-required]=\"required\"\n [class.has-selections]=\"selectedItems.length > 0\"\n (click)=\"toggleMenu($event)\">\n\n <!-- Selected tags -->\n @if (selectedTags.length > 0) {\n <ec-tags\n id=\"{{id}}_tags\"\n [tags]=\"selectedTags\"\n [wrap]=\"true\"\n [isCondensed]=\"false\"\n [isSubtle]=\"true\"\n (tagClosed)=\"removeTag($event)\"\n (click)=\"$event.stopPropagation()\">\n </ec-tags>\n }\n\n <!-- Filter input -->\n <input\n #filterInput\n class=\"multiselect-filter-input\"\n type=\"text\"\n [id]=\"id + '_filter'\"\n [formControl]=\"filterFormModel\"\n [placeholder]=\"effectivePlaceholder\"\n [tabindex]=\"tabindex\"\n (input)=\"onFilterInput()\"\n (keydown)=\"keyNavigate($event)\"\n (focusout)=\"onBlur()\"\n (click)=\"menuStatus === 'visible' ? $event.stopPropagation() : null\"\n autocomplete=\"off\"\n [attr.cdkFocusInitial]=\"autofocus || null\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"menuStatus === 'visible' ? id + '_menu_list' : null\"\n [attr.aria-activedescendant]=\"activeDescendantId\"\n [attr.aria-labelledby]=\"label ? id + '_label' : null\"\n [attr.aria-label]=\"!label ? effectivePlaceholder : null\"\n [attr.aria-describedby]=\"selectedItems.length > 0 ? id + '_selection_status' : null\" />\n\n <i class=\"ec-icon icon-required\"></i>\n <i class=\"ec-icon icon-invalid\"></i>\n </div>\n\n <!-- Live region for selection announcements -->\n <span [id]=\"id + '_selection_status'\"\n class=\"sr-only\"\n aria-live=\"polite\"\n aria-atomic=\"true\">\n {{ 'Multiselect_LiveRegion_Status_SC' | translate:{ count: selectedItems.length } }}\n </span>\n\n <!-- Clear button -->\n @if (selectedItems.length > 0 && !formModel.disabled && !readonly) {\n <ec-button class=\"multiselect-clear-btn\"\n [id]=\"id + '_clear'\"\n icon=\"icon-cancel\"\n type=\"secondary\"\n [tabindex]=\"0\"\n attr.aria-label=\"{{'ClearAllSelections_SC' | translate}}\"\n (click)=\"clearAll(); $event.stopPropagation()\">\n </ec-button>\n }\n\n <!-- Toggle button -->\n <ec-button class=\"textbox-group-btn-right\"\n [id]=\"id + '_button'\"\n [disabled]=\"formModel.disabled\"\n icon=\"icon-caret-down\"\n [tabindex]=\"-1\"\n type=\"secondary\"\n [attr.aria-label]=\"'Toggle dropdown'\"\n [attr.aria-expanded]=\"menuStatus === 'visible'\"\n (click)=\"toggleMenu($event)\"\n [class.active]=\"menuStatus === 'visible'\">\n </ec-button>\n </div>\n</div>\n\n<ng-template #dropdownmenu>\n <div class=\"popup\"\n ecOverlay\n role=\"listbox\"\n [attr.id]=\"id + '_listbox'\"\n [attr.aria-label]=\"label ? (label | translate) : effectivePlaceholder\"\n aria-multiselectable=\"true\"\n [status]=\"pending ? 'pending' : 'hasData'\">\n\n <ec-menu id=\"{{id}}_menu\"\n [class.border-top-0]=\"!filteredOptions.length && hideNoMatches && !showAddCustomOption\"\n [templateType]=\"'checkAndLabel'\"\n [customMenuTemplate]=\"checkboxMenuTemplate\"\n [showNoItems]=\"!hideNoMatches && !showAddCustomOption\"\n [noDataText]=\"noMatchesText\"\n [items]=\"filteredOptions\"\n [selected]=\"highlightedItem\"\n (selectedChanged)=\"onItemSelected($event)\"\n [truncateItems]=\"truncateItems\"\n [maintainSelectedItem]=\"false\">\n </ec-menu>\n\n @if (showAddCustomOption) {\n <div class=\"add-custom-option\"\n role=\"option\"\n attr.aria-label=\"{{'AddCustomItem_TC' | translate:{ customItem: filterFormModel.value } }}\"\n tabindex=\"-1\"\n (click)=\"addCustomItem()\">\n <i class=\"ec-icon icon-plus pr-2\" aria-hidden=\"true\"></i>\n <span class=\"label\">{{ 'AddCustomItem_TC' | translate:{ customItem: filterFormModel.value } }}</span>\n </div>\n }\n\n @if (showTotalRecordsFooter) {\n <footer [attr.id]=\"id + '_footer'\">\n <span>{{visibleOptionCount}} {{'of' | translate}} {{totalRecords}}</span>\n </footer>\n }\n </div>\n</ng-template>\n\n<!-- Custom checkbox menu item template -->\n<ng-template #checkboxMenuTemplate let-item>\n <div class=\"multiselect-item-row d-flex\"\n role=\"option\"\n [attr.aria-selected]=\"!!item.checked\"\n [attr.aria-label]=\"item.label\">\n @if (item === selectAllItem) {\n <ec-checkbox\n id=\"{{id}}_selectAll_checkbox\"\n class=\"m-0 pr-3\"\n [formModel]=\"selectAllFormControl\"\n [dependentCheckboxesGroup]=\"selectAllDependentGroup\"\n [label]=\"item.label\"\n (click)=\"$event.stopPropagation()\">\n </ec-checkbox>\n } @else {\n @if (item.display !== 'heading' && item.display !== 'heading-divided-section') {\n <!-- The checkbox is always ours; with a custom template it renders bare and the host owns the rest of the row. -->\n <ec-checkbox\n id=\"{{item.id || id + '_checkbox_' + item.label}}\"\n class=\"m-0\"\n [class.pr-3]=\"!customMenuTemplate\"\n [class.w-auto]=\"!!customMenuTemplate\"\n [formModel]=\"getCheckboxFormControl(item)\"\n [attr.aria-label]=\"item.label\"\n [label]=\"customMenuTemplate ? undefined : item.label\"\n [icon]=\"customMenuTemplate ? undefined : item.icon\"\n (click)=\"$event.stopPropagation()\">\n </ec-checkbox>\n @if (customMenuTemplate) {\n <!-- Host-owned row content. Clicks here bubble to the row and toggle the item unless the host stops them. -->\n <div class=\"multiselect-item-content\"\n [attr.id]=\"(item.id || id + '_checkbox_' + item.label) + '_content'\">\n <ng-container *ngTemplateOutlet=\"customMenuTemplate; context: { $implicit: item }\"></ng-container>\n </div>\n }\n } @else {\n <span>{{item.label}}</span>\n }\n }\n </div>\n</ng-template>\n", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:hover:not(:disabled):not(:focus),:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:hover:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:hover:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:2px solid transparent;outline-offset:2px}:host textarea:focus-visible,:host input:focus-visible,:host select:focus-visible{outline-color:var(--ec-border-color-focus)}:host .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.control.invalid .multiselect-input{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid)}.control.invalid .multiselect-input:focus-within:not(.is-focused){border-color:var(--ec-form-control-background-color-invalid)}.control.invalid .multiselect-input .icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}.control.invalid .multiselect-input .icon-required{display:none}.control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}.control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}.control.invalid:not(.open) .multiselect-clear-btn ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}.control.invalid:not(.open) .multiselect-clear-btn ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}.control.invalid:not(.open) .textbox-group:hover .multiselect-input:not(.is-focused):not(:focus-within){border-color:var(--ec-form-control-border-color-hover)}.control.invalid:not(.open) .textbox-group:hover .multiselect-clear-btn ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-hover)}.control.invalid:not(.open) .textbox-group:hover .textbox-group-btn-right ::ng-deep button:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}.control{position:relative}.control.is-disabled:not(.is-readonly) .multiselect-input{opacity:var(--ec-form-control-opacity-disabled);background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);pointer-events:none}.control.is-readonly .multiselect-input{border-right:1px solid var(--ec-form-control-border-color-readonly);border-top-right-radius:var(--ec-border-radius);border-bottom-right-radius:var(--ec-border-radius);background-color:var(--ec-form-control-background-color-readonly);border-color:var(--ec-form-control-border-color-readonly);color:var(--ec-form-control-color-readonly);cursor:default}.control.is-readonly .multiselect-input .multiselect-filter-input{color:var(--ec-form-control-color-readonly)}.control.is-readonly .multiselect-input .multiselect-filter-input::placeholder{color:var(--ec-form-control-color-readonly)}.control.is-readonly ec-button{display:none}.control.open .textbox-group ec-button.multiselect-clear-btn{--ec-button-background-color-secondary: var(--ec-form-control-background-color)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover .multiselect-input:not(.is-focused):not(:focus-within){border-color:var(--ec-form-control-border-color-hover)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover .multiselect-clear-btn{--ec-button-border-color-secondary: var(--ec-form-control-border-color-hover)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover ec-button.textbox-group-btn-right{--ec-button-border-color-secondary: var(--ec-form-control-border-color-hover)}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}.textbox-group{align-items:stretch}.multiselect-input{display:flex;flex-wrap:wrap;align-items:center;min-height:2rem;max-height:6rem;overflow-y:auto;padding:0 .5rem;background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-top-left-radius:var(--ec-border-radius);border-bottom-left-radius:var(--ec-border-radius);border-right:0;cursor:text;flex:1 1;box-sizing:border-box;position:relative}.multiselect-input .icon-required,.multiselect-input .icon-invalid{display:none;color:var(--ec-form-control-border-color-invalid)}.multiselect-input.is-required.is-empty{padding-left:1.75rem}.multiselect-input.is-required.is-empty .icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}.multiselect-input:focus-within:not(.is-focused){border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);outline:2px solid transparent;outline-offset:2px;position:relative;z-index:1;border-right:1px solid var(--ec-form-control-border-color-focus)}.multiselect-input.is-focused{border-right:1px solid var(--ec-form-control-border-color);z-index:1}.multiselect-filter-input{border:0;outline:none;background:transparent}.multiselect-input .multiselect-filter-input:focus,.multiselect-input .multiselect-filter-input:focus-visible{outline:none;box-shadow:none}.multiselect-filter-input{flex:1 1 100%;min-width:4rem;height:1.625rem;padding:0;font-size:var(--ec-form-control-font-size);color:var(--ec-form-control-color);line-height:1.25rem;overflow:hidden;text-overflow:ellipsis}.multiselect-filter-input::placeholder{color:var(--ec-form-control-color-placeholder);text-overflow:ellipsis}.has-selections:not(.is-focused) .multiselect-filter-input{width:0;min-width:0;flex:0 0 0;height:0;overflow:hidden;padding:0;margin:0}.popup{background-color:var(--ec-background-color);border-radius:var(--ec-border-radius-card);box-shadow:var(--ec-box-shadow-overlay);margin-top:.25rem;overflow:hidden;z-index:var(--ec-z-index-popup)}ec-menu{display:block}ec-menu ::ng-deep ul{max-height:30vh}ec-menu ::ng-deep ul li{white-space:nowrap}ec-menu ::ng-deep ul li.is-checked .icon-check{opacity:1;color:var(--ec-color-interactive)}ec-menu ::ng-deep ul li.select-all-item{font-weight:600}ec-menu ::ng-deep ul li .multiselect-item-row{flex:1 1 auto;align-items:center;min-width:0}ec-menu ::ng-deep ul li .multiselect-item-content{display:flex;align-items:center;flex:1 1 auto;min-width:0;margin-left:.5rem}ec-menu ::ng-deep ul li .multiselect-item-hover-only{opacity:0;transition:opacity .1s ease-in-out}ec-menu ::ng-deep ul li:hover .multiselect-item-hover-only,ec-menu ::ng-deep ul li.is-highlighted .multiselect-item-hover-only,ec-menu ::ng-deep ul li .multiselect-item-hover-only:focus-within{opacity:1}.multiselect-clear-btn{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-border-color-secondary-focus: transparent;--ec-button-color-icon-secondary: var(--ec-color-icon)}.multiselect-clear-btn ::ng-deep button{height:100%;border-left:0;border-right:0;border-radius:0;padding:0 .375rem}.multiselect-clear-btn ::ng-deep button:hover{background-color:var(--ec-background-color-hover)}.multiselect-clear-btn ::ng-deep button:focus-visible{outline-color:transparent}.multiselect-clear-btn ::ng-deep button .ec-icon{font-size:.75rem}ec-button.textbox-group-btn-right{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-border-color-secondary-focus: var(--ec-form-control-border-color);--ec-button-box-shadow-focus-secondary: none;--ec-button-color-icon-secondary: var(--ec-color-icon)}ec-button.textbox-group-btn-right ::ng-deep button{height:100%;border-top-right-radius:var(--ec-border-radius);border-bottom-right-radius:var(--ec-border-radius)}ec-button.textbox-group-btn-right ::ng-deep button:focus-visible{outline-color:transparent}.open .textbox-group ec-textbox{--ec-form-control-box-shadow-focus: none;--ec-form-control-border-color-focus: var(--ec-form-control-border-color)}.open .textbox-group ec-button{--ec-button-box-shadow-focus-secondary: none;--ec-button-background-color-secondary: var(--ec-background-color-selected)}.add-custom-option{display:flex;align-items:center;padding:.5rem .75rem;cursor:pointer;border-top:1px solid var(--ec-form-control-border-color, #ccc);color:var(--ec-color-text);font-size:.875rem}.add-custom-option:hover{background-color:var(--ec-color-background-hover, #f5f5f5)}.add-custom-option .label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}footer{padding:.5rem;border-top:1px solid var(--ec-border-color);color:var(--ec-color-hint-dark);font-size:var(--ec-font-size-label);text-align:right;line-height:1}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "lockButton", "icon", "iconColor", "label", "ariaLabel", "ariaExpanded", "ariaHaspopup", "ariaActivedescendant", "ariaControls", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: ViewOverlayComponent, selector: "[ecOverlay]", inputs: ["status", "message", "action", "noDataTemplate", "displayAsMask", "overlayClassList"] }, { kind: "component", type: MenuComponent, selector: "ec-menu", inputs: ["id", "items", "selected", "parent", "templateType", "customMenuTemplate", "title", "showNoItems", "noDataText", "enableKeyNav", "rolePattern", "highlightedItem", "maintainSelectedItem", "truncateItems", "preserveIconSpace", "dropdownToggleButton"], outputs: ["selectedChanged", "highlightedItemChange", "menuClosed"] }, { kind: "directive", type: PopupContainerDirective, selector: "[ecPopup]", inputs: ["ecPopup", "options"] }, { kind: "component", type: CheckboxComponent, selector: "ec-checkbox", inputs: ["name", "icon", "dependentCheckboxesGroup", "ignoreDisabledDependents"] }, { kind: "component", type: TagsComponent, selector: "ec-tags", inputs: ["id", "tags", "wrap", "isCondensed", "isSubtle", "highlightText", "highlightNormalizePattern"], outputs: ["tagClosed"] }, { kind: "component", type: HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] }); }
9655
9734
  }
9656
9735
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MultiselectComponent, decorators: [{
9657
9736
  type: Component,
9658
- args: [{ selector: 'ec-multiselect', standalone: false, template: "<div class=\"control control-label-{{labelPosition}}\"\n [ngClass]=\"{'invalid': formModel.touched && formModel.invalid,\n 'is-readonly': readonly,\n 'is-disabled': formModel.disabled}\">\n\n @if (label) {\n <label [attr.id]=\"id + '_label'\" [attr.for]=\"id + '_filter'\">\n <span>{{label | translate}}</span>\n @if (validationErrors.length > 0 && formModel.touched && formModel.invalid) {\n <span>&nbsp;{{validationErrors}}</span>\n }\n @if (helpPopover) {\n <ec-help-popover id=\"{{id}}_helpPopover\"\n class=\"d-inline-block my-n3 mx-n1\"\n text=\"{{helpPopover | translate}}\"\n contentPosition=\"{{helpPopoverPosition}}\">\n </ec-help-popover>\n }\n </label>\n }\n\n <div class=\"textbox-group control-input\"\n *ecPopup=\"dropdownmenu\">\n <div class=\"multiselect-input\"\n [attr.id]=\"id + '_input_container'\"\n role=\"combobox\"\n [attr.aria-expanded]=\"menuStatus === 'visible'\"\n aria-haspopup=\"listbox\"\n [attr.aria-owns]=\"id + '_menu_list'\"\n [class.is-focused]=\"menuStatus === 'visible'\"\n [class.is-disabled]=\"formModel.disabled\"\n [class.is-empty]=\"selectedItems.length === 0\"\n [class.is-required]=\"required\"\n [class.has-selections]=\"selectedItems.length > 0\"\n (click)=\"toggleMenu($event)\">\n\n <!-- Selected tags -->\n @if (selectedTags.length > 0) {\n <ec-tags\n id=\"{{id}}_tags\"\n [tags]=\"selectedTags\"\n [wrap]=\"true\"\n [isCondensed]=\"false\"\n [isSubtle]=\"true\"\n (tagClosed)=\"removeTag($event)\"\n (click)=\"$event.stopPropagation()\">\n </ec-tags>\n }\n\n <!-- Filter input -->\n <input\n #filterInput\n class=\"multiselect-filter-input\"\n type=\"text\"\n [id]=\"id + '_filter'\"\n [formControl]=\"filterFormModel\"\n [placeholder]=\"effectivePlaceholder\"\n [tabindex]=\"tabindex\"\n (input)=\"onFilterInput()\"\n (keydown)=\"keyNavigate($event)\"\n (focusout)=\"onBlur()\"\n (click)=\"menuStatus === 'visible' ? $event.stopPropagation() : null\"\n autocomplete=\"off\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"menuStatus === 'visible' ? id + '_menu_list' : null\"\n [attr.aria-activedescendant]=\"activeDescendantId\"\n [attr.aria-labelledby]=\"label ? id + '_label' : null\"\n [attr.aria-label]=\"!label ? effectivePlaceholder : null\"\n [attr.aria-describedby]=\"selectedItems.length > 0 ? id + '_selection_status' : null\" />\n\n <i class=\"ec-icon icon-required\"></i>\n <i class=\"ec-icon icon-invalid\"></i>\n </div>\n\n <!-- Live region for selection announcements -->\n <span [id]=\"id + '_selection_status'\"\n class=\"sr-only\"\n aria-live=\"polite\"\n aria-atomic=\"true\">\n {{ 'Multiselect_LiveRegion_Status_SC' | translate:{ count: selectedItems.length } }}\n </span>\n\n <!-- Clear button -->\n @if (selectedItems.length > 0 && !formModel.disabled && !readonly) {\n <ec-button class=\"multiselect-clear-btn\"\n [id]=\"id + '_clear'\"\n icon=\"icon-cancel\"\n type=\"secondary\"\n [tabindex]=\"0\"\n attr.aria-label=\"{{'ClearAllSelections_SC' | translate}}\"\n (click)=\"clearAll(); $event.stopPropagation()\">\n </ec-button>\n }\n\n <!-- Toggle button -->\n <ec-button class=\"textbox-group-btn-right\"\n [id]=\"id + '_button'\"\n [disabled]=\"formModel.disabled\"\n icon=\"icon-caret-down\"\n [tabindex]=\"0\"\n type=\"secondary\"\n [attr.aria-label]=\"'Toggle dropdown'\"\n [attr.aria-expanded]=\"menuStatus === 'visible'\"\n (click)=\"toggleMenu($event)\"\n [class.active]=\"menuStatus === 'visible'\">\n </ec-button>\n </div>\n</div>\n\n<ng-template #dropdownmenu>\n <div class=\"popup\"\n ecOverlay\n role=\"listbox\"\n [attr.id]=\"id + '_listbox'\"\n [attr.aria-label]=\"label ? (label | translate) : effectivePlaceholder\"\n aria-multiselectable=\"true\"\n [status]=\"pending ? 'pending' : 'hasData'\">\n\n <ec-menu id=\"{{id}}_menu\"\n [class.border-top-0]=\"!filteredOptions.length && hideNoMatches && !showAddCustomOption\"\n [templateType]=\"'checkAndLabel'\"\n [customMenuTemplate]=\"checkboxMenuTemplate\"\n [showNoItems]=\"!hideNoMatches && !showAddCustomOption\"\n [noDataText]=\"noMatchesText\"\n [items]=\"filteredOptions\"\n [selected]=\"highlightedItem\"\n (selectedChanged)=\"onItemSelected($event)\"\n [truncateItems]=\"truncateItems\"\n [maintainSelectedItem]=\"false\">\n </ec-menu>\n\n @if (showAddCustomOption) {\n <div class=\"add-custom-option\"\n role=\"option\"\n attr.aria-label=\"{{'AddCustomItem_TC' | translate:{ customItem: filterFormModel.value } }}\"\n tabindex=\"-1\"\n (click)=\"addCustomItem()\">\n <i class=\"ec-icon icon-plus pr-2\" aria-hidden=\"true\"></i>\n <span class=\"label\">{{ 'AddCustomItem_TC' | translate:{ customItem: filterFormModel.value } }}</span>\n </div>\n }\n </div>\n</ng-template>\n\n<!-- Custom checkbox menu item template -->\n<ng-template #checkboxMenuTemplate let-item>\n <div class=\"d-flex\"\n role=\"option\"\n [attr.aria-selected]=\"!!item.checked\"\n [attr.aria-label]=\"item.label\">\n @if (item === selectAllItem) {\n <ec-checkbox\n id=\"{{id}}_selectAll_checkbox\"\n class=\"m-0 pr-3\"\n [formModel]=\"selectAllFormControl\"\n [dependentCheckboxesGroup]=\"selectAllDependentGroup\"\n [label]=\"item.label\"\n (click)=\"$event.stopPropagation()\">\n </ec-checkbox>\n } @else {\n @if (item.display !== 'heading' && item.display !== 'heading-divided-section') {\n <ec-checkbox\n id=\"{{item.id || id + '_checkbox_' + item.label}}\"\n class=\"m-0 pr-3\"\n [formModel]=\"getCheckboxFormControl(item)\"\n [attr.aria-label]=\"item.label\"\n [label]=\"item.label\"\n [icon]=\"item.icon\"\n (click)=\"$event.stopPropagation()\">\n </ec-checkbox>\n } @else {\n <span>{{item.label}}</span>\n }\n }\n </div>\n</ng-template>\n", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:hover:not(:disabled):not(:focus),:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:hover:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:hover:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:2px solid transparent;outline-offset:2px}:host textarea:focus-visible,:host input:focus-visible,:host select:focus-visible{outline-color:var(--ec-border-color-focus)}:host .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.control.invalid .multiselect-input{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid)}.control.invalid .multiselect-input.is-focused{border-color:var(--ec-form-control-background-color-invalid)}.control.invalid .multiselect-input .icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}.control.invalid .multiselect-input .icon-required{display:none}.control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}.control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}.control.invalid:not(.open) .multiselect-clear-btn ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}.control.invalid:not(.open) .multiselect-clear-btn ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}.control.invalid:not(.open) .textbox-group:hover .multiselect-input:not(.is-focused){border-color:var(--ec-form-control-border-color-hover)}.control.invalid:not(.open) .textbox-group:hover .multiselect-clear-btn ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-hover)}.control.invalid:not(.open) .textbox-group:hover .textbox-group-btn-right ::ng-deep button:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}.control{position:relative}.control.is-disabled:not(.is-readonly) .multiselect-input{opacity:var(--ec-form-control-opacity-disabled);background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);pointer-events:none}.control.is-readonly .multiselect-input{border-right:1px solid var(--ec-form-control-border-color-readonly);border-top-right-radius:var(--ec-border-radius);border-bottom-right-radius:var(--ec-border-radius);background-color:var(--ec-form-control-background-color-readonly);border-color:var(--ec-form-control-border-color-readonly);color:var(--ec-form-control-color-readonly);cursor:default}.control.is-readonly .multiselect-input .multiselect-filter-input{color:var(--ec-form-control-color-readonly)}.control.is-readonly .multiselect-input .multiselect-filter-input::placeholder{color:var(--ec-form-control-color-readonly)}.control.is-readonly ec-button{display:none}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover .multiselect-input:not(.is-focused){border-color:var(--ec-form-control-border-color-hover)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover .multiselect-clear-btn{--ec-button-border-color-secondary: var(--ec-form-control-border-color-hover)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover ec-button.textbox-group-btn-right{--ec-button-border-color-secondary: var(--ec-form-control-border-color-hover)}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}.textbox-group{align-items:stretch}.multiselect-input{display:flex;flex-wrap:wrap;align-items:center;min-height:2rem;max-height:6rem;overflow-y:auto;padding:0 .5rem;background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-top-left-radius:var(--ec-border-radius);border-bottom-left-radius:var(--ec-border-radius);border-right:0;cursor:text;flex:1 1;box-sizing:border-box;position:relative}.multiselect-input .icon-required,.multiselect-input .icon-invalid{display:none;color:var(--ec-form-control-border-color-invalid)}.multiselect-input.is-required.is-empty{padding-left:1.75rem}.multiselect-input.is-required.is-empty .icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}.multiselect-input.is-focused{border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);z-index:1}.multiselect-filter-input{border:0;outline:none;background:transparent;flex:1 1 100%;min-width:4rem;height:1.625rem;padding:0;font-size:var(--ec-form-control-font-size);color:var(--ec-form-control-color);line-height:1.25rem;overflow:hidden;text-overflow:ellipsis}.multiselect-filter-input::placeholder{color:var(--ec-form-control-color-placeholder);text-overflow:ellipsis}.has-selections:not(.is-focused) .multiselect-filter-input{width:0;min-width:0;flex:0 0 0;height:0;overflow:hidden;padding:0;margin:0}.popup{background-color:var(--ec-background-color);border-radius:var(--ec-border-radius-card);box-shadow:var(--ec-box-shadow-overlay);margin-top:.25rem;overflow:hidden;z-index:var(--ec-z-index-popup)}ec-menu{display:block}ec-menu ::ng-deep ul{max-height:30vh}ec-menu ::ng-deep ul li{white-space:nowrap}ec-menu ::ng-deep ul li.is-checked .icon-check{opacity:1;color:var(--ec-color-interactive)}ec-menu ::ng-deep ul li.select-all-item{font-weight:600}.multiselect-clear-btn{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-border-color-secondary-focus: var(--ec-form-control-border-color);--ec-button-color-icon-secondary: var(--ec-color-icon)}.multiselect-clear-btn ::ng-deep button{height:100%;border-left:0;border-right:0;border-radius:0;padding:0 .375rem}.multiselect-clear-btn ::ng-deep button:hover{background-color:var(--ec-background-color-hover)}.multiselect-clear-btn ::ng-deep button .ec-icon{font-size:.75rem}ec-button.textbox-group-btn-right{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-border-color-secondary-focus: var(--ec-form-control-border-color);--ec-button-color-icon-secondary: var(--ec-color-icon)}ec-button.textbox-group-btn-right ::ng-deep button{height:100%;border-top-right-radius:var(--ec-border-radius);border-bottom-right-radius:var(--ec-border-radius)}.open .textbox-group ec-textbox{--ec-form-control-box-shadow-focus: none;--ec-form-control-border-color-focus: var(--ec-form-control-border-color)}.open .textbox-group ec-button{--ec-button-box-shadow-focus-secondary: none;--ec-button-background-color-secondary: var(--ec-background-color-selected)}.add-custom-option{display:flex;align-items:center;padding:.5rem .75rem;cursor:pointer;border-top:1px solid var(--ec-form-control-border-color, #ccc);color:var(--ec-color-text);font-size:.875rem}.add-custom-option:hover{background-color:var(--ec-color-background-hover, #f5f5f5)}.add-custom-option .label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
9737
+ args: [{ selector: 'ec-multiselect', standalone: false, template: "<div class=\"control control-label-{{labelPosition}}\"\n [ngClass]=\"{'invalid': formModel.touched && formModel.invalid,\n 'is-readonly': readonly,\n 'is-disabled': formModel.disabled,\n 'open': menuStatus === 'visible'}\">\n\n @if (label) {\n <label [attr.id]=\"id + '_label'\" [attr.for]=\"id + '_filter'\">\n <span>{{label | translate}}</span>\n @if (validationErrors.length > 0 && formModel.touched && formModel.invalid) {\n <span>&nbsp;{{validationErrors}}</span>\n }\n @if (helpPopover) {\n <ec-help-popover id=\"{{id}}_helpPopover\"\n class=\"d-inline-block my-n3 mx-n1\"\n text=\"{{helpPopover | translate}}\"\n contentPosition=\"{{helpPopoverPosition}}\">\n </ec-help-popover>\n }\n </label>\n }\n\n <div class=\"textbox-group control-input\"\n *ecPopup=\"dropdownmenu\">\n <div class=\"multiselect-input\"\n [attr.id]=\"id + '_input_container'\"\n role=\"combobox\"\n [attr.aria-expanded]=\"menuStatus === 'visible'\"\n aria-haspopup=\"listbox\"\n [attr.aria-owns]=\"id + '_menu_list'\"\n [class.is-focused]=\"menuStatus === 'visible'\"\n [class.is-disabled]=\"formModel.disabled\"\n [class.is-empty]=\"selectedItems.length === 0\"\n [class.is-required]=\"required\"\n [class.has-selections]=\"selectedItems.length > 0\"\n (click)=\"toggleMenu($event)\">\n\n <!-- Selected tags -->\n @if (selectedTags.length > 0) {\n <ec-tags\n id=\"{{id}}_tags\"\n [tags]=\"selectedTags\"\n [wrap]=\"true\"\n [isCondensed]=\"false\"\n [isSubtle]=\"true\"\n (tagClosed)=\"removeTag($event)\"\n (click)=\"$event.stopPropagation()\">\n </ec-tags>\n }\n\n <!-- Filter input -->\n <input\n #filterInput\n class=\"multiselect-filter-input\"\n type=\"text\"\n [id]=\"id + '_filter'\"\n [formControl]=\"filterFormModel\"\n [placeholder]=\"effectivePlaceholder\"\n [tabindex]=\"tabindex\"\n (input)=\"onFilterInput()\"\n (keydown)=\"keyNavigate($event)\"\n (focusout)=\"onBlur()\"\n (click)=\"menuStatus === 'visible' ? $event.stopPropagation() : null\"\n autocomplete=\"off\"\n [attr.cdkFocusInitial]=\"autofocus || null\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"menuStatus === 'visible' ? id + '_menu_list' : null\"\n [attr.aria-activedescendant]=\"activeDescendantId\"\n [attr.aria-labelledby]=\"label ? id + '_label' : null\"\n [attr.aria-label]=\"!label ? effectivePlaceholder : null\"\n [attr.aria-describedby]=\"selectedItems.length > 0 ? id + '_selection_status' : null\" />\n\n <i class=\"ec-icon icon-required\"></i>\n <i class=\"ec-icon icon-invalid\"></i>\n </div>\n\n <!-- Live region for selection announcements -->\n <span [id]=\"id + '_selection_status'\"\n class=\"sr-only\"\n aria-live=\"polite\"\n aria-atomic=\"true\">\n {{ 'Multiselect_LiveRegion_Status_SC' | translate:{ count: selectedItems.length } }}\n </span>\n\n <!-- Clear button -->\n @if (selectedItems.length > 0 && !formModel.disabled && !readonly) {\n <ec-button class=\"multiselect-clear-btn\"\n [id]=\"id + '_clear'\"\n icon=\"icon-cancel\"\n type=\"secondary\"\n [tabindex]=\"0\"\n attr.aria-label=\"{{'ClearAllSelections_SC' | translate}}\"\n (click)=\"clearAll(); $event.stopPropagation()\">\n </ec-button>\n }\n\n <!-- Toggle button -->\n <ec-button class=\"textbox-group-btn-right\"\n [id]=\"id + '_button'\"\n [disabled]=\"formModel.disabled\"\n icon=\"icon-caret-down\"\n [tabindex]=\"-1\"\n type=\"secondary\"\n [attr.aria-label]=\"'Toggle dropdown'\"\n [attr.aria-expanded]=\"menuStatus === 'visible'\"\n (click)=\"toggleMenu($event)\"\n [class.active]=\"menuStatus === 'visible'\">\n </ec-button>\n </div>\n</div>\n\n<ng-template #dropdownmenu>\n <div class=\"popup\"\n ecOverlay\n role=\"listbox\"\n [attr.id]=\"id + '_listbox'\"\n [attr.aria-label]=\"label ? (label | translate) : effectivePlaceholder\"\n aria-multiselectable=\"true\"\n [status]=\"pending ? 'pending' : 'hasData'\">\n\n <ec-menu id=\"{{id}}_menu\"\n [class.border-top-0]=\"!filteredOptions.length && hideNoMatches && !showAddCustomOption\"\n [templateType]=\"'checkAndLabel'\"\n [customMenuTemplate]=\"checkboxMenuTemplate\"\n [showNoItems]=\"!hideNoMatches && !showAddCustomOption\"\n [noDataText]=\"noMatchesText\"\n [items]=\"filteredOptions\"\n [selected]=\"highlightedItem\"\n (selectedChanged)=\"onItemSelected($event)\"\n [truncateItems]=\"truncateItems\"\n [maintainSelectedItem]=\"false\">\n </ec-menu>\n\n @if (showAddCustomOption) {\n <div class=\"add-custom-option\"\n role=\"option\"\n attr.aria-label=\"{{'AddCustomItem_TC' | translate:{ customItem: filterFormModel.value } }}\"\n tabindex=\"-1\"\n (click)=\"addCustomItem()\">\n <i class=\"ec-icon icon-plus pr-2\" aria-hidden=\"true\"></i>\n <span class=\"label\">{{ 'AddCustomItem_TC' | translate:{ customItem: filterFormModel.value } }}</span>\n </div>\n }\n\n @if (showTotalRecordsFooter) {\n <footer [attr.id]=\"id + '_footer'\">\n <span>{{visibleOptionCount}} {{'of' | translate}} {{totalRecords}}</span>\n </footer>\n }\n </div>\n</ng-template>\n\n<!-- Custom checkbox menu item template -->\n<ng-template #checkboxMenuTemplate let-item>\n <div class=\"multiselect-item-row d-flex\"\n role=\"option\"\n [attr.aria-selected]=\"!!item.checked\"\n [attr.aria-label]=\"item.label\">\n @if (item === selectAllItem) {\n <ec-checkbox\n id=\"{{id}}_selectAll_checkbox\"\n class=\"m-0 pr-3\"\n [formModel]=\"selectAllFormControl\"\n [dependentCheckboxesGroup]=\"selectAllDependentGroup\"\n [label]=\"item.label\"\n (click)=\"$event.stopPropagation()\">\n </ec-checkbox>\n } @else {\n @if (item.display !== 'heading' && item.display !== 'heading-divided-section') {\n <!-- The checkbox is always ours; with a custom template it renders bare and the host owns the rest of the row. -->\n <ec-checkbox\n id=\"{{item.id || id + '_checkbox_' + item.label}}\"\n class=\"m-0\"\n [class.pr-3]=\"!customMenuTemplate\"\n [class.w-auto]=\"!!customMenuTemplate\"\n [formModel]=\"getCheckboxFormControl(item)\"\n [attr.aria-label]=\"item.label\"\n [label]=\"customMenuTemplate ? undefined : item.label\"\n [icon]=\"customMenuTemplate ? undefined : item.icon\"\n (click)=\"$event.stopPropagation()\">\n </ec-checkbox>\n @if (customMenuTemplate) {\n <!-- Host-owned row content. Clicks here bubble to the row and toggle the item unless the host stops them. -->\n <div class=\"multiselect-item-content\"\n [attr.id]=\"(item.id || id + '_checkbox_' + item.label) + '_content'\">\n <ng-container *ngTemplateOutlet=\"customMenuTemplate; context: { $implicit: item }\"></ng-container>\n </div>\n }\n } @else {\n <span>{{item.label}}</span>\n }\n }\n </div>\n</ng-template>\n", styles: [":host{color:var(--ec-form-control-color);font-size:var(--ec-form-control-font-size);display:block;margin-bottom:1rem;width:100%}:host :host-context(.form-condensed){margin-bottom:.5rem}:host .control{width:100%;display:flex;flex-direction:column}:host .control.control-label-bottom{flex-direction:column-reverse}:host .control.control-label-left{flex-direction:row}:host .control.control-label-left label{margin-right:.25rem}:host .control.control-label-right{flex-direction:row-reverse}:host .control.control-label-right label{margin-left:.25rem}:host .control.control-label-left,:host .control.control-label-right{align-items:center}:host .control.control-label-left label,:host .control.control-label-right label{flex:1 1;margin-top:0;margin-bottom:0}:host .control.control-label-left .control-input,:host .control.control-label-right .control-input{flex:2 2}:host .control.is-readonly input,:host .control.is-readonly select,:host .control.is-readonly textarea{border-color:var(--ec-form-control-border-color-readonly);background-color:var(--ec-form-control-background-color-readonly);background-clip:border-box;background-image:none;color:var(--ec-form-control-color-readonly);opacity:1;-webkit-user-select:none;user-select:none;pointer-events:none;overflow:hidden;white-space:nowrap}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:focus,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:focus{border-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid:hover:not(:disabled):not(:focus),:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid:hover:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid{background-repeat:no-repeat;background-position:.5rem center;background-size:1rem,1rem;padding-left:1.75rem;background-image:none}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-invalid,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-invalid~.icon-required,:host .control.invalid .textbox-group-input ::ng-deep .control input.ng-valid~.icon-required{display:none}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}:host .control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:hover:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}:host .textbox-group{display:flex;position:relative}:host textarea:focus,:host input:focus,:host select:focus{outline:2px solid transparent;outline-offset:2px}:host textarea:focus-visible,:host input:focus-visible,:host select:focus-visible{outline-color:var(--ec-border-color-focus)}:host .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.control.invalid .multiselect-input{background-color:var(--ec-form-control-background-color-invalid);border-color:var(--ec-form-control-border-color-invalid)}.control.invalid .multiselect-input:focus-within:not(.is-focused){border-color:var(--ec-form-control-background-color-invalid)}.control.invalid .multiselect-input .icon-invalid{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}.control.invalid .multiselect-input .icon-required{display:none}.control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}.control.invalid:not(.open) .textbox-group-btn-right ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}.control.invalid:not(.open) .multiselect-clear-btn ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-invalid)}.control.invalid:not(.open) .multiselect-clear-btn ::ng-deep button{background-color:var(--ec-form-control-background-color-invalid)}.control.invalid:not(.open) .textbox-group:hover .multiselect-input:not(.is-focused):not(:focus-within){border-color:var(--ec-form-control-border-color-hover)}.control.invalid:not(.open) .textbox-group:hover .multiselect-clear-btn ::ng-deep button:not(:focus){border-color:var(--ec-form-control-border-color-hover)}.control.invalid:not(.open) .textbox-group:hover .textbox-group-btn-right ::ng-deep button:not(:disabled):not(:focus){border-color:var(--ec-form-control-border-color-hover)}.control{position:relative}.control.is-disabled:not(.is-readonly) .multiselect-input{opacity:var(--ec-form-control-opacity-disabled);background-color:var(--ec-form-control-background-color-disabled);border-color:var(--ec-form-control-border-color-disabled);pointer-events:none}.control.is-readonly .multiselect-input{border-right:1px solid var(--ec-form-control-border-color-readonly);border-top-right-radius:var(--ec-border-radius);border-bottom-right-radius:var(--ec-border-radius);background-color:var(--ec-form-control-background-color-readonly);border-color:var(--ec-form-control-border-color-readonly);color:var(--ec-form-control-color-readonly);cursor:default}.control.is-readonly .multiselect-input .multiselect-filter-input{color:var(--ec-form-control-color-readonly)}.control.is-readonly .multiselect-input .multiselect-filter-input::placeholder{color:var(--ec-form-control-color-readonly)}.control.is-readonly ec-button{display:none}.control.open .textbox-group ec-button.multiselect-clear-btn{--ec-button-background-color-secondary: var(--ec-form-control-background-color)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover .multiselect-input:not(.is-focused):not(:focus-within){border-color:var(--ec-form-control-border-color-hover)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover .multiselect-clear-btn{--ec-button-border-color-secondary: var(--ec-form-control-border-color-hover)}.control:not(.is-disabled):not(.is-readonly) .textbox-group:hover ec-button.textbox-group-btn-right{--ec-button-border-color-secondary: var(--ec-form-control-border-color-hover)}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}.textbox-group{align-items:stretch}.multiselect-input{display:flex;flex-wrap:wrap;align-items:center;min-height:2rem;max-height:6rem;overflow-y:auto;padding:0 .5rem;background-color:var(--ec-form-control-background-color);border:1px solid var(--ec-form-control-border-color);border-top-left-radius:var(--ec-border-radius);border-bottom-left-radius:var(--ec-border-radius);border-right:0;cursor:text;flex:1 1;box-sizing:border-box;position:relative}.multiselect-input .icon-required,.multiselect-input .icon-invalid{display:none;color:var(--ec-form-control-border-color-invalid)}.multiselect-input.is-required.is-empty{padding-left:1.75rem}.multiselect-input.is-required.is-empty .icon-required{display:inline-flex;position:absolute;left:.5rem;top:.5rem;z-index:1}.multiselect-input:focus-within:not(.is-focused){border-color:var(--ec-form-control-border-color-focus);box-shadow:var(--ec-form-control-box-shadow-focus);outline:2px solid transparent;outline-offset:2px;position:relative;z-index:1;border-right:1px solid var(--ec-form-control-border-color-focus)}.multiselect-input.is-focused{border-right:1px solid var(--ec-form-control-border-color);z-index:1}.multiselect-filter-input{border:0;outline:none;background:transparent}.multiselect-input .multiselect-filter-input:focus,.multiselect-input .multiselect-filter-input:focus-visible{outline:none;box-shadow:none}.multiselect-filter-input{flex:1 1 100%;min-width:4rem;height:1.625rem;padding:0;font-size:var(--ec-form-control-font-size);color:var(--ec-form-control-color);line-height:1.25rem;overflow:hidden;text-overflow:ellipsis}.multiselect-filter-input::placeholder{color:var(--ec-form-control-color-placeholder);text-overflow:ellipsis}.has-selections:not(.is-focused) .multiselect-filter-input{width:0;min-width:0;flex:0 0 0;height:0;overflow:hidden;padding:0;margin:0}.popup{background-color:var(--ec-background-color);border-radius:var(--ec-border-radius-card);box-shadow:var(--ec-box-shadow-overlay);margin-top:.25rem;overflow:hidden;z-index:var(--ec-z-index-popup)}ec-menu{display:block}ec-menu ::ng-deep ul{max-height:30vh}ec-menu ::ng-deep ul li{white-space:nowrap}ec-menu ::ng-deep ul li.is-checked .icon-check{opacity:1;color:var(--ec-color-interactive)}ec-menu ::ng-deep ul li.select-all-item{font-weight:600}ec-menu ::ng-deep ul li .multiselect-item-row{flex:1 1 auto;align-items:center;min-width:0}ec-menu ::ng-deep ul li .multiselect-item-content{display:flex;align-items:center;flex:1 1 auto;min-width:0;margin-left:.5rem}ec-menu ::ng-deep ul li .multiselect-item-hover-only{opacity:0;transition:opacity .1s ease-in-out}ec-menu ::ng-deep ul li:hover .multiselect-item-hover-only,ec-menu ::ng-deep ul li.is-highlighted .multiselect-item-hover-only,ec-menu ::ng-deep ul li .multiselect-item-hover-only:focus-within{opacity:1}.multiselect-clear-btn{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-border-color-secondary-focus: transparent;--ec-button-color-icon-secondary: var(--ec-color-icon)}.multiselect-clear-btn ::ng-deep button{height:100%;border-left:0;border-right:0;border-radius:0;padding:0 .375rem}.multiselect-clear-btn ::ng-deep button:hover{background-color:var(--ec-background-color-hover)}.multiselect-clear-btn ::ng-deep button:focus-visible{outline-color:transparent}.multiselect-clear-btn ::ng-deep button .ec-icon{font-size:.75rem}ec-button.textbox-group-btn-right{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-border-color-secondary-focus: var(--ec-form-control-border-color);--ec-button-box-shadow-focus-secondary: none;--ec-button-color-icon-secondary: var(--ec-color-icon)}ec-button.textbox-group-btn-right ::ng-deep button{height:100%;border-top-right-radius:var(--ec-border-radius);border-bottom-right-radius:var(--ec-border-radius)}ec-button.textbox-group-btn-right ::ng-deep button:focus-visible{outline-color:transparent}.open .textbox-group ec-textbox{--ec-form-control-box-shadow-focus: none;--ec-form-control-border-color-focus: var(--ec-form-control-border-color)}.open .textbox-group ec-button{--ec-button-box-shadow-focus-secondary: none;--ec-button-background-color-secondary: var(--ec-background-color-selected)}.add-custom-option{display:flex;align-items:center;padding:.5rem .75rem;cursor:pointer;border-top:1px solid var(--ec-form-control-border-color, #ccc);color:var(--ec-color-text);font-size:.875rem}.add-custom-option:hover{background-color:var(--ec-color-background-hover, #f5f5f5)}.add-custom-option .label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}footer{padding:.5rem;border-top:1px solid var(--ec-border-color);color:var(--ec-color-hint-dark);font-size:var(--ec-font-size-label);text-align:right;line-height:1}\n"] }]
9659
9738
  }], ctorParameters: () => [{ type: ValidationMessageService }, { type: FormGroupHelper }, { type: i3.TranslateService }, { type: ScrollService }], propDecorators: { onResize: [{
9660
9739
  type: HostListener,
9661
9740
  args: ['window:resize']
@@ -9679,6 +9758,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
9679
9758
  type: Input
9680
9759
  }], maxSelections: [{
9681
9760
  type: Input
9761
+ }], totalRecords: [{
9762
+ type: Input
9763
+ }], showSelectAll: [{
9764
+ type: Input
9765
+ }], customMenuTemplate: [{
9766
+ type: Input
9682
9767
  }], search: [{
9683
9768
  type: Output
9684
9769
  }], selectionChanged: [{