Skip to main content
cngx-src documentation

CngxActionMultiSelect

ComponentPrimaryOnPushNo encapsulationv0.1.0WCAG AA

projects/forms/select/action-multi-select/action-multi-select.component.ts

Import#

import { CngxActionMultiSelect } from '@cngx/forms/select'

Description#

Multi-value combobox with inline quick-create. Parallels CngxCombobox and adds the action-slot protocol from CngxActionSelect: *cngxSelectAction.commit() routes through the CreateCommitHandler to materialise a new T, patches the local buffer, appends to values, emits selectionChange({ action: 'create', added: [newValue] }).

closeOnCreate default false - multi-pick UX keeps the panel open after each create. Commit-controller supersede guard tears down previous subscriptions on rapid consecutive creates.

Dismiss-guard: Escape and click-outside intercepted while actionDirty() is true; Escape fires cancel().

https://cngxjs.github.io/cngx/examples/#/forms/select/action-multi-select/basic

Metadata#

Host#

Providers#

CNGX_FORM_FIELD_CONTROL
useExisting CngxActionMultiSelect
CNGX_SELECT_PANEL_HOST
useExisting CngxActionMultiSelect
CNGX_SELECT_PANEL_VIEW_HOST
useExisting CngxActionMultiSelect

Relationships

Index#

Inputs#

actionPosition#"top" | "bottom" | "both" | "none"
input()

Position of *cngxSelectAction in the panel.

default this.actionConfig.actionPosition,
announceChanges#boolean | null
input()
default null
input()
default null
ariaLabel#string | null
input()
default null, { alias: 'aria-label' }
ariaLabelledBy#string | null
input()
default null, { alias: 'aria-labelledby' }
autofocus#boolean
input()
default false
caretGlyph#TemplateRef | null
default null
chipOverflow#NonNullable

Chip-strip overflow strategy.

default this.config.chipOverflow,
chipRemoveAriaLabel#string
input()
default this.config.ariaLabels?.chipRemove ?? 'Remove'
clearable#boolean
input()
default false
clearButtonAriaLabel#string
input()
default this.config.ariaLabels?.clearButton ?? 'Reset selection',
clearGlyph#TemplateRef | null
default null
closeOnCreate#boolean
input()

Whether a successful create closes the panel. Default false - multi-pick UX keeps the panel open. Set true for confirm-to- create workflows.

default this.actionConfig.closeOnCreate ?? false
default null
input()
default this.config.commitErrorDisplay
input()
default 'optimistic'
default cngxSelectDefaultCompare as CngxSelectCompareFn<T>,
disabledInput#boolean
input()
default false, { alias: 'disabled' }
enterKeyHint#NonNullable

Mobile enterkeyhint. Default 'enter' - Enter appends a chip without closing the panel.

default this.config.enterKeyHint ?? 'enter',
hideCaret#boolean
input()
default !this.config.showCaret
hideSelectionIndicator#boolean
input()
default !this.config.showSelectionIndicator
idInput#string | null
input()
default null, { alias: 'id' }
inputMode#NonNullable

Mobile inputmode. Defaults from CngxSelectConfig.inputMode.

default this.config.inputMode
label#string
input()
default ''
liveInputFallback#boolean
input()

Fall back to raw <input>.value when debounced searchTerm hasn't caught up.

default this.actionConfig.liveInputFallback
loading#boolean
input()
default false
input()
default this.config.loadingVariant
maxVisibleChips#number
input()

Max chips in 'truncate' mode.

default this.config.maxVisibleChips
default [] as CngxSelectOptionsInput<T>
panelClass#string | readonly string[] | null
input()
default null
panelWidth#'trigger' | number | null
input()
default this.config.panelWidth
placeholder#string
input()
default ''
popoverPlacement#PopoverPlacement
input()

Popover placement relative to the trigger. Per-instance input wins over CngxActionSelectConfig.popoverPlacement.

default this.actionConfig.popoverPlacement

Quick-create handler. null disables the create path - slot still renders, commit() becomes a silent no-op.

default null
input()
default this.config.refreshingVariant
requiredInput#boolean
input()
default false, { alias: 'required' }
searchDebounceMs#number
input()

Debounce for the inline search (ms). Default 0 for action-slot feedback.

default this.config.typeaheadDebounceInterval
input()
default null
selectionIndicatorPosition#'before' | 'after' | null
input()
default null
input()
default null
skeletonRowCount#number
input()
default this.config.skeletonRowCount
skipInitial#boolean
input()
default false
default null
tabIndex#number
input()
default 0
values#T[]
model()

Two-way multi-value binding.

default []

Outputs#

cleared#void
output()
closed#void
output()
commitError#unknown
output()

Dedicated channel for successful creates. Fires after selectionChange.

opened#void
output()
openedChange#boolean
output()
retry#void
output()
searchTermChange#string
output()
stateChange#AsyncStatus
output()
values#T[]
model()

Two-way multi-value binding.

Instance Properties#

commitState#unknown
Readonly
this.core.commitState
disabled#unknown
Readonly
this.core.disabled
retryFn#unknown
Readonly
input<(() => void) | null>(null)
selectedOptions#unknown
ProtectedReadonly
computed<CngxSelectOptionDef<T>[]>(
  () => {
    const vals = this.values();
    if (vals.length === 0) {
      return [];
    }
    // Chip strip resolves against the UNFILTERED option merge so
    // chips for previously-picked values stay visible when the
    // search term hides the matching option from the listbox.
    const eq = this.compareWith();
    const out: CngxSelectOptionDef<T>[] = [];
    const flat = this.core.unfilteredFlatOptions();
    for (const v of vals) {
      const match = flat.find((o) => eq(o.value, v));
      if (match) {
        out.push(match);
      }
    }
    return out;
  },
  {
    equal: (a, b) => {
      if (a === b) {
        return true;
      }
      if (a.length !== b.length) {
        return false;
      }
      for (let i = 0; i < a.length; i++) {
        if (!Object.is(a[i], b[i])) {
          return false;
        }
      }
      return true;
    },
  },
)

Methods#

clearLocalItems#void
close#void
focus#void
focus(options?: FocusOptions)
@paramoptions?FocusOptions
handleBlur#void
Protected
handleChipRemoveClick#void
Protected
handleChipRemoveClick(event: Event, opt: CngxSelectOptionDef<T>)
@parameventEvent
handleClearAllClick#void
Protected
handleClearAllClick(event: Event)
@parameventEvent
handleFocus#void
Protected
handleRetry#void
Protected
handleWrapperClick#void
Protected
handleWrapperClick(event: MouseEvent)
@parameventMouseEvent
isEmpty#boolean
Protected
open#void
patchData#void
patchData(item: CngxSelectOptionDef<T>)
toggle#void

HostBindings#

BindingExpression
[id]resolvedId()
[attr.aria-readonly]ariaReadonly()

Structural styles shared across the entire CngxSelect family - imported via styleUrls from every variant (CngxSelect, CngxMultiSelect, CngxCombobox, CngxTypeahead, CngxTreeSelect, CngxReorderableMultiSelect, CngxActionSelect, CngxActionMultiSelect, CngxSelectShell, and the panel components).

All variants run encapsulation: None so the rules below are global; the .cngx-select__* BEM-style class prefix is the namespace.

State modifiers

  • .cngx-option--highlighted on an option row - primary-tinted background marking the keyboard-focused row
  • [aria-disabled='true'] on an option - opacity 0.5 + cursor: not-allowed
  • .cngx-select__option--pending - cursor: progress while a row's commit is in flight
  • .cngx-select__chip-list--reordering - whole-strip cursor: grabbing while a drag is active
  • .cngx-select__chip--dragging on a chip - Trello-style lift (shadow + scale + tilt + accent fill)
  • .cngx-select__chip--drag-over on a chip - vertical drop bar painted on the leading edge via ::before

Variants

Chip-list overflow modes via data-overflow:

  • default - flex-wrap chips across multiple rows
  • data-overflow='scroll-x' - single row + horizontal scroll
  • data-overflow='truncate' - single row + clipped overflow + the .cngx-select__chip-overflow-badge count pill

Error surfaces with two layouts:

  • .cngx-select__error - column-stacked block (message + retry)
  • .cngx-select__error--inline - inline banner above the option list
  • .cngx-select__commit-error - per-commit failure banner

Slots

  • .cngx-select__panel - the floating panel surface (anchor-positioned via position-try-fallbacks)
  • .cngx-select__group-header - uppercase optgroup label
  • .cngx-select__option / .cngx-select__check - option row + the selected-state checkmark
  • .cngx-select__loading / .cngx-select__empty - inline message rows
  • .cngx-select__skeleton / .cngx-select__skeleton-row - first-load shimmer placeholders (static under prefers-reduced-motion)
  • .cngx-select__spinner-wrap / .cngx-select__spinner - first-load spinner ring
  • .cngx-select__loading-bar - first-load top-edge progress bar
  • .cngx-select__refreshing / .cngx-select__refreshing-spinner / .cngx-select__refreshing-dots - subsequent-load indicators
  • .cngx-select__option-spinner / .cngx-select__option-error - per-row commit feedback
  • .cngx-select__chip-list / .cngx-select__chip-overflow-badge - chip strip + overflow count
  • .cngx-select__chip-wrap / .cngx-select__chip-handle - reorderable chip surface + optional drag-handle glyph
  • .cngx-select__error / .cngx-select__error--inline / .cngx-select__error-message / .cngx-select__error-retry / .cngx-select__commit-error - error block, banner, and retry pieces

Inheritance

Tokens are registered top-level in @layer cngx.tokens via @property so any consumer (cngx.theme layer, app layer) can override without learning the type.

Panel surface, every primary-tinted glyph, and every danger-toned error surface delegate to the foundation so a dark-mode swap cascades through the floating panel even when anchor positioning detaches it from the trigger's DOM context:

  • --cngx-select-panel-border -> --cngx-color-border
  • --cngx-select-panel-bg -> --cngx-color-surface
  • --cngx-select-panel-color -> --cngx-color-text
  • --cngx-select-panel-shadow -> --cngx-shadow-md
  • --cngx-select-check-color -> --cngx-color-primary
  • --cngx-select-spinner-color -> --cngx-color-primary
  • --cngx-select-loading-bar-color -> --cngx-color-primary
  • --cngx-select-refreshing-color -> --cngx-color-primary
  • --cngx-select-option-spinner-color -> --cngx-color-primary
  • --cngx-select-option-error-color -> --cngx-color-danger
  • --cngx-select-error-color -> --cngx-color-danger
  • --cngx-select-chip-remove-hover-color -> --cngx-color-danger
  • --cngx-select-chip-drag-bg -> --cngx-color-primary
  • --cngx-select-chip-drop-bar-color -> --cngx-color-primary
  • --cngx-select-trigger-invalid-border-color -> --cngx-color-danger
  • --cngx-select-trigger-invalid-outline-color -> --cngx-color-danger

--cngx-select-panel-min-width is intentionally NOT registered via @property so the anchor-size(width) fallback survives when the consumer doesn't override it; registering it with any initial-value would shadow the var() fallback and break anchor positioning.

Dark mode

Three hooks swap alpha-on-black surfaces (panel shadow, option highlight, spinner track, chip-overflow tint, chip remove-hover tint, chip handle muted, chip drag shadow) plus the skeleton shimmer gradient and the option-spinner track:

  • prefers-color-scheme: dark
  • [data-color-scheme="dark"]
  • .dark class

Foundation-delegated tokens ride the foundation cascade unchanged.

Pair with

  • @cngx/themes/material/select-theme - Material 3 surface treatment across the entire family

Trigger skin for CngxActionMultiSelect - a multi-select variant that surfaces a per-row action handler (typically a quick-create button). The host carries .cngx-action-multi-select; structural parts (panel frame, option rows, chip strip, loading variants, error surfaces) ride on shared/select-base.css. This file owns the trigger-specific bits: the role="group" wrapper, the inline <input> as the focusable element, the clear-all button, and the caret glyph.

State modifiers

  • :focus-within on .cngx-action-multi-select__trigger - focus-ring outline + offset
  • [aria-disabled='true'] on the trigger - opacity dim + cursor: not-allowed
  • :hover on .cngx-action-multi-select__clear-all - opacity 1
  • :focus-visible on the clear-all button - 2px primary outline

Slots

  • .cngx-action-multi-select__root - display: contents host shim
  • .cngx-action-multi-select__trigger - the bordered row
  • .cngx-action-multi-select__input - inline role="combobox" input
  • .cngx-action-multi-select__trigger-label - text summary slot
  • .cngx-action-multi-select__clear-all - reset-all button
  • .cngx-action-multi-select__caret - panel-state glyph

Inheritance

Trigger tokens delegate up the family chain so consumer themes only need to override at the level they want to brand:

  • --cngx-action-multi-select-* -> --cngx-combobox-* -> --cngx-select-* -> hardcoded
  • --cngx-action-multi-select-border -> --cngx-color-border
  • --cngx-action-multi-select-focus-outline -> --cngx-color-primary

Once registered via @property the inner var() steps are documentation-only; system tokens (--cngx-color-*) are the brand-wide override path.

Pair with

  • @cngx/themes/material/select-theme - Material 3 surface treatment shared across the entire select family

Index#

Surface

--cngx-select-panel-border#*
Default value 1px solid oklch(0.85 0.01 250)

Border shorthand of the dropdown panel. Falls back through --cngx-color-border. inherits: true so the :root delegating value reaches the floating panel host (anchor-positioned, may sit outside the normal DOM flow).

See: [[--cngx-color-border]]

--cngx-select-panel-bg#<color>
Default value oklch(1 0 0)

Background of the dropdown panel. Falls back through --cngx-color-surface.

See: [[--cngx-color-surface]]

--cngx-select-panel-color#*
Default value currentColor

Text color inside the panel. syntax: '*' + initial-value currentColor lets the panel inherit text color from its ancestor by default. Registering as <color> would forbid currentColor since <color> requires a computationally- independent value.

--cngx-select-panel-shadow#*
Default value 0 4px 12px oklch(0 0 0 / 0.12)

Drop-shadow shorthand. Falls back through --cngx-shadow-md. inherits: true so the :root dark-mode override (deeper shadow on dark) reaches the floating panel host.

--cngx-select-placeholder-color#<color>
Default value oklch(0 0 0 / 0.5)

Color of the placeholder text shown when no value is selected.

--cngx-select-caret-color#<color>
Default value oklch(0 0 0 / 0.5)

Color of the dropdown caret glyph shared across every variant. Muted by default to mirror the placeholder token; the Material bridge maps it to --mat-sys-on-surface-variant. inherits: true so a trigger-level override reaches the glyph element.

--cngx-select-clear-color#<color>
Default value oklch(0 0 0 / 0.5)

Color of the clear-button glyph shared across every variant. Tracks the same muted default as the caret so both trigger affordances read uniformly. inherits: true so a trigger-level override reaches the glyph element.

--cngx-action-multi-select-border#*
Default value 1px solid oklch(0.85 0.01 250)

Border shorthand of the trigger.

--cngx-action-multi-select-bg#<color>
Default value transparent

Background of the trigger.

--cngx-action-multi-select-color#*
Default value currentColor

Text color of the trigger.

Layout

--cngx-select-panel-radius#*
Default value 0.25rem

Corner radius of the dropdown panel.

--cngx-select-panel-padding#*
Default value 0.25rem

Inner padding of the panel.

--cngx-select-panel-max-height#*
Default value 16rem

Maximum height before vertical scrolling kicks in.

--cngx-select-option-padding#*
Default value 0.375rem 0.5rem

Padding shorthand of each option row.

--cngx-select-option-min-height#*
Default value auto

Minimum height of an option row - defaults to auto so dense rows stay compact.

--cngx-select-option-radius#*
Default value 0.125rem

Corner radius of an option row.

--cngx-select-caret-size#*
Default value 1.25em

Font-size of the dropdown caret glyph shared across every variant.

--cngx-select-chip-gap#*
Default value 0.25rem

Gap between chips inside the trigger chip list.

--cngx-select-chip-wrap-radius#*
Default value 0.25rem

Corner radius of the reorderable chip wrap container.

--cngx-select-chip-wrap-gap#*
Default value 0.25rem

Gap between the chip body and any projected drag handle.

--cngx-action-multi-select-min-width#*
Default value 12rem

Minimum inline size of the trigger.

--cngx-action-multi-select-gap#*
Default value 0.375rem

Gap between the chip list, input, caret, and clear-all button.

--cngx-action-multi-select-padding#*
Default value 0.25rem 0.375rem

Padding shorthand of the trigger.

--cngx-action-multi-select-radius#*
Default value 0.25rem

Corner radius of the trigger.

--cngx-action-multi-select-min-height#*
Default value 2.25rem

Minimum block size of the trigger.

--cngx-action-multi-select-input-flex-basis#*
Default value 4rem

Flex basis of the inline input.

--cngx-action-multi-select-input-min-width#*
Default value 4rem

Minimum inline size of the inline input.

State / Highlighted

--cngx-select-option-highlight-bg#<color>
Default value oklch(0.66 0.19 50 / 0.1)

Background of the keyboard-highlighted option row. Defaults to a low-alpha tint of --cngx-color-primary so the highlight reads as brand-accented without competing with selection state.

See: [[--cngx-color-primary]]

State / Selected

--cngx-select-check-color#<color>
Default value oklch(0.66 0.19 50)

Color of the selected-option checkmark glyph. Falls back through --cngx-color-primary.

See: [[--cngx-color-primary]]

State / Disabled

--cngx-select-disabled-opacity#<number>
Default value 0.5

Opacity multiplier applied when the trigger is disabled. Shared family-wide so every variant dims its disabled trigger identically.

--cngx-action-multi-select-disabled-opacity#<number>
Default value 0.5

Opacity multiplier applied when the trigger is disabled.

State / Loading

--cngx-select-skeleton-gap#*
Default value 0.25rem

Vertical gap between skeleton placeholder rows.

--cngx-select-skeleton-padding#*
Default value 0.25rem

Padding around the skeleton placeholder block.

--cngx-select-skeleton-row-height#*
Default value 1.75rem

Height of each skeleton placeholder row.

--cngx-select-skeleton-row-radius#*
Default value 0.125rem

Corner radius of each skeleton placeholder row.

--cngx-select-spinner-padding#*
Default value 1rem

Padding around the first-load spinner wrapper.

--cngx-select-spinner-size#*
Default value 1.5rem

Diameter of the first-load spinner ring.

--cngx-select-spinner-border#*
Default value 2px solid oklch(0 0 0 / 0.15)

Track stroke of the first-load spinner ring. inherits: true so the :root dark-mode override (alpha-on-white on dark) reaches the spinner inside the floating panel.

--cngx-select-spinner-color#<color>
Default value oklch(0.66 0.19 50)

Indicator stroke of the first-load spinner ring. Falls back to --cngx-color-primary.

--cngx-select-loading-bar-height#<length>
Default value 3px

Height of the first-load loading bar.

--cngx-select-loading-bar-color#<color>
Default value oklch(0.66 0.19 50)

Color of the first-load loading bar. Falls back to --cngx-color-primary.

State / Refreshing

--cngx-select-refreshing-height#<length>
Default value 2px

Height of the subsequent-load refreshing bar.

--cngx-select-refreshing-color#<color>
Default value oklch(0.66 0.19 50)

Color of the refreshing bar gradient. Falls back to --cngx-color-primary.

--cngx-select-refreshing-spinner-padding#*
Default value 0.25rem

Padding around the refreshing spinner wrapper.

--cngx-select-refreshing-dots-gap#*
Default value 0.25rem

Gap between the three refreshing dots.

--cngx-select-refreshing-dots-padding#*
Default value 0.375rem

Padding around the refreshing dots block.

--cngx-select-refreshing-dot-size#*
Default value 0.375rem

Diameter of each refreshing dot.

--cngx-select-refreshing-dot-color#*
Default value currentColor

Color of each refreshing dot.

State / Commit

--cngx-select-option-spinner-size#*
Default value 0.875rem

Diameter of the per-row commit spinner.

--cngx-select-option-spinner-color#<color>
Default value oklch(0.66 0.19 50)

Indicator stroke of the per-row commit spinner.

--cngx-select-option-error-color#<color>
Default value oklch(0.6 0.18 25)

Glyph color of the per-row commit error indicator. Falls back to --cngx-color-danger.

--cngx-select-commit-error-padding#*
Default value 0.375rem 0.5rem

Padding of the commit error banner.

--cngx-select-commit-error-radius#*
Default value 0.125rem

Corner radius of the commit error banner.

State / Overflow

--cngx-select-chip-overflow-badge-bg#<color>
Default value oklch(0 0 0 / 0.08)

Background of the chip overflow badge shown in truncate overflow mode.

--cngx-select-chip-overflow-badge-color#<color>
Default value oklch(0 0 0 / 0.6)

Text color of the chip overflow badge.

State / Remove

--cngx-select-chip-remove-size#*
Default value 1.25rem

Hit-target diameter of the chip remove button inside a reorderable chip wrap.

--cngx-select-chip-remove-hover-bg#<color>
Default value oklch(0 0 0 / 0.12)

Background tint of the chip remove button on hover.

--cngx-select-chip-remove-hover-color#<color>
Default value oklch(0.6 0.18 25)

Foreground color of the chip remove button on hover. Falls back to --cngx-color-danger.

State / Reorder

--cngx-select-chip-handle-color#<color>
Default value oklch(0.5 0.01 250)

Color of the optional projected drag-handle glyph.

--cngx-select-chip-handle-size#*
Default value 0.75rem

Font-size of the optional projected drag-handle glyph.

State / Dragging

--cngx-select-chip-drag-shadow#*
Default value 0 8px 20px oklch(0 0 0 / 0.28)

Drop-shadow of the chip lifted into the dragging state. inherits: true so the :root dark-mode override (deeper shadow on dark) reaches the chip while it's being dragged.

--cngx-select-chip-drag-bg#<color>
Default value oklch(0.66 0.19 50)

Background of the chip lifted into the dragging state. Falls back to --cngx-color-primary.

See: [[--cngx-color-primary]]

--cngx-select-chip-drag-color#<color>
Default value oklch(1 0 0)

Text color of the chip lifted into the dragging state.

--cngx-select-chip-drag-scale#<number>
Default value 1.06

Scale multiplier of the dragging chip - Trello-style lift.

--cngx-select-chip-drag-tilt#<angle>
Default value -1.5deg

Rotation tilt applied to the dragging chip - Trello-style lift.

--cngx-select-chip-drop-bar-width#<length>
Default value 3px

Width of the drop-indicator bar between chips.

--cngx-select-chip-drop-bar-color#<color>
Default value oklch(0.66 0.19 50)

Color of the drop-indicator bar between chips. Falls back to --cngx-color-primary.

State / Error

--cngx-select-error-gap#*
Default value 0.5rem

Gap between the error message and the retry button.

--cngx-select-error-padding#*
Default value 0.5rem 0.75rem

Padding of the panel-wide error block.

--cngx-select-error-color#<color>
Default value oklch(0.6 0.18 25)

Text color of every error surface. Falls back to --cngx-color-danger.

See: [[--cngx-color-danger]]

--cngx-select-error-inline-padding#*
Default value 0.375rem 0.5rem

Padding of the inline error banner shown above the option list.

--cngx-select-error-inline-radius#*
Default value 0.125rem

Corner radius of the inline error banner.

--cngx-select-error-retry-border#*
Default value 1px solid currentColor

Border shorthand of the error retry button.

State / Trigger invalid

--cngx-select-trigger-invalid-border-color#<color>
Default value oklch(0.6 0.18 25)

Border color painted on the trigger wrapper when aria-invalid="true". Defaults track --cngx-color-danger via the delegating :root entry below.

--cngx-select-trigger-invalid-border-width#<length>
Default value 1px

Border width painted on the trigger wrapper when aria-invalid="true".

--cngx-select-trigger-invalid-outline-color#<color>
Default value oklch(0.6 0.18 25)

Outline color layered on the invalid trigger when focus is inside it. Defaults track --cngx-color-danger via the delegating :root entry below.

--cngx-select-trigger-invalid-glow#*
Default value 0 0 0 3px oklch(0.6 0.18 25 / 0.2)

Soft halo layered behind the invalid trigger at focus time. Authored as a box-shadow so it composes with any consumer-supplied focus outline.

State / Focus

--cngx-action-multi-select-focus-outline#*
Default value 2px solid oklch(0.66 0.19 50)

Focus-ring outline shorthand applied on :focus-within. Falls back to --cngx-color-primary.

See: [[--cngx-color-primary]]

State / Clear

--cngx-action-multi-select-clear-opacity#<number>
Default value 0.6

Resting opacity of the clear-all button.

Material theme

import { ChangeDetectionStrategy, Component, ViewEncapsulation, signal } from '@angular/core';

import { CngxActionMultiSelect, type CngxSelectOptionDef } from '@cngx/forms/select';

/**
 * `CngxActionMultiSelect` rendered against a Material 3 palette via the
 * published `@cngx/themes/material/select-theme` bridge.
 *
 * The stylesheet builds a real M3 theme: `mat.theme` emits the `--mat-sys-*`
 * system tokens, then `select.theme($theme)` routes every `--cngx-select-*`
 * token onto its Material counterpart, so the trigger, chip strip, panel
 * surface, and selected-option tones inherit the palette with no
 * per-instance overrides. `ViewEncapsulation.None` lets the global `html`
 * theme and the `:where(cngx-action-multi-select)` bridge rules reach both
 * the trigger and the top-layer panel.
 */
@Component({
  selector: 'app-root',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  imports: [CngxActionMultiSelect],
  styleUrl: './material-theme.component.scss',
  template: `
    <div class="demo">
      <cngx-action-multi-select
        [label]="'Favorite colors'"
        [options]="colors"
        [(values)]="values"
        [clearable]="true"
        [chipOverflow]="'truncate'"
        placeholder="Pick colors…"
      />
      <p class="demo__readout">Selected: {{ values().join(', ') || '—' }}</p>
    </div>
  `,
})
export class MaterialThemeExample {
  protected readonly values = signal<string[]>([]);

  protected readonly colors: CngxSelectOptionDef<string>[] = [
    { value: 'red', label: 'Red' },
    { value: 'green', label: 'Green' },
    { value: 'blue', label: 'Blue' },
    { value: 'amber', label: 'Amber' },
    { value: 'violet', label: 'Violet' },
  ];
}
export { MaterialThemeExample as AppComponent };