@flywheel-io/vision 21.5.0 → 21.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3508,11 +3508,11 @@ class FwMenuContainerComponent {
3508
3508
  this.keyHandler = input(undefined, ...(ngDevMode ? [{ debugName: "keyHandler" }] : /* istanbul ignore next */ []));
3509
3509
  effect(() => {
3510
3510
  const filter = this.filterText();
3511
+ // combinedMenuItems() is read here (rather than only inside onFilterChange) so this effect
3512
+ // re-runs once contentChildren resolves, which happens a beat later than initial render
3513
+ // when this component is rendered inside a CdkMenuTrigger/CDK-overlay-portaled template.
3514
+ this.combinedMenuItems();
3511
3515
  untracked(() => this.onFilterChange(filter));
3512
- const allMenuItems = this.combinedMenuItems();
3513
- allMenuItems.forEach((menuItem) => {
3514
- menuItem.hidden.set(!this.filteredMenuItems.includes(menuItem));
3515
- });
3516
3516
  });
3517
3517
  }
3518
3518
  ngAfterViewInit() {
@@ -3572,6 +3572,9 @@ class FwMenuContainerComponent {
3572
3572
  this.filterChanged.emit(filter);
3573
3573
  const filterFn = this.filterFn();
3574
3574
  this.filteredMenuItems = filterFn(filter, allMenuItems);
3575
+ allMenuItems.forEach((menuItem) => {
3576
+ menuItem.hidden.set(!this.filteredMenuItems.includes(menuItem));
3577
+ });
3575
3578
  // Hide separators whenever a filter is active
3576
3579
  const isFiltering = Boolean(filter && filter.trim() !== '');
3577
3580
  [...this.childSeparators(), ...this.additionalSeparators()].forEach((separator) => {
@@ -10654,6 +10657,33 @@ class FwTypeaheadComponent {
10654
10657
  * @default "No results found"
10655
10658
  */
10656
10659
  this.emptyText = input('No results found', ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
10660
+ /**
10661
+ * Text to display in place of the options list once no more options can be selected or added, i.e. when
10662
+ * `allowNew` is false and either every option is in `optionsNotAllowed` or every option is already selected.
10663
+ * @default "No options available"
10664
+ */
10665
+ this.exhaustedText = input('No options available', ...(ngDevMode ? [{ debugName: "exhaustedText" }] : /* istanbul ignore next */ []));
10666
+ /**
10667
+ * Values that cannot be selected or added, whether they come from `options` or are typed as a new value.
10668
+ * Matching is case-insensitive.
10669
+ * @default []
10670
+ */
10671
+ this.optionsNotAllowed = input([], ...(ngDevMode ? [{ debugName: "optionsNotAllowed" }] : /* istanbul ignore next */ []));
10672
+ /**
10673
+ * Called with a new (not-yet-existing) value before it's added, to allow rejecting it. Has no effect on
10674
+ * values that already exist in `options`.
10675
+ */
10676
+ this.onValidateNewOption = input(...(ngDevMode ? [undefined, { debugName: "onValidateNewOption" }] : /* istanbul ignore next */ []));
10677
+ /**
10678
+ * Label shown next to a new value that can be added
10679
+ * @default "New"
10680
+ */
10681
+ this.optionNewLabel = input('New', ...(ngDevMode ? [{ debugName: "optionNewLabel" }] : /* istanbul ignore next */ []));
10682
+ /**
10683
+ * Label shown next to an option or new value that's disallowed via `optionsNotAllowed` or `onValidateNewOption`
10684
+ * @default "Not Allowed"
10685
+ */
10686
+ this.optionNotAllowedLabel = input('Not Allowed', ...(ngDevMode ? [{ debugName: "optionNotAllowedLabel" }] : /* istanbul ignore next */ []));
10657
10687
  this.onChange = (_) => { };
10658
10688
  this.onTouched = () => {
10659
10689
  this.touched.set(true);
@@ -10728,13 +10758,55 @@ class FwTypeaheadComponent {
10728
10758
  const alreadySelected = Boolean(this.value()?.find((val) => val.toLowerCase() === newValue.toLowerCase()));
10729
10759
  return this.allowNew() && !alreadySelected && (!directMatch || loading);
10730
10760
  }, ...(ngDevMode ? [{ debugName: "displayNewOption" }] : /* istanbul ignore next */ []));
10761
+ this.isOptionNotAllowed = (optionValue) => {
10762
+ return this.optionsNotAllowed().some((notAllowed) => notAllowed.toLowerCase() === optionValue.toLowerCase());
10763
+ };
10764
+ /**
10765
+ * Whether the currently typed searchValue is allowed to be added as a new value, per `onValidateNewOption`
10766
+ * and `optionsNotAllowed`. Only meaningful while `displayNewOption()` is true.
10767
+ */
10768
+ this.newOptionAllowed = computed(() => {
10769
+ const newValue = this.searchValue();
10770
+ const validateNewOption = this.onValidateNewOption();
10771
+ return (!validateNewOption || validateNewOption(newValue)) && !this.isOptionNotAllowed(newValue);
10772
+ }, ...(ngDevMode ? [{ debugName: "newOptionAllowed" }] : /* istanbul ignore next */ []));
10773
+ /**
10774
+ * Whether the new-option row should be shown. It's hidden while other matching options are still displayed,
10775
+ * to avoid distracting from those, and only surfaced once nothing else matches.
10776
+ */
10777
+ this.showNewOption = computed(() => {
10778
+ return this.displayNewOption() && (this.newOptionAllowed() || (this.filteredOptions()?.length ?? 0) === 0);
10779
+ }, ...(ngDevMode ? [{ debugName: "showNewOption" }] : /* istanbul ignore next */ []));
10780
+ this.allOptionsNotAllowed = computed(() => {
10781
+ const options = this.filteredOptions() ?? [];
10782
+ return options.length > 0 && options.every((option) => this.isOptionNotAllowed(option));
10783
+ }, ...(ngDevMode ? [{ debugName: "allOptionsNotAllowed" }] : /* istanbul ignore next */ []));
10784
+ this.allOptionsSelected = computed(() => {
10785
+ const options = this.optionsInput();
10786
+ if (!Array.isArray(options) || options.length === 0) {
10787
+ return false;
10788
+ }
10789
+ return options.every((option) => this.value().some((val) => val.toLowerCase() === option.toLowerCase()));
10790
+ }, ...(ngDevMode ? [{ debugName: "allOptionsSelected" }] : /* istanbul ignore next */ []));
10791
+ /**
10792
+ * True once no more options can be selected or typed in: `allowNew` is false and either every remaining
10793
+ * option is in `optionsNotAllowed`, or every provided option has already been selected.
10794
+ */
10795
+ this.isExhausted = computed(() => !this.allowNew() && (this.allOptionsNotAllowed() || this.allOptionsSelected()), ...(ngDevMode ? [{ debugName: "isExhausted" }] : /* istanbul ignore next */ []));
10731
10796
  this.addValue = (newValue) => {
10797
+ if (this.isOptionNotAllowed(newValue)) {
10798
+ return;
10799
+ }
10732
10800
  const isInOptions = this.filteredOptions()?.includes(newValue);
10733
10801
  const isNewWhileDisallowed = !this.allowNew() && !isInOptions;
10734
10802
  const isDuplicate = this.value().includes(newValue.toLowerCase());
10735
10803
  if (isNewWhileDisallowed || isDuplicate) {
10736
10804
  return;
10737
10805
  }
10806
+ const validateNewOption = this.onValidateNewOption();
10807
+ if (!isInOptions && validateNewOption && !validateNewOption(newValue)) {
10808
+ return;
10809
+ }
10738
10810
  if (this.selectType() === 'single') {
10739
10811
  this.value.set([newValue]);
10740
10812
  this.trigger().close();
@@ -10897,13 +10969,13 @@ class FwTypeaheadComponent {
10897
10969
  newlyFocused.scrollIntoView();
10898
10970
  }
10899
10971
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: FwTypeaheadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10900
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: FwTypeaheadComponent, isStandalone: true, selector: "fw-typeahead", inputs: { loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, optionsInput: { classPropertyName: "optionsInput", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, maxOptionsHeight: { classPropertyName: "maxOptionsHeight", publicName: "maxOptionsHeight", isSignal: true, isRequired: false, transformFunction: null }, minOptionsHeight: { classPropertyName: "minOptionsHeight", publicName: "minOptionsHeight", isSignal: true, isRequired: false, transformFunction: null }, optionsWidth: { classPropertyName: "optionsWidth", publicName: "optionsWidth", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, selectType: { classPropertyName: "selectType", publicName: "selectType", isSignal: true, isRequired: false, transformFunction: null }, searchValue: { classPropertyName: "searchValue", publicName: "searchValue", isSignal: true, isRequired: false, transformFunction: null }, allowNew: { classPropertyName: "allowNew", publicName: "allowNew", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loading: "loadingChange", disabled: "disabledChange", value: "valueChange", searchValue: "searchValueChange" }, host: { listeners: { "document:click": "outsideClick()", "click": "onClick($event)" }, properties: { "class.fw-touched": "touched()" } }, providers: [
10972
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: FwTypeaheadComponent, isStandalone: true, selector: "fw-typeahead", inputs: { loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, exhaustedText: { classPropertyName: "exhaustedText", publicName: "exhaustedText", isSignal: true, isRequired: false, transformFunction: null }, optionsNotAllowed: { classPropertyName: "optionsNotAllowed", publicName: "optionsNotAllowed", isSignal: true, isRequired: false, transformFunction: null }, onValidateNewOption: { classPropertyName: "onValidateNewOption", publicName: "onValidateNewOption", isSignal: true, isRequired: false, transformFunction: null }, optionNewLabel: { classPropertyName: "optionNewLabel", publicName: "optionNewLabel", isSignal: true, isRequired: false, transformFunction: null }, optionNotAllowedLabel: { classPropertyName: "optionNotAllowedLabel", publicName: "optionNotAllowedLabel", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, optionsInput: { classPropertyName: "optionsInput", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, maxOptionsHeight: { classPropertyName: "maxOptionsHeight", publicName: "maxOptionsHeight", isSignal: true, isRequired: false, transformFunction: null }, minOptionsHeight: { classPropertyName: "minOptionsHeight", publicName: "minOptionsHeight", isSignal: true, isRequired: false, transformFunction: null }, optionsWidth: { classPropertyName: "optionsWidth", publicName: "optionsWidth", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, selectType: { classPropertyName: "selectType", publicName: "selectType", isSignal: true, isRequired: false, transformFunction: null }, searchValue: { classPropertyName: "searchValue", publicName: "searchValue", isSignal: true, isRequired: false, transformFunction: null }, allowNew: { classPropertyName: "allowNew", publicName: "allowNew", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loading: "loadingChange", disabled: "disabledChange", value: "valueChange", searchValue: "searchValueChange" }, host: { listeners: { "document:click": "outsideClick()", "click": "onClick($event)" }, properties: { "class.fw-touched": "touched()" } }, providers: [
10901
10973
  {
10902
10974
  provide: NG_VALUE_ACCESSOR,
10903
10975
  useExisting: forwardRef(() => FwTypeaheadComponent),
10904
10976
  multi: true,
10905
10977
  },
10906
- ], viewQueries: [{ propertyName: "trigger", first: true, predicate: CdkMenuTrigger, descendants: true, isSignal: true }, { propertyName: "displayedOptions", predicate: FwMenuItemComponent, descendants: true, isSignal: true }, { propertyName: "inputRef", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"full-container\">\n <div\n class=\"input-container\"\n [class.disabled]=\"disabled()\"\n [style.max-height]=\"maxHeight()\"\n [cdkMenuTriggerFor]=\"menuContent\"\n fwMenuRegister\n #inputContainer>\n @if (selectType() === 'multiple') {\n <fw-chip-list class=\"chips\" [disableOverflow]=\"!!maxHeight()\">\n @for(val of value(); track val) {\n <fw-chip\n color=\"primary\"\n [showClose]=\"true\"\n [title]=\"val\"\n [selectable]=\"false\"\n (close)=\"closeChip(val)\"\n />\n }\n </fw-chip-list>\n }\n <input\n data-testid=\"typeahead-input\"\n [class.highlight-placeholder]=\"highlightPlaceholder()\"\n [placeholder]=\"displayedPlaceholder()\"\n [disabled]=\"disabled()\"\n (input)=\"handleInput($event)\"\n (keydown)=\"handleKey($event)\"\n (blur)=\"onFocusLoss($event)\"\n #input\n type=\"text\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isMenuOpen()\"\n [attr.aria-controls]=\"listboxId\"\n aria-autocomplete=\"list\"\n [attr.aria-activedescendant]=\"getActiveDescendantId()\"\n />\n @if(loading()) {\n <fw-progress-spinner size=\"small\"/>\n }\n @if(selectType() === 'single' && value().length === 1) {\n <fw-icon class=\"clear-icon\" (click)=\"clearValue()\">close</fw-icon>\n }\n </div>\n</div>\n<ng-template #menuContent>\n <fw-menu-container\n [maxHeight]=\"maxOptionsHeight()\"\n [minHeight]=\"minOptionsHeight()\"\n [width]=\"optionsWidth() || inputContainer.offsetWidth - 2 + 'px'\"\n >\n <fw-menu role=\"listbox\" [id]=\"listboxId\" (mousedown)=\"$event.preventDefault()\">\n @if(loading() && !displayNewOption()) {\n <fw-menu-item title=\"Searching...\" [disabled]=\"true\"/>\n } @else if(!loading()) {\n @for (option of filteredOptions(); track option) {\n <fw-menu-item\n (click)=\"handleOptionClick(option)\"\n (mouseenter)=\"setFocusByValue(option)\"\n [title]=\"option\"\n [focused]=\"focusedOption() === option\"\n [value]=\"option\"\n />\n }\n @empty {\n @if (!displayNewOption()) {\n <fw-menu-item [title]=\"emptyText()\" [disabled]=\"true\"/>\n }\n }\n }\n @if(displayNewOption()) {\n <fw-menu-item\n (click)=\"handleOptionClick(searchValue())\"\n (mouseenter)=\"setFocusByValue(searchValue())\"\n [title]=\"searchValue()\"\n [value]=\"searchValue()\"\n [focused]=\"focusedOption() === searchValue()\">\n <p class=\"new-tag\">New</p>\n </fw-menu-item>\n }\n </fw-menu>\n </fw-menu-container>\n</ng-template>\n", styles: [".new-tag{margin:0;color:var(--typography-light)}:host.disabled{cursor:not-allowed}:host.disabled fw-icon{cursor:not-allowed!important}:host{display:flex;flex-direction:column;width:100%;line-height:21px}:host .chips,:host fw-progress-spinner{margin:-4px 0}:host .full-container{display:flex;flex-direction:column;width:100%}:host .highlight-placeholder::placeholder{color:var(--typography-base)!important}:host .clear-icon{cursor:pointer}:host .input-container{width:100%;box-sizing:border-box;color:var(--typography-light);background:var(--page-light);display:flex;padding:8px;row-gap:8px;align-items:center;border-radius:6px;border:1px solid var(--separations-input);font-family:Inter,sans-serif;flex-wrap:wrap;overflow-y:auto}:host .input-container:focus-within{border:1px solid var(--primary-base)}:host .input-container input{min-width:80px;font-size:14px;flex:1 1 80px;color:var(--typography-base);background:var(--page-light);border:none}:host .input-container input:focus{outline:none;border:none}:host .input-container input::placeholder{color:var(--typography-light)}:host .input-container .context{color:var(--typography-light)}:host.errored .input-container,:host.ng-touched.ng-invalid .input-container{border:1px solid var(--red-base)}.disabled{opacity:.4;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: FwTextInputModule }, { kind: "ngmodule", type: FwChipModule }, { kind: "component", type: FwChipComponent, selector: "fw-chip", inputs: ["maxWidth", "value", "variant", "color", "icon", "title", "description", "showClose", "closeLabel", "disabled", "selected", "textWrap", "selectable"], outputs: ["close", "select"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FwMenuModule }, { kind: "component", type: FwMenuComponent, selector: "fw-menu", inputs: ["disabled", "size", "multiSelect", "useCheckbox", "value", "role", "id"], outputs: ["disabledChange", "valueChange", "change"] }, { kind: "component", type: FwMenuContainerComponent, selector: "fw-menu-container, fw-menu-filter", inputs: ["width", "maxHeight", "minHeight", "border", "shadow", "showFilter", "filterText", "focusFilterOnMount", "offset", "emptyText", "disableWrapperScroll", "filterFn", "additionalMenuItems", "additionalGroups", "additionalSeparators", "keyHandler"], outputs: ["filteredMenuItemChange", "filterChanged"] }, { kind: "component", type: FwMenuItemComponent, selector: "fw-menu-item", inputs: ["itemRole", "value", "size", "title", "description", "icon", "iconColor", "disabled", "showCheckbox", "checkboxColor", "multiSelect", "hidden", "collapsed", "href", "target", "subItemsOpen", "mouseEnterHandler", "focused", "selected"], outputs: ["itemRoleChange", "sizeChange", "disabledChange", "showCheckboxChange", "multiSelectChange", "hiddenChange", "subItemsOpenChange", "mouseEnterHandlerChange", "click", "focusedChange", "selectedChange"] }, { kind: "ngmodule", type: CdkMenuModule }, { kind: "directive", type: i5.CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData", "cdkMenuTriggerTransformOriginOn"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "directive", type: MenuRegisterDirective, selector: "[fwMenuRegister]" }, { kind: "ngmodule", type: FwProgressModule }, { kind: "component", type: FwProgressSpinnerComponent, selector: "fw-progress-spinner", inputs: ["mode", "size", "color", "showValue", "value"] }, { kind: "component", type: FwChipListComponent, selector: "fw-chip-list", inputs: ["resizeDebounceMs", "disableOverflow"] }, { kind: "component", type: FwIconComponent, selector: "fw-icon", inputs: ["ariaLabel", "size", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10978
+ ], viewQueries: [{ propertyName: "trigger", first: true, predicate: CdkMenuTrigger, descendants: true, isSignal: true }, { propertyName: "displayedOptions", predicate: FwMenuItemComponent, descendants: true, isSignal: true }, { propertyName: "inputRef", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"full-container\">\n <div\n class=\"input-container\"\n [class.disabled]=\"disabled()\"\n [style.max-height]=\"maxHeight()\"\n [cdkMenuTriggerFor]=\"menuContent\"\n fwMenuRegister\n #inputContainer>\n @if (selectType() === 'multiple') {\n <fw-chip-list class=\"chips\" [disableOverflow]=\"!!maxHeight()\">\n @for(val of value(); track val) {\n <fw-chip\n color=\"primary\"\n [showClose]=\"true\"\n [title]=\"val\"\n [selectable]=\"false\"\n (close)=\"closeChip(val)\"\n />\n }\n </fw-chip-list>\n }\n <input\n data-testid=\"typeahead-input\"\n [class.highlight-placeholder]=\"highlightPlaceholder()\"\n [placeholder]=\"displayedPlaceholder()\"\n [disabled]=\"disabled()\"\n (input)=\"handleInput($event)\"\n (keydown)=\"handleKey($event)\"\n (blur)=\"onFocusLoss($event)\"\n #input\n type=\"text\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isMenuOpen()\"\n [attr.aria-controls]=\"listboxId\"\n aria-autocomplete=\"list\"\n [attr.aria-activedescendant]=\"getActiveDescendantId()\"\n />\n @if(loading()) {\n <fw-progress-spinner size=\"small\"/>\n }\n @if(selectType() === 'single' && value().length === 1) {\n <fw-icon class=\"clear-icon\" (click)=\"clearValue()\">close</fw-icon>\n }\n </div>\n</div>\n<ng-template #menuContent>\n <fw-menu-container\n [maxHeight]=\"maxOptionsHeight()\"\n [minHeight]=\"minOptionsHeight()\"\n [width]=\"optionsWidth() || inputContainer.offsetWidth - 2 + 'px'\"\n >\n <fw-menu role=\"listbox\" [id]=\"listboxId\" (mousedown)=\"$event.preventDefault()\">\n @if(loading() && !displayNewOption()) {\n <fw-menu-item title=\"Searching...\" [disabled]=\"true\"/>\n } @else if(!loading() && isExhausted()) {\n <fw-menu-item [title]=\"exhaustedText()\" [disabled]=\"true\"/>\n } @else if(!loading()) {\n @for (option of filteredOptions(); track option) {\n @let notAllowed = isOptionNotAllowed(option);\n <fw-menu-item\n (click)=\"handleOptionClick(option)\"\n (mouseenter)=\"notAllowed ? null : setFocusByValue(option)\"\n [title]=\"option\"\n [focused]=\"focusedOption() === option\"\n [disabled]=\"notAllowed\"\n [value]=\"option\"\n >\n @if (notAllowed) {\n <p class=\"new-tag\">{{ optionNotAllowedLabel() }}</p>\n }\n </fw-menu-item>\n }\n @empty {\n @if (!showNewOption()) {\n <fw-menu-item [title]=\"emptyText()\" [disabled]=\"true\"/>\n }\n }\n }\n @if(showNewOption()) {\n <fw-menu-item\n (click)=\"handleOptionClick(searchValue())\"\n (mouseenter)=\"newOptionAllowed() ? setFocusByValue(searchValue()) : null\"\n [title]=\"searchValue()\"\n [value]=\"searchValue()\"\n [disabled]=\"!newOptionAllowed()\"\n [focused]=\"focusedOption() === searchValue()\">\n <p class=\"new-tag\">{{ newOptionAllowed() ? optionNewLabel() : optionNotAllowedLabel() }}</p>\n </fw-menu-item>\n }\n </fw-menu>\n </fw-menu-container>\n</ng-template>\n", styles: [".new-tag{margin:0;color:var(--typography-light)}:host.disabled{cursor:not-allowed}:host.disabled fw-icon{cursor:not-allowed!important}:host{display:flex;flex-direction:column;width:100%;line-height:21px}:host .chips,:host fw-progress-spinner{margin:-4px 0}:host .full-container{display:flex;flex-direction:column;width:100%}:host .highlight-placeholder::placeholder{color:var(--typography-base)!important}:host .clear-icon{cursor:pointer}:host .input-container{width:100%;box-sizing:border-box;color:var(--typography-light);background:var(--page-light);display:flex;padding:8px;row-gap:8px;align-items:center;border-radius:6px;border:1px solid var(--separations-input);font-family:Inter,sans-serif;flex-wrap:wrap;overflow-y:auto}:host .input-container:focus-within{border:1px solid var(--primary-base)}:host .input-container input{min-width:80px;font-size:14px;flex:1 1 80px;color:var(--typography-base);background:var(--page-light);border:none}:host .input-container input:focus{outline:none;border:none}:host .input-container input::placeholder{color:var(--typography-light)}:host .input-container .context{color:var(--typography-light)}:host.errored .input-container,:host.ng-touched.ng-invalid .input-container{border:1px solid var(--red-base)}.disabled{opacity:.4;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: FwTextInputModule }, { kind: "ngmodule", type: FwChipModule }, { kind: "component", type: FwChipComponent, selector: "fw-chip", inputs: ["maxWidth", "value", "variant", "color", "icon", "title", "description", "showClose", "closeLabel", "disabled", "selected", "textWrap", "selectable"], outputs: ["close", "select"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FwMenuModule }, { kind: "component", type: FwMenuComponent, selector: "fw-menu", inputs: ["disabled", "size", "multiSelect", "useCheckbox", "value", "role", "id"], outputs: ["disabledChange", "valueChange", "change"] }, { kind: "component", type: FwMenuContainerComponent, selector: "fw-menu-container, fw-menu-filter", inputs: ["width", "maxHeight", "minHeight", "border", "shadow", "showFilter", "filterText", "focusFilterOnMount", "offset", "emptyText", "disableWrapperScroll", "filterFn", "additionalMenuItems", "additionalGroups", "additionalSeparators", "keyHandler"], outputs: ["filteredMenuItemChange", "filterChanged"] }, { kind: "component", type: FwMenuItemComponent, selector: "fw-menu-item", inputs: ["itemRole", "value", "size", "title", "description", "icon", "iconColor", "disabled", "showCheckbox", "checkboxColor", "multiSelect", "hidden", "collapsed", "href", "target", "subItemsOpen", "mouseEnterHandler", "focused", "selected"], outputs: ["itemRoleChange", "sizeChange", "disabledChange", "showCheckboxChange", "multiSelectChange", "hiddenChange", "subItemsOpenChange", "mouseEnterHandlerChange", "click", "focusedChange", "selectedChange"] }, { kind: "ngmodule", type: CdkMenuModule }, { kind: "directive", type: i5.CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData", "cdkMenuTriggerTransformOriginOn"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "directive", type: MenuRegisterDirective, selector: "[fwMenuRegister]" }, { kind: "ngmodule", type: FwProgressModule }, { kind: "component", type: FwProgressSpinnerComponent, selector: "fw-progress-spinner", inputs: ["mode", "size", "color", "showValue", "value"] }, { kind: "component", type: FwChipListComponent, selector: "fw-chip-list", inputs: ["resizeDebounceMs", "disableOverflow"] }, { kind: "component", type: FwIconComponent, selector: "fw-icon", inputs: ["ariaLabel", "size", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
10907
10979
  }
10908
10980
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: FwTypeaheadComponent, decorators: [{
10909
10981
  type: Component,
@@ -10925,11 +10997,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
10925
10997
  },
10926
10998
  ], host: {
10927
10999
  '[class.fw-touched]': 'touched()',
10928
- }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"full-container\">\n <div\n class=\"input-container\"\n [class.disabled]=\"disabled()\"\n [style.max-height]=\"maxHeight()\"\n [cdkMenuTriggerFor]=\"menuContent\"\n fwMenuRegister\n #inputContainer>\n @if (selectType() === 'multiple') {\n <fw-chip-list class=\"chips\" [disableOverflow]=\"!!maxHeight()\">\n @for(val of value(); track val) {\n <fw-chip\n color=\"primary\"\n [showClose]=\"true\"\n [title]=\"val\"\n [selectable]=\"false\"\n (close)=\"closeChip(val)\"\n />\n }\n </fw-chip-list>\n }\n <input\n data-testid=\"typeahead-input\"\n [class.highlight-placeholder]=\"highlightPlaceholder()\"\n [placeholder]=\"displayedPlaceholder()\"\n [disabled]=\"disabled()\"\n (input)=\"handleInput($event)\"\n (keydown)=\"handleKey($event)\"\n (blur)=\"onFocusLoss($event)\"\n #input\n type=\"text\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isMenuOpen()\"\n [attr.aria-controls]=\"listboxId\"\n aria-autocomplete=\"list\"\n [attr.aria-activedescendant]=\"getActiveDescendantId()\"\n />\n @if(loading()) {\n <fw-progress-spinner size=\"small\"/>\n }\n @if(selectType() === 'single' && value().length === 1) {\n <fw-icon class=\"clear-icon\" (click)=\"clearValue()\">close</fw-icon>\n }\n </div>\n</div>\n<ng-template #menuContent>\n <fw-menu-container\n [maxHeight]=\"maxOptionsHeight()\"\n [minHeight]=\"minOptionsHeight()\"\n [width]=\"optionsWidth() || inputContainer.offsetWidth - 2 + 'px'\"\n >\n <fw-menu role=\"listbox\" [id]=\"listboxId\" (mousedown)=\"$event.preventDefault()\">\n @if(loading() && !displayNewOption()) {\n <fw-menu-item title=\"Searching...\" [disabled]=\"true\"/>\n } @else if(!loading()) {\n @for (option of filteredOptions(); track option) {\n <fw-menu-item\n (click)=\"handleOptionClick(option)\"\n (mouseenter)=\"setFocusByValue(option)\"\n [title]=\"option\"\n [focused]=\"focusedOption() === option\"\n [value]=\"option\"\n />\n }\n @empty {\n @if (!displayNewOption()) {\n <fw-menu-item [title]=\"emptyText()\" [disabled]=\"true\"/>\n }\n }\n }\n @if(displayNewOption()) {\n <fw-menu-item\n (click)=\"handleOptionClick(searchValue())\"\n (mouseenter)=\"setFocusByValue(searchValue())\"\n [title]=\"searchValue()\"\n [value]=\"searchValue()\"\n [focused]=\"focusedOption() === searchValue()\">\n <p class=\"new-tag\">New</p>\n </fw-menu-item>\n }\n </fw-menu>\n </fw-menu-container>\n</ng-template>\n", styles: [".new-tag{margin:0;color:var(--typography-light)}:host.disabled{cursor:not-allowed}:host.disabled fw-icon{cursor:not-allowed!important}:host{display:flex;flex-direction:column;width:100%;line-height:21px}:host .chips,:host fw-progress-spinner{margin:-4px 0}:host .full-container{display:flex;flex-direction:column;width:100%}:host .highlight-placeholder::placeholder{color:var(--typography-base)!important}:host .clear-icon{cursor:pointer}:host .input-container{width:100%;box-sizing:border-box;color:var(--typography-light);background:var(--page-light);display:flex;padding:8px;row-gap:8px;align-items:center;border-radius:6px;border:1px solid var(--separations-input);font-family:Inter,sans-serif;flex-wrap:wrap;overflow-y:auto}:host .input-container:focus-within{border:1px solid var(--primary-base)}:host .input-container input{min-width:80px;font-size:14px;flex:1 1 80px;color:var(--typography-base);background:var(--page-light);border:none}:host .input-container input:focus{outline:none;border:none}:host .input-container input::placeholder{color:var(--typography-light)}:host .input-container .context{color:var(--typography-light)}:host.errored .input-container,:host.ng-touched.ng-invalid .input-container{border:1px solid var(--red-base)}.disabled{opacity:.4;pointer-events:none}\n"] }]
11000
+ }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"full-container\">\n <div\n class=\"input-container\"\n [class.disabled]=\"disabled()\"\n [style.max-height]=\"maxHeight()\"\n [cdkMenuTriggerFor]=\"menuContent\"\n fwMenuRegister\n #inputContainer>\n @if (selectType() === 'multiple') {\n <fw-chip-list class=\"chips\" [disableOverflow]=\"!!maxHeight()\">\n @for(val of value(); track val) {\n <fw-chip\n color=\"primary\"\n [showClose]=\"true\"\n [title]=\"val\"\n [selectable]=\"false\"\n (close)=\"closeChip(val)\"\n />\n }\n </fw-chip-list>\n }\n <input\n data-testid=\"typeahead-input\"\n [class.highlight-placeholder]=\"highlightPlaceholder()\"\n [placeholder]=\"displayedPlaceholder()\"\n [disabled]=\"disabled()\"\n (input)=\"handleInput($event)\"\n (keydown)=\"handleKey($event)\"\n (blur)=\"onFocusLoss($event)\"\n #input\n type=\"text\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isMenuOpen()\"\n [attr.aria-controls]=\"listboxId\"\n aria-autocomplete=\"list\"\n [attr.aria-activedescendant]=\"getActiveDescendantId()\"\n />\n @if(loading()) {\n <fw-progress-spinner size=\"small\"/>\n }\n @if(selectType() === 'single' && value().length === 1) {\n <fw-icon class=\"clear-icon\" (click)=\"clearValue()\">close</fw-icon>\n }\n </div>\n</div>\n<ng-template #menuContent>\n <fw-menu-container\n [maxHeight]=\"maxOptionsHeight()\"\n [minHeight]=\"minOptionsHeight()\"\n [width]=\"optionsWidth() || inputContainer.offsetWidth - 2 + 'px'\"\n >\n <fw-menu role=\"listbox\" [id]=\"listboxId\" (mousedown)=\"$event.preventDefault()\">\n @if(loading() && !displayNewOption()) {\n <fw-menu-item title=\"Searching...\" [disabled]=\"true\"/>\n } @else if(!loading() && isExhausted()) {\n <fw-menu-item [title]=\"exhaustedText()\" [disabled]=\"true\"/>\n } @else if(!loading()) {\n @for (option of filteredOptions(); track option) {\n @let notAllowed = isOptionNotAllowed(option);\n <fw-menu-item\n (click)=\"handleOptionClick(option)\"\n (mouseenter)=\"notAllowed ? null : setFocusByValue(option)\"\n [title]=\"option\"\n [focused]=\"focusedOption() === option\"\n [disabled]=\"notAllowed\"\n [value]=\"option\"\n >\n @if (notAllowed) {\n <p class=\"new-tag\">{{ optionNotAllowedLabel() }}</p>\n }\n </fw-menu-item>\n }\n @empty {\n @if (!showNewOption()) {\n <fw-menu-item [title]=\"emptyText()\" [disabled]=\"true\"/>\n }\n }\n }\n @if(showNewOption()) {\n <fw-menu-item\n (click)=\"handleOptionClick(searchValue())\"\n (mouseenter)=\"newOptionAllowed() ? setFocusByValue(searchValue()) : null\"\n [title]=\"searchValue()\"\n [value]=\"searchValue()\"\n [disabled]=\"!newOptionAllowed()\"\n [focused]=\"focusedOption() === searchValue()\">\n <p class=\"new-tag\">{{ newOptionAllowed() ? optionNewLabel() : optionNotAllowedLabel() }}</p>\n </fw-menu-item>\n }\n </fw-menu>\n </fw-menu-container>\n</ng-template>\n", styles: [".new-tag{margin:0;color:var(--typography-light)}:host.disabled{cursor:not-allowed}:host.disabled fw-icon{cursor:not-allowed!important}:host{display:flex;flex-direction:column;width:100%;line-height:21px}:host .chips,:host fw-progress-spinner{margin:-4px 0}:host .full-container{display:flex;flex-direction:column;width:100%}:host .highlight-placeholder::placeholder{color:var(--typography-base)!important}:host .clear-icon{cursor:pointer}:host .input-container{width:100%;box-sizing:border-box;color:var(--typography-light);background:var(--page-light);display:flex;padding:8px;row-gap:8px;align-items:center;border-radius:6px;border:1px solid var(--separations-input);font-family:Inter,sans-serif;flex-wrap:wrap;overflow-y:auto}:host .input-container:focus-within{border:1px solid var(--primary-base)}:host .input-container input{min-width:80px;font-size:14px;flex:1 1 80px;color:var(--typography-base);background:var(--page-light);border:none}:host .input-container input:focus{outline:none;border:none}:host .input-container input::placeholder{color:var(--typography-light)}:host .input-container .context{color:var(--typography-light)}:host.errored .input-container,:host.ng-touched.ng-invalid .input-container{border:1px solid var(--red-base)}.disabled{opacity:.4;pointer-events:none}\n"] }]
10929
11001
  }], propDecorators: { outsideClick: [{
10930
11002
  type: HostListener,
10931
11003
  args: ['document:click']
10932
- }], trigger: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkMenuTrigger), { isSignal: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }, { type: i0.Output, args: ["loadingChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], onClick: [{
11004
+ }], trigger: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkMenuTrigger), { isSignal: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }, { type: i0.Output, args: ["loadingChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], exhaustedText: [{ type: i0.Input, args: [{ isSignal: true, alias: "exhaustedText", required: false }] }], optionsNotAllowed: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsNotAllowed", required: false }] }], onValidateNewOption: [{ type: i0.Input, args: [{ isSignal: true, alias: "onValidateNewOption", required: false }] }], optionNewLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionNewLabel", required: false }] }], optionNotAllowedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionNotAllowedLabel", required: false }] }], onClick: [{
10933
11005
  type: HostListener,
10934
11006
  args: ['click', ['$event']]
10935
11007
  }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], optionsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], maxOptionsHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxOptionsHeight", required: false }] }], minOptionsHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "minOptionsHeight", required: false }] }], optionsWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsWidth", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], selectType: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectType", required: false }] }], searchValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchValue", required: false }] }, { type: i0.Output, args: ["searchValueChange"] }], allowNew: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowNew", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], displayedOptions: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => FwMenuItemComponent), { isSignal: true }] }], inputRef: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }] } });