import { LitElement, html, css } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; // Import official USWDS compiled CSS export interface SelectOption { value: string; text: string; disabled?: boolean; } /** * USA Select Web Component * * A simple, accessible USWDS select implementation as a custom element. * Uses official USWDS classes and styling with minimal custom code. * * @element usa-select * * @attr {string} name - Select name for form submission. * @attr {string} value - Currently selected value. * @attr {string} label - Label text displayed above the select. * @attr {string} hint - Helper text displayed below the label. * @attr {string} error - Error message displayed in red below the select. * @attr {string} success - Success message displayed in green below the select. * @attr {boolean} disabled - Whether the select is disabled. * @attr {boolean} required - Whether the select is required. * @attr {string} defaultOption - Placeholder text for default empty option. * @attr {boolean} compact - Render without form-group wrapper for use in patterns. * * @prop {Array<{value: string, text: string, disabled?: boolean}>} options - Array of select options. * * @fires change - Dispatched when the select value changes * @fires input - Dispatched when the select value changes (for consistency) * * @example * ```html * * * * * * * * * * * * ``` * * @see README.mdx - Complete API documentation, usage examples, and implementation notes * @see CHANGELOG.mdx - Component version history and breaking changes * @see TESTING.mdx - Testing documentation and coverage reports * * @uswds-css-reference https://github.com/uswds/uswds/tree/develop/packages/usa-select/src/styles/_usa-select.scss * @uswds-docs https://designsystem.digital.gov/components/select/ * @uswds-guidance https://designsystem.digital.gov/components/select/#guidance * @uswds-accessibility https://designsystem.digital.gov/components/select/#accessibility */ @customElement('usa-select') export class USASelect extends LitElement { private _selectId = ''; static override styles = css` :host { display: inline-block; width: 100%; } `; @property({ type: String }) name = ''; @property({ type: String }) value = ''; @property({ type: String }) label = ''; @property({ type: String }) hint = ''; @property({ type: String }) error = ''; @property({ type: String }) success = ''; @property({ type: Boolean, reflect: true }) disabled = false; @property({ type: Boolean }) required = false; @property({ type: Array }) options: Array<{ value: string; text: string; disabled?: boolean }> = []; @property({ type: String }) defaultOption = ''; /** * Whether to render in compact mode (no form-group wrapper) * Use this when the select is inside a fieldset or pattern where * the parent handles spacing and grouping */ @property({ type: Boolean }) compact = false; private selectElement?: HTMLSelectElement; // Use light DOM for USWDS compatibility protected override createRenderRoot(): HTMLElement { return this as any; } override connectedCallback() { super.connectedCallback(); // Set web component managed flag to prevent USWDS auto-initialization conflicts this.setAttribute('data-web-component-managed', 'true'); // Note: USWDS Select is CSS-only - no JavaScript initialization needed. // The native ${this.renderDefaultOption()} ${(this.options || []).map((option) => this.renderOption(option))} `; const selectTemplate = html` ${this.renderLabel(selectId)} ${this.renderHint(selectId)} ${this.renderError(selectId)} ${this.renderSuccess(selectId)} ${selectElement} `; // Compact mode: no form-group wrapper (for use inside fieldsets/patterns) if (this.compact) { return selectTemplate; } // Standard mode: wrap in form-group return html`
${selectTemplate}
`; } }