UNPKG

@angular/cdk

Version:

Angular Material Component Development Kit

1 lines 64.3 kB
{"version":3,"file":"listbox.mjs","sources":["../../../../../k8-fastbuild-ST-199a4f3c4e20/bin/src/cdk/listbox/listbox.ts","../../../../../k8-fastbuild-ST-199a4f3c4e20/bin/src/cdk/listbox/listbox-module.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {\n _IdGenerator,\n ActiveDescendantKeyManager,\n Highlightable,\n ListKeyManagerOption,\n} from '../a11y';\nimport {Directionality} from '../bidi';\nimport {coerceArray} from '../coercion';\nimport {SelectionModel} from '../collections';\nimport {\n A,\n DOWN_ARROW,\n END,\n ENTER,\n hasModifierKey,\n HOME,\n LEFT_ARROW,\n RIGHT_ARROW,\n SPACE,\n UP_ARROW,\n} from '../keycodes';\nimport {Platform} from '../platform';\nimport {\n AfterContentInit,\n booleanAttribute,\n ChangeDetectorRef,\n ContentChildren,\n Directive,\n ElementRef,\n forwardRef,\n inject,\n Input,\n NgZone,\n numberAttribute,\n OnDestroy,\n Output,\n QueryList,\n Renderer2,\n signal,\n} from '@angular/core';\nimport {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';\nimport {defer, merge, Observable, Subject} from 'rxjs';\nimport {filter, map, startWith, switchMap, takeUntil} from 'rxjs/operators';\n\n/**\n * An implementation of SelectionModel that internally always represents the selection as a\n * multi-selection. This is necessary so that we can recover the full selection if the user\n * switches the listbox from single-selection to multi-selection after initialization.\n *\n * This selection model may report multiple selected values, even if it is in single-selection\n * mode. It is up to the user (CdkListbox) to check for invalid selections.\n */\nclass ListboxSelectionModel<T> extends SelectionModel<T> {\n constructor(\n public multiple = false,\n initiallySelectedValues?: T[],\n emitChanges = true,\n compareWith?: (o1: T, o2: T) => boolean,\n ) {\n super(true, initiallySelectedValues, emitChanges, compareWith);\n }\n\n override isMultipleSelection(): boolean {\n return this.multiple;\n }\n\n override select(...values: T[]) {\n // The super class is always in multi-selection mode, so we need to override the behavior if\n // this selection model actually belongs to a single-selection listbox.\n if (this.multiple) {\n return super.select(...values);\n } else {\n return super.setSelection(...values);\n }\n }\n}\n\n/** A selectable option in a listbox. */\n@Directive({\n selector: '[cdkOption]',\n exportAs: 'cdkOption',\n host: {\n 'role': 'option',\n 'class': 'cdk-option',\n '[id]': 'id',\n '[attr.aria-selected]': 'isSelected()',\n '[attr.tabindex]': '_getTabIndex()',\n '[attr.aria-disabled]': 'disabled',\n '[class.cdk-option-active]': 'isActive()',\n '(click)': '_clicked.next($event)',\n '(focus)': '_handleFocus()',\n },\n})\nexport class CdkOption<T = unknown> implements ListKeyManagerOption, Highlightable, OnDestroy {\n /** The id of the option's host element. */\n @Input()\n get id() {\n return this._id || this._generatedId;\n }\n set id(value) {\n this._id = value;\n }\n private _id: string;\n private _generatedId = inject(_IdGenerator).getId('cdk-option-');\n\n /** The value of this option. */\n @Input('cdkOption') value: T;\n\n /**\n * The text used to locate this item during listbox typeahead. If not specified,\n * the `textContent` of the item will be used.\n */\n @Input('cdkOptionTypeaheadLabel') typeaheadLabel: string | null;\n\n /** Whether this option is disabled. */\n @Input({alias: 'cdkOptionDisabled', transform: booleanAttribute})\n get disabled(): boolean {\n return this.listbox.disabled || this._disabled();\n }\n set disabled(value: boolean) {\n this._disabled.set(value);\n }\n private _disabled = signal(false);\n\n /** The tabindex of the option when it is enabled. */\n @Input({\n alias: 'tabindex',\n transform: (value: unknown) => (value == null ? undefined : numberAttribute(value)),\n })\n get enabledTabIndex() {\n return this._enabledTabIndex() === undefined\n ? this.listbox.enabledTabIndex\n : this._enabledTabIndex();\n }\n set enabledTabIndex(value) {\n this._enabledTabIndex.set(value);\n }\n private _enabledTabIndex = signal<number | null | undefined>(undefined);\n\n /** The option's host element */\n readonly element: HTMLElement = inject(ElementRef).nativeElement;\n\n /** The parent listbox this option belongs to. */\n protected readonly listbox: CdkListbox<T> = inject(CdkListbox);\n\n /** Emits when the option is destroyed. */\n protected destroyed = new Subject<void>();\n\n /** Emits when the option is clicked. */\n readonly _clicked = new Subject<MouseEvent>();\n\n ngOnDestroy() {\n this.destroyed.next();\n this.destroyed.complete();\n }\n\n /** Whether this option is selected. */\n isSelected() {\n return this.listbox.isSelected(this);\n }\n\n /** Whether this option is active. */\n isActive() {\n return this.listbox.isActive(this);\n }\n\n /** Toggle the selected state of this option. */\n toggle() {\n this.listbox.toggle(this);\n }\n\n /** Select this option if it is not selected. */\n select() {\n this.listbox.select(this);\n }\n\n /** Deselect this option if it is selected. */\n deselect() {\n this.listbox.deselect(this);\n }\n\n /** Focus this option. */\n focus() {\n this.element.focus();\n }\n\n /** Get the label for this element which is required by the FocusableOption interface. */\n getLabel() {\n return (this.typeaheadLabel ?? this.element.textContent?.trim()) || '';\n }\n\n /**\n * No-op implemented as a part of `Highlightable`.\n * @docs-private\n */\n setActiveStyles() {\n // If the listbox is using `aria-activedescendant` the option won't have focus so the\n // browser won't scroll them into view automatically so we need to do it ourselves.\n if (this.listbox.useActiveDescendant) {\n this.element.scrollIntoView({block: 'nearest', inline: 'nearest'});\n }\n }\n\n /**\n * No-op implemented as a part of `Highlightable`.\n * @docs-private\n */\n setInactiveStyles() {}\n\n /** Handle focus events on the option. */\n protected _handleFocus() {\n // Options can wind up getting focused in active descendant mode if the user clicks on them.\n // In this case, we push focus back to the parent listbox to prevent an extra tab stop when\n // the user performs a shift+tab.\n if (this.listbox.useActiveDescendant) {\n this.listbox._setActiveOption(this);\n this.listbox.focus();\n }\n }\n\n /** Get the tabindex for this option. */\n protected _getTabIndex() {\n if (this.listbox.useActiveDescendant || this.disabled) {\n return -1;\n }\n return this.isActive() ? this.enabledTabIndex : -1;\n }\n}\n\n@Directive({\n selector: '[cdkListbox]',\n exportAs: 'cdkListbox',\n host: {\n 'role': 'listbox',\n 'class': 'cdk-listbox',\n '[id]': 'id',\n '[attr.tabindex]': '_getTabIndex()',\n '[attr.aria-disabled]': 'disabled',\n '[attr.aria-multiselectable]': 'multiple',\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\n '[attr.aria-orientation]': 'orientation',\n '(focus)': '_handleFocus()',\n '(keydown)': '_handleKeydown($event)',\n '(focusout)': '_handleFocusOut($event)',\n '(focusin)': '_handleFocusIn()',\n },\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => CdkListbox),\n multi: true,\n },\n ],\n})\nexport class CdkListbox<T = unknown> implements AfterContentInit, OnDestroy, ControlValueAccessor {\n private _cleanupWindowBlur: (() => void) | undefined;\n\n /** The id of the option's host element. */\n @Input()\n get id() {\n return this._id || this._generatedId;\n }\n set id(value) {\n this._id = value;\n }\n private _id: string;\n private _generatedId = inject(_IdGenerator).getId('cdk-listbox-');\n\n /** The tabindex to use when the listbox is enabled. */\n @Input('tabindex')\n get enabledTabIndex() {\n return this._enabledTabIndex() === undefined ? 0 : this._enabledTabIndex();\n }\n set enabledTabIndex(value) {\n this._enabledTabIndex.set(value);\n }\n private _enabledTabIndex = signal<number | null | undefined>(undefined);\n\n /** The value selected in the listbox, represented as an array of option values. */\n @Input('cdkListboxValue')\n get value(): readonly T[] {\n return this._invalid ? [] : this.selectionModel.selected;\n }\n set value(value: readonly T[]) {\n this._setSelection(value);\n }\n\n /**\n * Whether the listbox allows multiple options to be selected. If the value switches from `true`\n * to `false`, and more than one option is selected, all options are deselected.\n */\n @Input({alias: 'cdkListboxMultiple', transform: booleanAttribute})\n get multiple(): boolean {\n return this.selectionModel.multiple;\n }\n set multiple(value: boolean) {\n this.selectionModel.multiple = value;\n\n if (this.options) {\n this._updateInternalValue();\n }\n }\n\n /** Whether the listbox is disabled. */\n @Input({alias: 'cdkListboxDisabled', transform: booleanAttribute})\n get disabled() {\n return this._disabled();\n }\n set disabled(value: boolean) {\n this._disabled.set(value);\n }\n private _disabled = signal(false);\n\n /** Whether the listbox will use active descendant or will move focus onto the options. */\n @Input({alias: 'cdkListboxUseActiveDescendant', transform: booleanAttribute})\n get useActiveDescendant() {\n return this._useActiveDescendant();\n }\n set useActiveDescendant(value: boolean) {\n this._useActiveDescendant.set(value);\n }\n private _useActiveDescendant = signal(false);\n\n /** The orientation of the listbox. Only affects keyboard interaction, not visual layout. */\n @Input('cdkListboxOrientation')\n get orientation() {\n return this._orientation;\n }\n set orientation(value: 'horizontal' | 'vertical') {\n this._orientation = value === 'horizontal' ? 'horizontal' : 'vertical';\n if (value === 'horizontal') {\n this.listKeyManager?.withHorizontalOrientation(this._dir?.value || 'ltr');\n } else {\n this.listKeyManager?.withVerticalOrientation();\n }\n }\n private _orientation: 'horizontal' | 'vertical' = 'vertical';\n\n /** The function used to compare option values. */\n @Input('cdkListboxCompareWith')\n get compareWith(): undefined | ((o1: T, o2: T) => boolean) {\n return this.selectionModel.compareWith;\n }\n set compareWith(fn: undefined | ((o1: T, o2: T) => boolean)) {\n this.selectionModel.compareWith = fn;\n }\n\n /**\n * Whether the keyboard navigation should wrap when the user presses arrow down on the last item\n * or arrow up on the first item.\n */\n @Input({alias: 'cdkListboxNavigationWrapDisabled', transform: booleanAttribute})\n get navigationWrapDisabled() {\n return this._navigationWrapDisabled;\n }\n set navigationWrapDisabled(wrap: boolean) {\n this._navigationWrapDisabled = wrap;\n this.listKeyManager?.withWrap(!this._navigationWrapDisabled);\n }\n private _navigationWrapDisabled = false;\n\n /** Whether keyboard navigation should skip over disabled items. */\n @Input({alias: 'cdkListboxNavigatesDisabledOptions', transform: booleanAttribute})\n get navigateDisabledOptions() {\n return this._navigateDisabledOptions;\n }\n set navigateDisabledOptions(skip: boolean) {\n this._navigateDisabledOptions = skip;\n this.listKeyManager?.skipPredicate(\n this._navigateDisabledOptions ? this._skipNonePredicate : this._skipDisabledPredicate,\n );\n }\n private _navigateDisabledOptions = false;\n\n /** Emits when the selected value(s) in the listbox change. */\n @Output('cdkListboxValueChange') readonly valueChange = new Subject<ListboxValueChangeEvent<T>>();\n\n /** The child options in this listbox. */\n @ContentChildren(CdkOption, {descendants: true}) protected options: QueryList<CdkOption<T>>;\n\n /** The selection model used by the listbox. */\n protected selectionModel = new ListboxSelectionModel<T>();\n\n /** The key manager that manages keyboard navigation for this listbox. */\n protected listKeyManager: ActiveDescendantKeyManager<CdkOption<T>>;\n\n /** Emits when the listbox is destroyed. */\n protected readonly destroyed = new Subject<void>();\n\n /** The host element of the listbox. */\n protected readonly element: HTMLElement = inject(ElementRef).nativeElement;\n\n /** The Angular zone. */\n protected readonly ngZone = inject(NgZone);\n\n /** The change detector for this listbox. */\n protected readonly changeDetectorRef = inject(ChangeDetectorRef);\n\n /** Whether the currently selected value in the selection model is invalid. */\n private _invalid = false;\n\n /** The last user-triggered option. */\n private _lastTriggered: CdkOption<T> | null = null;\n\n /** Callback called when the listbox has been touched */\n private _onTouched = () => {};\n\n /** Callback called when the listbox value changes */\n private _onChange: (value: readonly T[]) => void = () => {};\n\n /** Emits when an option has been clicked. */\n private _optionClicked = defer(() =>\n (this.options.changes as Observable<CdkOption<T>[]>).pipe(\n startWith(this.options),\n switchMap(options =>\n merge(...options.map(option => option._clicked.pipe(map(event => ({option, event}))))),\n ),\n ),\n );\n\n /** The directionality of the page. */\n private readonly _dir = inject(Directionality, {optional: true});\n\n /** Whether the component is being rendered in the browser. */\n private readonly _isBrowser: boolean = inject(Platform).isBrowser;\n\n /** A predicate that skips disabled options. */\n private readonly _skipDisabledPredicate = (option: CdkOption<T>) => option.disabled;\n\n /** A predicate that does not skip any options. */\n private readonly _skipNonePredicate = () => false;\n\n /** Whether the listbox currently has focus. */\n private _hasFocus = false;\n\n /** A reference to the option that was active before the listbox lost focus. */\n private _previousActiveOption: CdkOption<T> | null = null;\n\n constructor() {\n if (this._isBrowser) {\n const renderer = inject(Renderer2);\n\n this._cleanupWindowBlur = this.ngZone.runOutsideAngular(() => {\n return renderer.listen('window', 'blur', () => {\n if (this.element.contains(document.activeElement) && this._previousActiveOption) {\n this._setActiveOption(this._previousActiveOption);\n this._previousActiveOption = null;\n }\n });\n });\n }\n }\n\n ngAfterContentInit() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n this._verifyNoOptionValueCollisions();\n this._verifyOptionValues();\n }\n\n this._initKeyManager();\n\n // Update the internal value whenever the options or the model value changes.\n merge(this.selectionModel.changed, this.options.changes)\n .pipe(startWith(null), takeUntil(this.destroyed))\n .subscribe(() => this._updateInternalValue());\n\n this._optionClicked\n .pipe(\n filter(({option}) => !option.disabled),\n takeUntil(this.destroyed),\n )\n .subscribe(({option, event}) => this._handleOptionClicked(option, event));\n }\n\n ngOnDestroy() {\n this._cleanupWindowBlur?.();\n this.listKeyManager?.destroy();\n this.destroyed.next();\n this.destroyed.complete();\n }\n\n /**\n * Toggle the selected state of the given option.\n * @param option The option to toggle\n */\n toggle(option: CdkOption<T>) {\n this.toggleValue(option.value);\n }\n\n /**\n * Toggle the selected state of the given value.\n * @param value The value to toggle\n */\n toggleValue(value: T) {\n if (this._invalid) {\n this.selectionModel.clear(false);\n }\n this.selectionModel.toggle(value);\n }\n\n /**\n * Select the given option.\n * @param option The option to select\n */\n select(option: CdkOption<T>) {\n this.selectValue(option.value);\n }\n\n /**\n * Select the given value.\n * @param value The value to select\n */\n selectValue(value: T) {\n if (this._invalid) {\n this.selectionModel.clear(false);\n }\n this.selectionModel.select(value);\n }\n\n /**\n * Deselect the given option.\n * @param option The option to deselect\n */\n deselect(option: CdkOption<T>) {\n this.deselectValue(option.value);\n }\n\n /**\n * Deselect the given value.\n * @param value The value to deselect\n */\n deselectValue(value: T) {\n if (this._invalid) {\n this.selectionModel.clear(false);\n }\n this.selectionModel.deselect(value);\n }\n\n /**\n * Set the selected state of all options.\n * @param isSelected The new selected state to set\n */\n setAllSelected(isSelected: boolean) {\n if (!isSelected) {\n this.selectionModel.clear();\n } else {\n if (this._invalid) {\n this.selectionModel.clear(false);\n }\n this.selectionModel.select(...this.options.map(option => option.value));\n }\n }\n\n /**\n * Get whether the given option is selected.\n * @param option The option to get the selected state of\n */\n isSelected(option: CdkOption<T>) {\n return this.isValueSelected(option.value);\n }\n\n /**\n * Get whether the given option is active.\n * @param option The option to get the active state of\n */\n isActive(option: CdkOption<T>): boolean {\n return !!(this.listKeyManager?.activeItem === option);\n }\n\n /**\n * Get whether the given value is selected.\n * @param value The value to get the selected state of\n */\n isValueSelected(value: T) {\n if (this._invalid) {\n return false;\n }\n return this.selectionModel.isSelected(value);\n }\n\n /**\n * Registers a callback to be invoked when the listbox's value changes from user input.\n * @param fn The callback to register\n * @docs-private\n */\n registerOnChange(fn: (value: readonly T[]) => void): void {\n this._onChange = fn;\n }\n\n /**\n * Registers a callback to be invoked when the listbox is blurred by the user.\n * @param fn The callback to register\n * @docs-private\n */\n registerOnTouched(fn: () => {}): void {\n this._onTouched = fn;\n }\n\n /**\n * Sets the listbox's value.\n * @param value The new value of the listbox\n * @docs-private\n */\n writeValue(value: readonly T[]): void {\n this._setSelection(value);\n this._verifyOptionValues();\n }\n\n /**\n * Sets the disabled state of the listbox.\n * @param isDisabled The new disabled state\n * @docs-private\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n this.changeDetectorRef.markForCheck();\n }\n\n /** Focus the listbox's host element. */\n focus() {\n this.element.focus();\n }\n\n /**\n * Triggers the given option in response to user interaction.\n * - In single selection mode: selects the option and deselects any other selected option.\n * - In multi selection mode: toggles the selected state of the option.\n * @param option The option to trigger\n */\n protected triggerOption(option: CdkOption<T> | null) {\n if (option && !option.disabled) {\n this._lastTriggered = option;\n const changed = this.multiple\n ? this.selectionModel.toggle(option.value)\n : this.selectionModel.select(option.value);\n if (changed) {\n this._onChange(this.value);\n this.valueChange.next({\n value: this.value,\n listbox: this,\n option: option,\n });\n }\n }\n }\n\n /**\n * Trigger the given range of options in response to user interaction.\n * Should only be called in multi-selection mode.\n * @param trigger The option that was triggered\n * @param from The start index of the options to toggle\n * @param to The end index of the options to toggle\n * @param on Whether to toggle the option range on\n */\n protected triggerRange(trigger: CdkOption<T> | null, from: number, to: number, on: boolean) {\n if (this.disabled || (trigger && trigger.disabled)) {\n return;\n }\n this._lastTriggered = trigger;\n const isEqual = this.compareWith ?? Object.is;\n const updateValues = [...this.options]\n .slice(Math.max(0, Math.min(from, to)), Math.min(this.options.length, Math.max(from, to) + 1))\n .filter(option => !option.disabled)\n .map(option => option.value);\n const selected = [...this.value];\n for (const updateValue of updateValues) {\n const selectedIndex = selected.findIndex(selectedValue =>\n isEqual(selectedValue, updateValue),\n );\n if (on && selectedIndex === -1) {\n selected.push(updateValue);\n } else if (!on && selectedIndex !== -1) {\n selected.splice(selectedIndex, 1);\n }\n }\n let changed = this.selectionModel.setSelection(...selected);\n if (changed) {\n this._onChange(this.value);\n this.valueChange.next({\n value: this.value,\n listbox: this,\n option: trigger,\n });\n }\n }\n\n /**\n * Sets the given option as active.\n * @param option The option to make active\n */\n _setActiveOption(option: CdkOption<T>) {\n this.listKeyManager.setActiveItem(option);\n }\n\n /** Called when the listbox receives focus. */\n protected _handleFocus() {\n if (!this.useActiveDescendant) {\n if (this.selectionModel.selected.length > 0) {\n this._setNextFocusToSelectedOption();\n } else {\n this.listKeyManager.setNextItemActive();\n }\n\n this._focusActiveOption();\n }\n }\n\n /** Called when the user presses keydown on the listbox. */\n protected _handleKeydown(event: KeyboardEvent) {\n if (this.disabled) {\n return;\n }\n\n const {keyCode} = event;\n const previousActiveIndex = this.listKeyManager.activeItemIndex;\n const ctrlKeys = ['ctrlKey', 'metaKey'] as const;\n\n if (this.multiple && keyCode === A && hasModifierKey(event, ...ctrlKeys)) {\n // Toggle all options off if they're all selected, otherwise toggle them all on.\n this.triggerRange(\n null,\n 0,\n this.options.length - 1,\n this.options.length !== this.value.length,\n );\n event.preventDefault();\n return;\n }\n\n if (\n this.multiple &&\n (keyCode === SPACE || keyCode === ENTER) &&\n hasModifierKey(event, 'shiftKey')\n ) {\n if (this.listKeyManager.activeItem && this.listKeyManager.activeItemIndex != null) {\n this.triggerRange(\n this.listKeyManager.activeItem,\n this._getLastTriggeredIndex() ?? this.listKeyManager.activeItemIndex,\n this.listKeyManager.activeItemIndex,\n !this.listKeyManager.activeItem.isSelected(),\n );\n }\n event.preventDefault();\n return;\n }\n\n if (\n this.multiple &&\n keyCode === HOME &&\n hasModifierKey(event, ...ctrlKeys) &&\n hasModifierKey(event, 'shiftKey')\n ) {\n const trigger = this.listKeyManager.activeItem;\n if (trigger) {\n const from = this.listKeyManager.activeItemIndex!;\n this.listKeyManager.setFirstItemActive();\n this.triggerRange(\n trigger,\n from,\n this.listKeyManager.activeItemIndex!,\n !trigger.isSelected(),\n );\n }\n event.preventDefault();\n return;\n }\n\n if (\n this.multiple &&\n keyCode === END &&\n hasModifierKey(event, ...ctrlKeys) &&\n hasModifierKey(event, 'shiftKey')\n ) {\n const trigger = this.listKeyManager.activeItem;\n if (trigger) {\n const from = this.listKeyManager.activeItemIndex!;\n this.listKeyManager.setLastItemActive();\n this.triggerRange(\n trigger,\n from,\n this.listKeyManager.activeItemIndex!,\n !trigger.isSelected(),\n );\n }\n event.preventDefault();\n return;\n }\n\n if (keyCode === SPACE || keyCode === ENTER) {\n this.triggerOption(this.listKeyManager.activeItem);\n event.preventDefault();\n return;\n }\n\n const isNavKey =\n keyCode === UP_ARROW ||\n keyCode === DOWN_ARROW ||\n keyCode === LEFT_ARROW ||\n keyCode === RIGHT_ARROW ||\n keyCode === HOME ||\n keyCode === END;\n this.listKeyManager.onKeydown(event);\n // Will select an option if shift was pressed while navigating to the option\n if (isNavKey && event.shiftKey && previousActiveIndex !== this.listKeyManager.activeItemIndex) {\n this.triggerOption(this.listKeyManager.activeItem);\n }\n }\n\n /** Called when a focus moves into the listbox. */\n protected _handleFocusIn() {\n // Note that we use a `focusin` handler for this instead of the existing `focus` handler,\n // because focus won't land on the listbox if `useActiveDescendant` is enabled.\n this._hasFocus = true;\n }\n\n /**\n * Called when the focus leaves an element in the listbox.\n * @param event The focusout event\n */\n protected _handleFocusOut(event: FocusEvent) {\n // Some browsers (e.g. Chrome and Firefox) trigger the focusout event when the user returns back to the document.\n // To prevent losing the active option in this case, we store it in `_previousActiveOption` and restore it on the window `blur` event\n // This ensures that the `activeItem` matches the actual focused element when the user returns to the document.\n this._previousActiveOption = this.listKeyManager.activeItem;\n\n const otherElement = event.relatedTarget as Element;\n if (this.element !== otherElement && !this.element.contains(otherElement)) {\n this._onTouched();\n this._hasFocus = false;\n this._setNextFocusToSelectedOption();\n }\n }\n\n /** Get the id of the active option if active descendant is being used. */\n protected _getAriaActiveDescendant(): string | null | undefined {\n return this.useActiveDescendant ? this.listKeyManager?.activeItem?.id : null;\n }\n\n /** Get the tabindex for the listbox. */\n protected _getTabIndex() {\n if (this.disabled) {\n return -1;\n }\n return this.useActiveDescendant || !this.listKeyManager.activeItem ? this.enabledTabIndex : -1;\n }\n\n /** Initialize the key manager. */\n private _initKeyManager() {\n this.listKeyManager = new ActiveDescendantKeyManager(this.options)\n .withWrap(!this._navigationWrapDisabled)\n .withTypeAhead()\n .withHomeAndEnd()\n .withAllowedModifierKeys(['shiftKey'])\n .skipPredicate(\n this._navigateDisabledOptions ? this._skipNonePredicate : this._skipDisabledPredicate,\n );\n\n if (this.orientation === 'vertical') {\n this.listKeyManager.withVerticalOrientation();\n } else {\n this.listKeyManager.withHorizontalOrientation(this._dir?.value || 'ltr');\n }\n\n if (this.selectionModel.selected.length) {\n Promise.resolve().then(() => this._setNextFocusToSelectedOption());\n }\n\n this.listKeyManager.change.subscribe(() => this._focusActiveOption());\n\n this.options.changes.pipe(takeUntil(this.destroyed)).subscribe(() => {\n const activeOption = this.listKeyManager.activeItem;\n\n // If the active option was deleted, we need to reset\n // the key manager so it can allow focus back in.\n if (activeOption && !this.options.find(option => option === activeOption)) {\n this.listKeyManager.setActiveItem(-1);\n this.changeDetectorRef.markForCheck();\n }\n });\n }\n\n /** Focus the active option. */\n private _focusActiveOption() {\n if (!this.useActiveDescendant) {\n this.listKeyManager.activeItem?.focus();\n }\n this.changeDetectorRef.markForCheck();\n }\n\n /**\n * Set the selected values.\n * @param value The list of new selected values.\n */\n private _setSelection(value: readonly T[]) {\n if (this._invalid) {\n this.selectionModel.clear(false);\n }\n this.selectionModel.setSelection(...this._coerceValue(value));\n\n if (!this._hasFocus) {\n this._setNextFocusToSelectedOption();\n }\n }\n\n /** Sets the first selected option as first in the keyboard focus order. */\n private _setNextFocusToSelectedOption() {\n // Null check the options since they only get defined after `ngAfterContentInit`.\n const selected = this.options?.find(option => option.isSelected());\n\n if (selected) {\n this.listKeyManager.updateActiveItem(selected);\n }\n }\n\n /** Update the internal value of the listbox based on the selection model. */\n private _updateInternalValue() {\n const indexCache = new Map<T, number>();\n this.selectionModel.sort((a: T, b: T) => {\n const aIndex = this._getIndexForValue(indexCache, a);\n const bIndex = this._getIndexForValue(indexCache, b);\n return aIndex - bIndex;\n });\n const selected = this.selectionModel.selected;\n this._invalid =\n (!this.multiple && selected.length > 1) || !!this._getInvalidOptionValues(selected).length;\n this.changeDetectorRef.markForCheck();\n }\n\n /**\n * Gets the index of the given value in the given list of options.\n * @param cache The cache of indices found so far\n * @param value The value to find\n * @return The index of the value in the options list\n */\n private _getIndexForValue(cache: Map<T, number>, value: T) {\n const isEqual = this.compareWith || Object.is;\n if (!cache.has(value)) {\n let index = -1;\n for (let i = 0; i < this.options.length; i++) {\n if (isEqual(value, this.options.get(i)!.value)) {\n index = i;\n break;\n }\n }\n cache.set(value, index);\n }\n return cache.get(value)!;\n }\n\n /**\n * Handle the user clicking an option.\n * @param option The option that was clicked.\n */\n private _handleOptionClicked(option: CdkOption<T>, event: MouseEvent) {\n event.preventDefault();\n this.listKeyManager.setActiveItem(option);\n if (event.shiftKey && this.multiple) {\n this.triggerRange(\n option,\n this._getLastTriggeredIndex() ?? this.listKeyManager.activeItemIndex!,\n this.listKeyManager.activeItemIndex!,\n !option.isSelected(),\n );\n } else {\n this.triggerOption(option);\n }\n }\n\n /** Verifies that no two options represent the same value under the compareWith function. */\n private _verifyNoOptionValueCollisions() {\n this.options.changes.pipe(startWith(this.options), takeUntil(this.destroyed)).subscribe(() => {\n const isEqual = this.compareWith ?? Object.is;\n for (let i = 0; i < this.options.length; i++) {\n const option = this.options.get(i)!;\n let duplicate: CdkOption<T> | null = null;\n for (let j = i + 1; j < this.options.length; j++) {\n const other = this.options.get(j)!;\n if (isEqual(option.value, other.value)) {\n duplicate = other;\n break;\n }\n }\n if (duplicate) {\n // TODO(mmalerba): Link to docs about this.\n if (this.compareWith) {\n console.warn(\n `Found multiple CdkOption representing the same value under the given compareWith function`,\n {\n option1: option.element,\n option2: duplicate.element,\n compareWith: this.compareWith,\n },\n );\n } else {\n console.warn(`Found multiple CdkOption with the same value`, {\n option1: option.element,\n option2: duplicate.element,\n });\n }\n return;\n }\n }\n });\n }\n\n /** Verifies that the option values are valid. */\n private _verifyOptionValues() {\n if (this.options && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n const selected = this.selectionModel.selected;\n const invalidValues = this._getInvalidOptionValues(selected);\n\n if (!this.multiple && selected.length > 1) {\n throw Error('Listbox cannot have more than one selected value in multi-selection mode.');\n }\n\n if (invalidValues.length) {\n throw Error('Listbox has selected values that do not match any of its options.');\n }\n }\n }\n\n /**\n * Coerces a value into an array representing a listbox selection.\n * @param value The value to coerce\n * @return An array\n */\n private _coerceValue(value: readonly T[]) {\n return value == null ? [] : coerceArray(value);\n }\n\n /**\n * Get the sublist of values that do not represent valid option values in this listbox.\n * @param values The list of values\n * @return The sublist of values that are not valid option values\n */\n private _getInvalidOptionValues(values: readonly T[]) {\n const isEqual = this.compareWith || Object.is;\n const validValues = (this.options || []).map(option => option.value);\n return values.filter(value => !validValues.some(validValue => isEqual(value, validValue)));\n }\n\n /** Get the index of the last triggered option. */\n private _getLastTriggeredIndex() {\n const index = this.options.toArray().indexOf(this._lastTriggered!);\n return index === -1 ? null : index;\n }\n}\n\n/** Change event that is fired whenever the value of the listbox changes. */\nexport interface ListboxValueChangeEvent<T> {\n /** The new value of the listbox. */\n readonly value: readonly T[];\n\n /** Reference to the listbox that emitted the event. */\n readonly listbox: CdkListbox<T>;\n\n /** Reference to the option that was triggered. */\n readonly option: CdkOption<T> | null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {CdkListbox, CdkOption} from './listbox';\n\nconst EXPORTED_DECLARATIONS = [CdkListbox, CdkOption];\n\n@NgModule({\n imports: [...EXPORTED_DECLARATIONS],\n exports: [...EXPORTED_DECLARATIONS],\n})\nexport class CdkListboxModule {}\n"],"names":["ListboxSelectionModel","SelectionModel","multiple","constructor","initiallySelectedValues","emitChanges","compareWith","isMultipleSelection","select","values","setSelection","CdkOption","id","_id","_generatedId","value","inject","_IdGenerator","getId","typeaheadLabel","disabled","listbox","_disabled","set","signal","enabledTabIndex","_enabledTabIndex","undefined","element","ElementRef","nativeElement","CdkListbox","destroyed","Subject","_clicked","ngOnDestroy","next","complete","isSelected","isActive","toggle","deselect","focus","getLabel","textContent","trim","setActiveStyles","useActiveDescendant","scrollIntoView","block","inline","setInactiveStyles","_handleFocus","_setActiveOption","_getTabIndex","deps","target","i0","ɵɵFactoryTarget","Directive","isStandalone","selector","inputs","booleanAttribute","numberAttribute","host","attributes","listeners","properties","classAttribute","exportAs","ngImport","decorators","args","Input","alias","transform","_cleanupWindowBlur","_invalid","selectionModel","selected","_setSelection","options","_updateInternalValue","_useActiveDescendant","orientation","_orientation","listKeyManager","withHorizontalOrientation","_dir","withVerticalOrientation","fn","navigationWrapDisabled","_navigationWrapDisabled","wrap","withWrap","navigateDisabledOptions","_navigateDisabledOptions","skip","skipPredicate","_skipNonePredicate","_skipDisabledPredicate","valueChange","ngZone","NgZone","changeDetectorRef","ChangeDetectorRef","_lastTriggered","_onTouched","_onChange","_optionClicked","defer","changes","pipe","startWith","switchMap","merge","map","option","event","Directionality","optional","_isBrowser","Platform","isBrowser","_hasFocus","_previousActiveOption","renderer","Renderer2","runOutsideAngular","listen","contains","document","activeElement","ngAfterContentInit","ngDevMode","_verifyNoOptionValueCollisions","_verifyOptionValues","_initKeyManager","changed","takeUntil","subscribe","filter","_handleOptionClicked","destroy","toggleValue","clear","selectValue","deselectValue","setAllSelected","isValueSelected","activeItem","registerOnChange","registerOnTouched","writeValue","setDisabledState","isDisabled","markForCheck","triggerOption","triggerRange","trigger","from","to","on","isEqual","Object","is","updateValues","slice","Math","max","min","length","updateValue","selectedIndex","findIndex","selectedValue","push","splice","setActiveItem","_setNextFocusToSelectedOption","setNextItemActive","_focusActiveOption","_handleKeydown","keyCode","previousActiveIndex","activeItemIndex","ctrlKeys","A","hasModifierKey","preventDefault","SPACE","ENTER","_getLastTriggeredIndex","HOME","setFirstItemActive","END","setLastItemActive","isNavKey","UP_ARROW","DOWN_ARROW","LEFT_ARROW","RIGHT_ARROW","onKeydown","shiftKey","_handleFocusIn","_handleFocusOut","otherElement","relatedTarget","_getAriaActiveDescendant","ActiveDescendantKeyManager","withTypeAhead","withHomeAndEnd","withAllowedModifierKeys","Promise","resolve","then","change","activeOption","find","_coerceValue","updateActiveItem","indexCache","Map","sort","a","b","aIndex","_getIndexForValue","bIndex","_getInvalidOptionValues","cache","has","index","i","get","duplicate","j","other","console","warn","option1","option2","invalidValues","Error","coerceArray","validValues","some","validValue","toArray","indexOf","outputs","providers","provide","NG_VALUE_ACCESSOR","useExisting","forwardRef","multi","queries","propertyName","predicate","descendants","Output","ContentChildren","EXPORTED_DECLARATIONS","CdkListboxModule","NgModule","ɵmod","ɵɵngDeclareNgModule","minVersion","version","type","exports","imports"],"mappings":"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