UNPKG

@angular/material

Version:
1 lines 149 kB
{"version":3,"file":"chips.mjs","sources":["../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/tokens.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-action.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-icons.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip.html","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-option.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-option.html","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-edit-input.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-row.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-row.html","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-set.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-listbox.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-grid.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/chip-input.ts","../../../../../darwin_arm64-fastbuild-ST-46c76129e412/bin/src/material/chips/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 {ENTER} from '@angular/cdk/keycodes';\nimport {InjectionToken} from '@angular/core';\n\n/** Default options, for the chips module, that can be overridden. */\nexport interface MatChipsDefaultOptions {\n /** The list of key codes that will trigger a chipEnd event. */\n separatorKeyCodes: readonly number[] | ReadonlySet<number>;\n\n /** Whether icon indicators should be hidden for single-selection. */\n hideSingleSelectionIndicator?: boolean;\n}\n\n/** Injection token to be used to override the default options for the chips module. */\nexport const MAT_CHIPS_DEFAULT_OPTIONS = new InjectionToken<MatChipsDefaultOptions>(\n 'mat-chips-default-options',\n {\n providedIn: 'root',\n factory: () => ({\n separatorKeyCodes: [ENTER],\n }),\n },\n);\n\n/**\n * Injection token that can be used to reference instances of `MatChipAvatar`. It serves as\n * alternative token to the actual `MatChipAvatar` class which could cause unnecessary\n * retention of the class and its directive metadata.\n */\nexport const MAT_CHIP_AVATAR = new InjectionToken('MatChipAvatar');\n\n/**\n * Injection token that can be used to reference instances of `MatChipTrailingIcon`. It serves as\n * alternative token to the actual `MatChipTrailingIcon` class which could cause unnecessary\n * retention of the class and its directive metadata.\n */\nexport const MAT_CHIP_TRAILING_ICON = new InjectionToken('MatChipTrailingIcon');\n\n/**\n * Injection token that can be used to reference instances of `MatChipRemove`. It serves as\n * alternative token to the actual `MatChipRemove` class which could cause unnecessary\n * retention of the class and its directive metadata.\n */\nexport const MAT_CHIP_REMOVE = new InjectionToken('MatChipRemove');\n\n/**\n * Injection token used to avoid a circular dependency between the `MatChip` and `MatChipAction`.\n */\nexport const MAT_CHIP = new InjectionToken('MatChip');\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 {\n Directive,\n ElementRef,\n Input,\n booleanAttribute,\n numberAttribute,\n inject,\n} from '@angular/core';\nimport {ENTER, SPACE} from '@angular/cdk/keycodes';\nimport {MAT_CHIP} from './tokens';\nimport {_CdkPrivateStyleLoader} from '@angular/cdk/private';\nimport {_StructuralStylesLoader} from '../core';\n\n/**\n * Section within a chip.\n * @docs-private\n */\n@Directive({\n selector: '[matChipAction]',\n host: {\n 'class': 'mdc-evolution-chip__action mat-mdc-chip-action',\n '[class.mdc-evolution-chip__action--primary]': '_isPrimary',\n '[class.mdc-evolution-chip__action--presentational]': '!isInteractive',\n '[class.mdc-evolution-chip__action--trailing]': '!_isPrimary',\n '[attr.tabindex]': '_getTabindex()',\n '[attr.disabled]': '_getDisabledAttribute()',\n '[attr.aria-disabled]': 'disabled',\n '(click)': '_handleClick($event)',\n '(keydown)': '_handleKeydown($event)',\n },\n})\nexport class MatChipAction {\n _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n protected _parentChip = inject<{\n _handlePrimaryActionInteraction(): void;\n remove(): void;\n disabled: boolean;\n _isEditing?: boolean;\n }>(MAT_CHIP);\n\n /** Whether the action is interactive. */\n @Input() isInteractive = true;\n\n /** Whether this is the primary action in the chip. */\n _isPrimary = true;\n\n /** Whether the action is disabled. */\n @Input({transform: booleanAttribute})\n get disabled(): boolean {\n return this._disabled || this._parentChip?.disabled || false;\n }\n set disabled(value: boolean) {\n this._disabled = value;\n }\n private _disabled = false;\n\n /** Tab index of the action. */\n @Input({\n transform: (value: unknown) => (value == null ? -1 : numberAttribute(value)),\n })\n tabIndex: number = -1;\n\n /**\n * Private API to allow focusing this chip when it is disabled.\n */\n @Input()\n private _allowFocusWhenDisabled = false;\n\n /**\n * Determine the value of the disabled attribute for this chip action.\n */\n protected _getDisabledAttribute(): string | null {\n // When this chip action is disabled and focusing disabled chips is not permitted, return empty\n // string to indicate that disabled attribute should be included.\n return this.disabled && !this._allowFocusWhenDisabled ? '' : null;\n }\n\n /**\n * Determine the value of the tabindex attribute for this chip action.\n */\n protected _getTabindex(): string | null {\n return (this.disabled && !this._allowFocusWhenDisabled) || !this.isInteractive\n ? null\n : this.tabIndex.toString();\n }\n\n constructor(...args: unknown[]);\n\n constructor() {\n inject(_CdkPrivateStyleLoader).load(_StructuralStylesLoader);\n if (this._elementRef.nativeElement.nodeName === 'BUTTON') {\n this._elementRef.nativeElement.setAttribute('type', 'button');\n }\n }\n\n focus() {\n this._elementRef.nativeElement.focus();\n }\n\n _handleClick(event: MouseEvent) {\n if (!this.disabled && this.isInteractive && this._isPrimary) {\n event.preventDefault();\n this._parentChip._handlePrimaryActionInteraction();\n }\n }\n\n _handleKeydown(event: KeyboardEvent) {\n if (\n (event.keyCode === ENTER || event.keyCode === SPACE) &&\n !this.disabled &&\n this.isInteractive &&\n this._isPrimary &&\n !this._parentChip._isEditing\n ) {\n event.preventDefault();\n this._parentChip._handlePrimaryActionInteraction();\n }\n }\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 {ENTER, SPACE} from '@angular/cdk/keycodes';\nimport {Directive} from '@angular/core';\nimport {MatChipAction} from './chip-action';\nimport {MAT_CHIP_AVATAR, MAT_CHIP_REMOVE, MAT_CHIP_TRAILING_ICON} from './tokens';\n\n/** Avatar image within a chip. */\n@Directive({\n selector: 'mat-chip-avatar, [matChipAvatar]',\n host: {\n 'class': 'mat-mdc-chip-avatar mdc-evolution-chip__icon mdc-evolution-chip__icon--primary',\n 'role': 'img',\n },\n providers: [{provide: MAT_CHIP_AVATAR, useExisting: MatChipAvatar}],\n})\nexport class MatChipAvatar {}\n\n/** Non-interactive trailing icon in a chip. */\n@Directive({\n selector: 'mat-chip-trailing-icon, [matChipTrailingIcon]',\n host: {\n 'class':\n 'mat-mdc-chip-trailing-icon mdc-evolution-chip__icon mdc-evolution-chip__icon--trailing',\n 'aria-hidden': 'true',\n },\n providers: [{provide: MAT_CHIP_TRAILING_ICON, useExisting: MatChipTrailingIcon}],\n})\nexport class MatChipTrailingIcon extends MatChipAction {\n /**\n * MDC considers all trailing actions as a remove icon,\n * but we support non-interactive trailing icons.\n */\n override isInteractive = false;\n\n override _isPrimary = false;\n}\n\n/**\n * Directive to remove the parent chip when the trailing icon is clicked or\n * when the ENTER key is pressed on it.\n *\n * Recommended for use with the Material Design \"cancel\" icon\n * available at https://material.io/icons/#ic_cancel.\n *\n * Example:\n *\n * ```\n * <mat-chip>\n * <mat-icon matChipRemove>cancel</mat-icon>\n * </mat-chip>\n * ```\n */\n\n@Directive({\n selector: '[matChipRemove]',\n host: {\n 'class':\n 'mat-mdc-chip-remove mat-mdc-chip-trailing-icon mat-focus-indicator ' +\n 'mdc-evolution-chip__icon mdc-evolution-chip__icon--trailing',\n 'role': 'button',\n '[attr.aria-hidden]': 'null',\n },\n providers: [{provide: MAT_CHIP_REMOVE, useExisting: MatChipRemove}],\n})\nexport class MatChipRemove extends MatChipAction {\n override _isPrimary = false;\n\n override _handleClick(event: MouseEvent): void {\n if (!this.disabled) {\n event.stopPropagation();\n event.preventDefault();\n this._parentChip.remove();\n }\n }\n\n override _handleKeydown(event: KeyboardEvent) {\n if ((event.keyCode === ENTER || event.keyCode === SPACE) && !this.disabled) {\n event.stopPropagation();\n event.preventDefault();\n this._parentChip.remove();\n }\n }\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 {FocusMonitor, _IdGenerator} from '@angular/cdk/a11y';\nimport {BACKSPACE, DELETE} from '@angular/cdk/keycodes';\nimport {_CdkPrivateStyleLoader, _VisuallyHiddenLoader} from '@angular/cdk/private';\nimport {DOCUMENT} from '@angular/common';\nimport {\n ANIMATION_MODULE_TYPE,\n AfterContentInit,\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ContentChildren,\n DoCheck,\n ElementRef,\n EventEmitter,\n Injector,\n Input,\n NgZone,\n OnDestroy,\n OnInit,\n Output,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n booleanAttribute,\n inject,\n} from '@angular/core';\nimport {\n MAT_RIPPLE_GLOBAL_OPTIONS,\n MatRippleLoader,\n RippleGlobalOptions,\n _StructuralStylesLoader,\n} from '../core';\nimport {Subject, Subscription, merge} from 'rxjs';\nimport {MatChipAction} from './chip-action';\nimport {MatChipAvatar, MatChipRemove, MatChipTrailingIcon} from './chip-icons';\nimport {MAT_CHIP, MAT_CHIP_AVATAR, MAT_CHIP_REMOVE, MAT_CHIP_TRAILING_ICON} from './tokens';\n\n/** Represents an event fired on an individual `mat-chip`. */\nexport interface MatChipEvent {\n /** The chip the event was fired on. */\n chip: MatChip;\n}\n\n/**\n * Material design styled Chip base component. Used inside the MatChipSet component.\n *\n * Extended by MatChipOption and MatChipRow for different interaction patterns.\n */\n@Component({\n selector: 'mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]',\n exportAs: 'matChip',\n templateUrl: 'chip.html',\n styleUrl: 'chip.css',\n host: {\n 'class': 'mat-mdc-chip',\n '[class]': '\"mat-\" + (color || \"primary\")',\n '[class.mdc-evolution-chip]': '!_isBasicChip',\n '[class.mdc-evolution-chip--disabled]': 'disabled',\n '[class.mdc-evolution-chip--with-trailing-action]': '_hasTrailingIcon()',\n '[class.mdc-evolution-chip--with-primary-graphic]': 'leadingIcon',\n '[class.mdc-evolution-chip--with-primary-icon]': 'leadingIcon',\n '[class.mdc-evolution-chip--with-avatar]': 'leadingIcon',\n '[class.mat-mdc-chip-with-avatar]': 'leadingIcon',\n '[class.mat-mdc-chip-highlighted]': 'highlighted',\n '[class.mat-mdc-chip-disabled]': 'disabled',\n '[class.mat-mdc-basic-chip]': '_isBasicChip',\n '[class.mat-mdc-standard-chip]': '!_isBasicChip',\n '[class.mat-mdc-chip-with-trailing-icon]': '_hasTrailingIcon()',\n '[class._mat-animation-noopable]': '_animationsDisabled',\n '[id]': 'id',\n '[attr.role]': 'role',\n '[attr.aria-label]': 'ariaLabel',\n '(keydown)': '_handleKeydown($event)',\n },\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{provide: MAT_CHIP, useExisting: MatChip}],\n imports: [MatChipAction],\n})\nexport class MatChip implements OnInit, AfterViewInit, AfterContentInit, DoCheck, OnDestroy {\n _changeDetectorRef = inject(ChangeDetectorRef);\n _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n protected _ngZone = inject(NgZone);\n private _focusMonitor = inject(FocusMonitor);\n private _globalRippleOptions = inject<RippleGlobalOptions>(MAT_RIPPLE_GLOBAL_OPTIONS, {\n optional: true,\n });\n\n protected _document = inject(DOCUMENT);\n\n /** Emits when the chip is focused. */\n readonly _onFocus = new Subject<MatChipEvent>();\n\n /** Emits when the chip is blurred. */\n readonly _onBlur = new Subject<MatChipEvent>();\n\n /** Whether this chip is a basic (unstyled) chip. */\n _isBasicChip: boolean;\n\n /** Role for the root of the chip. */\n @Input() role: string | null = null;\n\n /** Whether the chip has focus. */\n private _hasFocusInternal = false;\n\n /** Whether moving focus into the chip is pending. */\n private _pendingFocus: boolean;\n\n /** Subscription to changes in the chip's actions. */\n private _actionChanges: Subscription | undefined;\n\n /** Whether animations for the chip are enabled. */\n _animationsDisabled: boolean;\n\n /** All avatars present in the chip. */\n @ContentChildren(MAT_CHIP_AVATAR, {descendants: true})\n protected _allLeadingIcons: QueryList<MatChipAvatar>;\n\n /** All trailing icons present in the chip. */\n @ContentChildren(MAT_CHIP_TRAILING_ICON, {descendants: true})\n protected _allTrailingIcons: QueryList<MatChipTrailingIcon>;\n\n /** All remove icons present in the chip. */\n @ContentChildren(MAT_CHIP_REMOVE, {descendants: true})\n protected _allRemoveIcons: QueryList<MatChipRemove>;\n\n _hasFocus() {\n return this._hasFocusInternal;\n }\n\n /** A unique id for the chip. If none is supplied, it will be auto-generated. */\n @Input() id: string = inject(_IdGenerator).getId('mat-mdc-chip-');\n\n // TODO(#26104): Consider deprecating and using `_computeAriaAccessibleName` instead.\n // `ariaLabel` may be unnecessary, and `_computeAriaAccessibleName` only supports\n // datepicker's use case.\n /** ARIA label for the content of the chip. */\n @Input('aria-label') ariaLabel: string | null = null;\n\n // TODO(#26104): Consider deprecating and using `_computeAriaAccessibleName` instead.\n // `ariaDescription` may be unnecessary, and `_computeAriaAccessibleName` only supports\n // datepicker's use case.\n /** ARIA description for the content of the chip. */\n @Input('aria-description') ariaDescription: string | null = null;\n\n /** Id of a span that contains this chip's aria description. */\n _ariaDescriptionId = `${this.id}-aria-description`;\n\n /** Whether the chip list is disabled. */\n _chipListDisabled: boolean = false;\n\n private _textElement!: HTMLElement;\n\n /**\n * The value of the chip. Defaults to the content inside\n * the `mat-mdc-chip-action-label` element.\n */\n @Input()\n get value(): any {\n return this._value !== undefined ? this._value : this._textElement.textContent!.trim();\n }\n set value(value: any) {\n this._value = value;\n }\n protected _value: any;\n\n // TODO: should be typed as `ThemePalette` but internal apps pass in arbitrary strings.\n /**\n * Theme color of the chip. This API is supported in M2 themes only, it has no\n * effect in M3 themes. For color customization in M3, see https://material.angular.io/components/chips/styling.\n *\n * For information on applying color variants in M3, see\n * https://material.angular.io/guide/material-2-theming#optional-add-backwards-compatibility-styles-for-color-variants\n */\n @Input() color?: string | null;\n\n /**\n * Determines whether or not the chip displays the remove styling and emits (removed) events.\n */\n @Input({transform: booleanAttribute})\n removable: boolean = true;\n\n /**\n * Colors the chip for emphasis as if it were selected.\n */\n @Input({transform: booleanAttribute})\n highlighted: boolean = false;\n\n /** Whether the ripple effect is disabled or not. */\n @Input({transform: booleanAttribute})\n disableRipple: boolean = false;\n\n /** Whether the chip is disabled. */\n @Input({transform: booleanAttribute})\n get disabled(): boolean {\n return this._disabled || this._chipListDisabled;\n }\n set disabled(value: boolean) {\n this._disabled = value;\n }\n private _disabled = false;\n\n /** Emitted when a chip is to be removed. */\n @Output() readonly removed: EventEmitter<MatChipEvent> = new EventEmitter<MatChipEvent>();\n\n /** Emitted when the chip is destroyed. */\n @Output() readonly destroyed: EventEmitter<MatChipEvent> = new EventEmitter<MatChipEvent>();\n\n /** The unstyled chip selector for this component. */\n protected basicChipAttrName = 'mat-basic-chip';\n\n /** The chip's leading icon. */\n @ContentChild(MAT_CHIP_AVATAR) leadingIcon: MatChipAvatar;\n\n /** The chip's trailing icon. */\n @ContentChild(MAT_CHIP_TRAILING_ICON) trailingIcon: MatChipTrailingIcon;\n\n /** The chip's trailing remove icon. */\n @ContentChild(MAT_CHIP_REMOVE) removeIcon: MatChipRemove;\n\n /** Action receiving the primary set of user interactions. */\n @ViewChild(MatChipAction) primaryAction: MatChipAction;\n\n /**\n * Handles the lazy creation of the MatChip ripple.\n * Used to improve initial load time of large applications.\n */\n private _rippleLoader: MatRippleLoader = inject(MatRippleLoader);\n\n protected _injector = inject(Injector);\n\n constructor(...args: unknown[]);\n\n constructor() {\n const styleLoader = inject(_CdkPrivateStyleLoader);\n styleLoader.load(_StructuralStylesLoader);\n styleLoader.load(_VisuallyHiddenLoader);\n const animationMode = inject(ANIMATION_MODULE_TYPE, {optional: true});\n this._animationsDisabled = animationMode === 'NoopAnimations';\n this._monitorFocus();\n\n this._rippleLoader?.configureRipple(this._elementRef.nativeElement, {\n className: 'mat-mdc-chip-ripple',\n disabled: this._isRippleDisabled(),\n });\n }\n\n ngOnInit() {\n // This check needs to happen in `ngOnInit` so the overridden value of\n // `basicChipAttrName` coming from base classes can be picked up.\n const element = this._elementRef.nativeElement;\n this._isBasicChip =\n element.hasAttribute(this.basicChipAttrName) ||\n element.tagName.toLowerCase() === this.basicChipAttrName;\n }\n\n ngAfterViewInit() {\n this._textElement = this._elementRef.nativeElement.querySelector('.mat-mdc-chip-action-label')!;\n\n if (this._pendingFocus) {\n this._pendingFocus = false;\n this.focus();\n }\n }\n\n ngAfterContentInit(): void {\n // Since the styling depends on the presence of some\n // actions, we have to mark for check on changes.\n this._actionChanges = merge(\n this._allLeadingIcons.changes,\n this._allTrailingIcons.changes,\n this._allRemoveIcons.changes,\n ).subscribe(() => this._changeDetectorRef.markForCheck());\n }\n\n ngDoCheck(): void {\n this._rippleLoader.setDisabled(this._elementRef.nativeElement, this._isRippleDisabled());\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef);\n this._rippleLoader?.destroyRipple(this._elementRef.nativeElement);\n this._actionChanges?.unsubscribe();\n this.destroyed.emit({chip: this});\n this.destroyed.complete();\n }\n\n /**\n * Allows for programmatic removal of the chip.\n *\n * Informs any listeners of the removal request. Does not remove the chip from the DOM.\n */\n remove(): void {\n if (this.removable) {\n this.removed.emit({chip: this});\n }\n }\n\n /** Whether or not the ripple should be disabled. */\n _isRippleDisabled(): boolean {\n return (\n this.disabled ||\n this.disableRipple ||\n this._animationsDisabled ||\n this._isBasicChip ||\n !!this._globalRippleOptions?.disabled\n );\n }\n\n /** Returns whether the chip has a trailing icon. */\n _hasTrailingIcon() {\n return !!(this.trailingIcon || this.removeIcon);\n }\n\n /** Handles keyboard events on the chip. */\n _handleKeydown(event: KeyboardEvent) {\n // Ignore backspace events where the user is holding down the key\n // so that we don't accidentally remove too many chips.\n if ((event.keyCode === BACKSPACE && !event.repeat) || event.keyCode === DELETE) {\n event.preventDefault();\n this.remove();\n }\n }\n\n /** Allows for programmatic focusing of the chip. */\n focus(): void {\n if (!this.disabled) {\n // If `focus` is called before `ngAfterViewInit`, we won't have access to the primary action.\n // This can happen if the consumer tries to focus a chip immediately after it is added.\n // Queue the method to be called again on init.\n if (this.primaryAction) {\n this.primaryAction.focus();\n } else {\n this._pendingFocus = true;\n }\n }\n }\n\n /** Gets the action that contains a specific target node. */\n _getSourceAction(target: Node): MatChipAction | undefined {\n return this._getActions().find(action => {\n const element = action._elementRef.nativeElement;\n return element === target || element.contains(target);\n });\n }\n\n /** Gets all of the actions within the chip. */\n _getActions(): MatChipAction[] {\n const result: MatChipAction[] = [];\n\n if (this.primaryAction) {\n result.push(this.primaryAction);\n }\n\n if (this.removeIcon) {\n result.push(this.removeIcon);\n }\n\n if (this.trailingIcon) {\n result.push(this.trailingIcon);\n }\n\n return result;\n }\n\n /** Handles interactions with the primary action of the chip. */\n _handlePrimaryActionInteraction() {\n // Empty here, but is overwritten in child classes.\n }\n\n /** Starts the focus monitoring process on the chip. */\n private _monitorFocus() {\n this._focusMonitor.monitor(this._elementRef, true).subscribe(origin => {\n const hasFocus = origin !== null;\n\n if (hasFocus !== this._hasFocusInternal) {\n this._hasFocusInternal = hasFocus;\n\n if (hasFocus) {\n this._onFocus.next({chip: this});\n } else {\n // When animations are enabled, Angular may end up removing the chip from the DOM a little\n // earlier than usual, causing it to be blurred and throwing off the logic in the chip list\n // that moves focus to the next item. To work around the issue, we defer marking the chip\n // as not focused until after the next render.\n this._changeDetectorRef.markForCheck();\n setTimeout(() => this._ngZone.run(() => this._onBlur.next({chip: this})));\n }\n }\n });\n }\n}\n","<span class=\"mat-mdc-chip-focus-overlay\"></span>\n\n<span class=\"mdc-evolution-chip__cell mdc-evolution-chip__cell--primary\">\n <span matChipAction [isInteractive]=\"false\">\n @if (leadingIcon) {\n <span class=\"mdc-evolution-chip__graphic mat-mdc-chip-graphic\">\n <ng-content select=\"mat-chip-avatar, [matChipAvatar]\"></ng-content>\n </span>\n }\n <span class=\"mdc-evolution-chip__text-label mat-mdc-chip-action-label\">\n <ng-content></ng-content>\n <span class=\"mat-mdc-chip-primary-focus-indicator mat-focus-indicator\"></span>\n </span>\n </span>\n</span>\n\n@if (_hasTrailingIcon()) {\n <span class=\"mdc-evolution-chip__cell mdc-evolution-chip__cell--trailing\">\n <ng-content select=\"mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon]\"></ng-content>\n </span>\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 {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n Output,\n ViewEncapsulation,\n OnInit,\n inject,\n booleanAttribute,\n} from '@angular/core';\nimport {MatChip} from './chip';\nimport {MAT_CHIP, MAT_CHIPS_DEFAULT_OPTIONS} from './tokens';\nimport {MatChipAction} from './chip-action';\n\n/** Event object emitted by MatChipOption when selected or deselected. */\nexport class MatChipSelectionChange {\n constructor(\n /** Reference to the chip that emitted the event. */\n public source: MatChipOption,\n /** Whether the chip that emitted the event is selected. */\n public selected: boolean,\n /** Whether the selection change was a result of a user interaction. */\n public isUserInput = false,\n ) {}\n}\n\n/**\n * An extension of the MatChip component that supports chip selection. Used with MatChipListbox.\n *\n * Unlike other chips, the user can focus on disabled chip options inside a MatChipListbox. The\n * user cannot click disabled chips.\n */\n@Component({\n selector: 'mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]',\n templateUrl: 'chip-option.html',\n styleUrl: 'chip.css',\n host: {\n 'class': 'mat-mdc-chip mat-mdc-chip-option',\n '[class.mdc-evolution-chip]': '!_isBasicChip',\n '[class.mdc-evolution-chip--filter]': '!_isBasicChip',\n '[class.mdc-evolution-chip--selectable]': '!_isBasicChip',\n '[class.mat-mdc-chip-selected]': 'selected',\n '[class.mat-mdc-chip-multiple]': '_chipListMultiple',\n '[class.mat-mdc-chip-disabled]': 'disabled',\n '[class.mat-mdc-chip-with-avatar]': 'leadingIcon',\n '[class.mdc-evolution-chip--disabled]': 'disabled',\n '[class.mdc-evolution-chip--selected]': 'selected',\n // This class enables the transition on the checkmark. Usually MDC adds it when selection\n // starts and removes it once the animation is finished. We don't need to go through all\n // the trouble, because we only care about the selection animation. MDC needs to do it,\n // because they also have an exit animation that we don't care about.\n '[class.mdc-evolution-chip--selecting]': '!_animationsDisabled',\n '[class.mdc-evolution-chip--with-trailing-action]': '_hasTrailingIcon()',\n '[class.mdc-evolution-chip--with-primary-icon]': 'leadingIcon',\n '[class.mdc-evolution-chip--with-primary-graphic]': '_hasLeadingGraphic()',\n '[class.mdc-evolution-chip--with-avatar]': 'leadingIcon',\n '[class.mat-mdc-chip-highlighted]': 'highlighted',\n '[class.mat-mdc-chip-with-trailing-icon]': '_hasTrailingIcon()',\n '[attr.tabindex]': 'null',\n '[attr.aria-label]': 'null',\n '[attr.aria-description]': 'null',\n '[attr.role]': 'role',\n '[id]': 'id',\n },\n providers: [\n {provide: MatChip, useExisting: MatChipOption},\n {provide: MAT_CHIP, useExisting: MatChipOption},\n ],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MatChipAction],\n})\nexport class MatChipOption extends MatChip implements OnInit {\n /** Default chip options. */\n private _defaultOptions = inject(MAT_CHIPS_DEFAULT_OPTIONS, {optional: true});\n\n /** Whether the chip list is selectable. */\n chipListSelectable: boolean = true;\n\n /** Whether the chip list is in multi-selection mode. */\n _chipListMultiple: boolean = false;\n\n /** Whether the chip list hides single-selection indicator. */\n _chipListHideSingleSelectionIndicator: boolean =\n this._defaultOptions?.hideSingleSelectionIndicator ?? false;\n\n /**\n * Whether or not the chip is selectable.\n *\n * When a chip is not selectable, changes to its selected state are always\n * ignored. By default an option chip is selectable, and it becomes\n * non-selectable if its parent chip list is not selectable.\n */\n @Input({transform: booleanAttribute})\n get selectable(): boolean {\n return this._selectable && this.chipListSelectable;\n }\n set selectable(value: boolean) {\n this._selectable = value;\n this._changeDetectorRef.markForCheck();\n }\n protected _selectable: boolean = true;\n\n /** Whether the chip is selected. */\n @Input({transform: booleanAttribute})\n get selected(): boolean {\n return this._selected;\n }\n set selected(value: boolean) {\n this._setSelectedState(value, false, true);\n }\n private _selected = false;\n\n /**\n * The ARIA selected applied to the chip. Conforms to WAI ARIA best practices for listbox\n * interaction patterns.\n *\n * From [WAI ARIA Listbox authoring practices guide](\n * https://www.w3.org/WAI/ARIA/apg/patterns/listbox/):\n * \"If any options are selected, each selected option has either aria-selected or aria-checked\n * set to true. All options that are selectable but not selected have either aria-selected or\n * aria-checked set to false.\"\n *\n * Set `aria-selected=\"false\"` on not-selected listbox options that are selectable to fix\n * VoiceOver reading every option as \"selected\" (#25736).\n */\n get ariaSelected(): string | null {\n return this.selectable ? this.selected.toString() : null;\n }\n\n /** The unstyled chip selector for this component. */\n protected override basicChipAttrName = 'mat-basic-chip-option';\n\n /** Emitted when the chip is selected or deselected. */\n @Output() readonly selectionChange: EventEmitter<MatChipSelectionChange> =\n new EventEmitter<MatChipSelectionChange>();\n\n override ngOnInit() {\n super.ngOnInit();\n this.role = 'presentation';\n }\n\n /** Selects the chip. */\n select(): void {\n this._setSelectedState(true, false, true);\n }\n\n /** Deselects the chip. */\n deselect(): void {\n this._setSelectedState(false, false, true);\n }\n\n /** Selects this chip and emits userInputSelection event */\n selectViaInteraction(): void {\n this._setSelectedState(true, true, true);\n }\n\n /** Toggles the current selected state of this chip. */\n toggleSelected(isUserInput: boolean = false): boolean {\n this._setSelectedState(!this.selected, isUserInput, true);\n return this.selected;\n }\n\n override _handlePrimaryActionInteraction() {\n if (!this.disabled) {\n // Interacting with the primary action implies that the chip already has focus, however\n // there's a bug in Safari where focus ends up lingering on the previous chip (see #27544).\n // We work around it by explicitly focusing the primary action of the current chip.\n this.focus();\n\n if (this.selectable) {\n this.toggleSelected(true);\n }\n }\n }\n\n _hasLeadingGraphic() {\n if (this.leadingIcon) {\n return true;\n }\n\n // The checkmark graphic communicates selected state for both single-select and multi-select.\n // Include checkmark in single-select to fix a11y issue where selected state is communicated\n // visually only using color (#25886).\n return !this._chipListHideSingleSelectionIndicator || this._chipListMultiple;\n }\n\n _setSelectedState(isSelected: boolean, isUserInput: boolean, emitEvent: boolean) {\n if (isSelected !== this.selected) {\n this._selected = isSelected;\n\n if (emitEvent) {\n this.selectionChange.emit({\n source: this,\n isUserInput,\n selected: this.selected,\n });\n }\n\n this._changeDetectorRef.markForCheck();\n }\n }\n}\n","<span class=\"mat-mdc-chip-focus-overlay\"></span>\n\n<span class=\"mdc-evolution-chip__cell mdc-evolution-chip__cell--primary\">\n <button\n matChipAction\n [_allowFocusWhenDisabled]=\"true\"\n [attr.aria-selected]=\"ariaSelected\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-describedby]=\"_ariaDescriptionId\"\n role=\"option\">\n @if (_hasLeadingGraphic()) {\n <span class=\"mdc-evolution-chip__graphic mat-mdc-chip-graphic\">\n <ng-content select=\"mat-chip-avatar, [matChipAvatar]\"></ng-content>\n <span class=\"mdc-evolution-chip__checkmark\">\n <svg\n class=\"mdc-evolution-chip__checkmark-svg\"\n viewBox=\"-2 -3 30 30\"\n focusable=\"false\"\n aria-hidden=\"true\">\n <path class=\"mdc-evolution-chip__checkmark-path\"\n fill=\"none\" stroke=\"currentColor\" d=\"M1.73,12.91 8.1,19.28 22.79,4.59\" />\n </svg>\n </span>\n </span>\n }\n <span class=\"mdc-evolution-chip__text-label mat-mdc-chip-action-label\">\n <ng-content></ng-content>\n <span class=\"mat-mdc-chip-primary-focus-indicator mat-focus-indicator\"></span>\n </span>\n </button>\n</span>\n\n@if (_hasTrailingIcon()) {\n <span class=\"mdc-evolution-chip__cell mdc-evolution-chip__cell--trailing\">\n <ng-content select=\"mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon]\"></ng-content>\n </span>\n}\n\n<span class=\"cdk-visually-hidden\" [id]=\"_ariaDescriptionId\">{{ariaDescription}}</span>\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 {Directive, ElementRef, inject} from '@angular/core';\nimport {DOCUMENT} from '@angular/common';\n\n/**\n * A directive that makes a span editable and exposes functions to modify and retrieve the\n * element's contents.\n */\n@Directive({\n selector: 'span[matChipEditInput]',\n host: {\n 'class': 'mat-chip-edit-input',\n 'role': 'textbox',\n 'tabindex': '-1',\n 'contenteditable': 'true',\n },\n})\nexport class MatChipEditInput {\n private readonly _elementRef = inject(ElementRef);\n private readonly _document = inject(DOCUMENT);\n\n constructor(...args: unknown[]);\n constructor() {}\n\n initialize(initialValue: string) {\n this.getNativeElement().focus();\n this.setValue(initialValue);\n }\n\n getNativeElement(): HTMLElement {\n return this._elementRef.nativeElement;\n }\n\n setValue(value: string) {\n this.getNativeElement().textContent = value;\n this._moveCursorToEndOfInput();\n }\n\n getValue(): string {\n return this.getNativeElement().textContent || '';\n }\n\n private _moveCursorToEndOfInput() {\n const range = this._document.createRange();\n range.selectNodeContents(this.getNativeElement());\n range.collapse(false);\n const sel = window.getSelection()!;\n sel.removeAllRanges();\n sel.addRange(range);\n }\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 {ENTER} from '@angular/cdk/keycodes';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ContentChild,\n EventEmitter,\n Input,\n Output,\n ViewChild,\n ViewEncapsulation,\n afterNextRender,\n} from '@angular/core';\nimport {takeUntil} from 'rxjs/operators';\nimport {MatChip, MatChipEvent} from './chip';\nimport {MatChipAction} from './chip-action';\nimport {MatChipEditInput} from './chip-edit-input';\nimport {MAT_CHIP} from './tokens';\n\n/** Represents an event fired on an individual `mat-chip` when it is edited. */\nexport interface MatChipEditedEvent extends MatChipEvent {\n /** The final edit value. */\n value: string;\n}\n\n/**\n * An extension of the MatChip component used with MatChipGrid and\n * the matChipInputFor directive.\n */\n@Component({\n selector: 'mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]',\n templateUrl: 'chip-row.html',\n styleUrl: 'chip.css',\n host: {\n 'class': 'mat-mdc-chip mat-mdc-chip-row mdc-evolution-chip',\n '[class.mat-mdc-chip-with-avatar]': 'leadingIcon',\n '[class.mat-mdc-chip-disabled]': 'disabled',\n '[class.mat-mdc-chip-editing]': '_isEditing',\n '[class.mat-mdc-chip-editable]': 'editable',\n '[class.mdc-evolution-chip--disabled]': 'disabled',\n '[class.mdc-evolution-chip--with-trailing-action]': '_hasTrailingIcon()',\n '[class.mdc-evolution-chip--with-primary-graphic]': 'leadingIcon',\n '[class.mdc-evolution-chip--with-primary-icon]': 'leadingIcon',\n '[class.mdc-evolution-chip--with-avatar]': 'leadingIcon',\n '[class.mat-mdc-chip-highlighted]': 'highlighted',\n '[class.mat-mdc-chip-with-trailing-icon]': '_hasTrailingIcon()',\n '[id]': 'id',\n // Has to have a negative tabindex in order to capture\n // focus and redirect it to the primary action.\n '[attr.tabindex]': 'disabled ? null : -1',\n '[attr.aria-label]': 'null',\n '[attr.aria-description]': 'null',\n '[attr.role]': 'role',\n '(focus)': '_handleFocus()',\n '(dblclick)': '_handleDoubleclick($event)',\n },\n providers: [\n {provide: MatChip, useExisting: MatChipRow},\n {provide: MAT_CHIP, useExisting: MatChipRow},\n ],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MatChipAction, MatChipEditInput],\n})\nexport class MatChipRow extends MatChip implements AfterViewInit {\n protected override basicChipAttrName = 'mat-basic-chip-row';\n\n /**\n * The editing action has to be triggered in a timeout. While we're waiting on it, a blur\n * event might occur which will interrupt the editing. This flag is used to avoid interruptions\n * while the editing action is being initialized.\n */\n private _editStartPending = false;\n\n @Input() editable: boolean = false;\n\n /** Emitted when the chip is edited. */\n @Output() readonly edited: EventEmitter<MatChipEditedEvent> =\n new EventEmitter<MatChipEditedEvent>();\n\n /** The default chip edit input that is used if none is projected into this chip row. */\n @ViewChild(MatChipEditInput) defaultEditInput?: MatChipEditInput;\n\n /** The projected chip edit input. */\n @ContentChild(MatChipEditInput) contentEditInput?: MatChipEditInput;\n\n _isEditing = false;\n\n constructor(...args: unknown[]);\n\n constructor() {\n super();\n\n this.role = 'row';\n this._onBlur.pipe(takeUntil(this.destroyed)).subscribe(() => {\n if (this._isEditing && !this._editStartPending) {\n this._onEditFinish();\n }\n });\n }\n\n override _hasTrailingIcon() {\n // The trailing icon is hidden while editing.\n return !this._isEditing && super._hasTrailingIcon();\n }\n\n /** Sends focus to the first gridcell when the user clicks anywhere inside the chip. */\n _handleFocus() {\n if (!this._isEditing && !this.disabled) {\n this.focus();\n }\n }\n\n override _handleKeydown(event: KeyboardEvent): void {\n if (event.keyCode === ENTER && !this.disabled) {\n if (this._isEditing) {\n event.preventDefault();\n this._onEditFinish();\n } else if (this.editable) {\n this._startEditing(event);\n }\n } else if (this._isEditing) {\n // Stop the event from reaching the chip set in order to avoid navigating.\n event.stopPropagation();\n } else {\n super._handleKeydown(event);\n }\n }\n\n _handleDoubleclick(event: MouseEvent) {\n if (!this.disabled && this.editable) {\n this._startEditing(event);\n }\n }\n\n private _startEditing(event: Event) {\n if (\n !this.primaryAction ||\n (this.removeIcon && this._getSourceAction(event.target as Node) === this.removeIcon)\n ) {\n return;\n }\n\n // The value depends on the DOM so we need to extract it before we flip the flag.\n const value = this.value;\n\n this._isEditing = this._editStartPending = true;\n\n // Defer initializing the input until after it has been added to the DOM.\n afterNextRender(\n () => {\n this._getEditInput().initialize(value);\n this._editStartPending = false;\n },\n {injector: this._injector},\n );\n }\n\n private _onEditFinish() {\n this._isEditing = this._editStartPending = false;\n this.edited.emit({chip: this, value: this._getEditInput().getValue()});\n\n // If the edit input is still focused or focus was returned to the body after it was destroyed,\n // return focus to the chip contents.\n if (\n this._document.activeElement === this._getEditInput().getNativeElement() ||\n this._document.activeElement === this._document.body\n ) {\n this.primaryAction.focus();\n }\n }\n\n override _isRippleDisabled(): boolean {\n return super._isRippleDisabled() || this._isEditing;\n }\n\n /**\n * Gets the projected chip edit input, or the default input if none is projected in. One of these\n * two values is guaranteed to be defined.\n */\n private _getEditInput(): MatChipEditInput {\n return this.contentEditInput || this.defaultEditInput!;\n }\n}\n","@if (!_isEditing) {\n <span class=\"mat-mdc-chip-focus-overlay\"></span>\n}\n\n<span class=\"mdc-evolution-chip__cell mdc-evolution-chip__cell--primary\" role=\"gridcell\"\n matChipAction\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-describedby]=\"_ariaDescriptionId\">\n @if (leadingIcon) {\n <span class=\"mdc-evolution-chip__graphic mat-mdc-chip-graphic\">\n <ng-content select=\"mat-chip-avatar, [matChipAvatar]\"></ng-content>\n </span>\n }\n\n <span class=\"mdc-evolution-chip__text-label mat-mdc-chip-action-label\">\n @if (_isEditing) {\n @if (contentEditInput) {\n <ng-content select=\"[matChipEditInput]\"></ng-content>\n } @else {\n <span matChipEditInput></span>\n }\n } @else {\n <ng-content></ng-content>\n }\n\n <span class=\"mat-mdc-chip-primary-focus-indicator mat-focus-indicator\" aria-hidden=\"true\"></span>\n </span>\n</span>\n\n@if (_hasTrailingIcon()) {\n <span\n class=\"mdc-evolution-chip__cell mdc-evolution-chip__cell--trailing\"\n role=\"gridcell\">\n <ng-content select=\"mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon]\"></ng-content>\n </span>\n}\n\n<span class=\"cdk-visually-hidden\" [id]=\"_ariaDescriptionId\">{{ariaDescription}}</span>\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 {FocusKeyManager} from '@angular/cdk/a11y';\nimport {Directionality} from '@angular/cdk/bidi';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n ElementRef,\n Input,\n OnDestroy,\n QueryList,\n ViewEncapsulation,\n booleanAttribute,\n numberAttribute,\n inject,\n} from '@angular/core';\nimport {Observable, Subject, merge} from 'rxjs';\nimport {startWith, switchMap, takeUntil} from 'rxjs/operators';\nimport {MatChip, MatChipEvent} from './chip';\nimport {MatChipAction} from './chip-action';\n\n/**\n * Basic container component for the MatChip component.\n *\n * Extended by MatChipListbox and MatChipGrid for different interaction patterns.\n */\n@Component({\n selector: 'mat-chip-set',\n template: `\n <div class=\"mdc-evolution-chip-set__chips\" role=\"presentation\">\n <ng-content></ng-content>\n </div>\n `,\n styleUrl: 'chip-set.css',\n host: {\n 'class': 'mat-mdc-chip-set mdc-evolution-chip-set',\n '(keydown)': '_handleKeydown($event)',\n '[attr.role]': 'role',\n },\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MatChipSet implements AfterViewInit, OnDestroy {\n protected _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n protected _changeDetectorRef = inject(ChangeDetectorRef);\n private _dir = inject(Directionality, {optional: true});\n\n /** Index of the last destroyed chip that had focus. */\n private _lastDestroyedFocusedChipIndex: number | null = null;\n\n /** Used to manage focus within the chip list. */\n protected _keyManager: FocusKeyManager<MatChipAction>;\n\n /** Subject that emits when the component has been destroyed. */\n protected _destroyed = new Subject<void>();\n\n /** Role to use if it hasn't been overwritten by the user. */\n protected _defaultRole = 'presentation';\n\n /** Combined stream of all of the child chips' focus events. */\n get chipFocusChanges(): Observable<MatChipEvent> {\n return this._getChipStream(chip => chip._onFocus);\n }\n\n /** Combined stream of all of the child chips' destroy events. */\n get chipDestroyedChanges(): Observable<MatChipEvent> {\n return this._getChipStream(chip => chip.destroyed);\n }\n\n /** Combined stream of all of the child chips' remove events. */\n get chipRemovedChanges(): Observable<MatChipEvent> {\n return this._getChipStream(chip => chip.removed);\n }\n\n /** Whether the chip set is disabled. */\n @Input({transform: booleanAttribute})\n get disabled(): boolean {\n return this._disabled;\n }\n set disabled(value: boolean) {\n this._disabled = value;\n this._syncChipsState();\n }\n protected _disabled: boolean = false;\n\n /** Whether the chip list contains chips or not. */\n get empty(): boolean {\n return !this._chips || this._chips.length === 0;\n }\n\n /** The ARIA role applied to the chip set. */\n @Input()\n get role(): string | null {\n if (this._explicitRole) {\n return this._explicitRole;\n }\n\n return this.empty ? null : this._defaultRole;\n }\n\n /** Tabindex of the chip set. */\n @Input({\n transform: (value: unknown) => (value == null ? 0 : numberAttribute(value)),\n })\n tabIndex: number = 0;\n\n set role(value: string | null) {\n this._explicitRole = value;\n }\n private _explicitRole: string | null = null;\n\n /** Whether any of the chips inside of this chip-set has focus. */\n get focused(): boolean {\n return this._hasFocusedChip();\n }\n\n /** The chips that are part of this chip set. */\n @ContentChildren(MatChip, {\n // We need to use `descendants: true`, because Ivy will no longer match\n // indirect descendants if it's left as false.\n descendants: true,\n })\n _chips: QueryList<MatChip>;\n\n /** Flat list of all the actions contained within the chips. */\n _chipActions = new QueryList<MatChipAction>();\n\n constructor(...args: unknown[]);\n constructor() {}\n\n ngAfterViewInit() {\n this._setUpFocusManagement();\n this._trackChipSetChanges();\n this._trackDestroyedFocusedChip();\n }\n\n ngOnDestroy() {\n this._keyManager?.destroy();\n this._chipActions.destroy();\n this._destroyed.next();\n this._destroyed.complete();\n }\n\n /** Checks whether any of the chips is focused. */\n protected _hasFocusedChip() {\n return this._chips && this._chips.some(chip => chip._hasFocus());\n }\n\n /** Syncs the chip-set's state with the individual chips. */\n protected _syncChipsState() {\n this._chips?.forEach(chip => {\n chip._chipListDisabled = this._disabled;\n chip._changeDetectorRef.markForCheck();\n });\n }\n\n /** Dummy method for subclasses to override. Base chip set cannot be focused. */\n focus() {}\n\n /** Handles keyboard events on the chip set. */\n _handleKeydown(event: KeyboardEvent) {\n if (this._originatesFromChip(event)) {\n this._keyManager.onKeydown(event);\n }\n }\n\n /**\n * Utility to ensure all indexes are valid.\n *\n * @param index The index to be checked.\n * @returns True if the index is valid for our list of chips.\n */\n protected _isValidIndex(index: number): boolean {\n return index >= 0 && index < this._chips.length;\n }\n\n /**\n * Removes the `tabindex` from the chip set and resets it back afterwards, allowing the\n * user to tab out of it. This prevents the set from capturing focus and redirecting\n * it back to the first chip, creating a focus trap, if it user tries to tab away.\n */\n protected _allowFocusEscape() {\n const previous = this._elementRef.nativeElement.tabIndex;\n\n if (previous !== -1) {\n // Set the tabindex directly on the element, instead of going through\n // the data binding, because we aren't guaranteed that change detection\n // will run quickly enough to allow focus to escape.\n this._elementRef.nativeElement.tabIndex = -1;\n\n // Note that this needs to be a `setTimeout`, because a `Promise.resolve`\n // doesn't allow enough time for the focus to escape.\n setTimeout(() => (this._elementRef.nativeElement.tabIndex = previous));\n }\n }\n\n /**\n * Gets a stream of events from all the chips within the set.\n * The stream will automatically incorporate any newly-added chips.\n */\n protected _getChipStream<T, C extends MatChip = MatChip>(\n mappingFunction: (chip: C) => Observable<T>,\n ): Observable<T> {\n return this._chips.changes.pipe(\n startWith(null),\n switchMap(() => merge(...(this._chips as QueryList<C>).map(mappingFunction))),\n );\n }\n\n /** Checks whether an event comes from inside a chip element. */\n protected _originatesFromChip(event: Event): boolean {\n let currentElement = event.target as HTMLElement | null;\n\n while (currentElement && currentElement !== this._el