/** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import '../../elevation/elevation.js'; import {html, nothing} from 'lit'; import {property, query} from 'lit/decorators.js'; import {ARIAMixinStrict} from '../../internal/aria/aria.js'; import {redispatchEvent} from '../../internal/events/redispatch-event.js'; import {MultiActionChip} from './multi-action-chip.js'; import {renderRemoveButton} from './trailing-icons.js'; /** * A filter chip component. * * @fires remove {Event} Dispatched when the remove button is clicked. */ export class FilterChip extends MultiActionChip { @property({type: Boolean}) elevated = false; @property({type: Boolean}) removable = false; @property({type: Boolean, reflect: true}) selected = false; /** * Only needed for SSR. * * Add this attribute when a filter chip has a `slot="selected-icon"` to avoid * a Flash Of Unstyled Content. */ @property({type: Boolean, reflect: true, attribute: 'has-selected-icon'}) hasSelectedIcon = false; protected get primaryId() { return 'button'; } @query('.primary.action') protected readonly primaryAction!: HTMLElement | null; @query('.trailing.action') protected readonly trailingAction!: HTMLElement | null; protected override getContainerClasses() { return { ...super.getContainerClasses(), elevated: this.elevated, selected: this.selected, 'has-trailing': this.removable, 'has-icon': this.hasIcon || this.selected, }; } protected override renderPrimaryAction(content: unknown) { const {ariaLabel} = this as ARIAMixinStrict; return html` `; } protected override renderLeadingIcon() { if (!this.selected) { return super.renderLeadingIcon(); } return html` `; } protected override renderTrailingAction(focusListener: EventListener) { if (this.removable) { return renderRemoveButton({ focusListener, ariaLabel: this.ariaLabelRemove, disabled: this.disabled || this.softDisabled, }); } return nothing; } protected override renderOutline() { if (this.elevated) { return html``; } return super.renderOutline(); } private handleClickOnChild(event: MouseEvent) { if (this.disabled || this.softDisabled) { return; } // Store prevValue to revert in case `chip.selected` is changed during an // event listener. const prevValue = this.selected; this.selected = !this.selected; const preventDefault = !redispatchEvent(this, event); if (preventDefault) { // We should not do `this.selected = !this.selected`, since a client // click listener could change its value. Instead, always revert to the // original value. this.selected = prevValue; return; } } }