) {
// Update the select element if it exists
if (this.selectElement) {
this.updateSelectElement();
}
// Apply captured content using DOM manipulation
this.applySlottedContent();
}
private applySlottedContent() {
if (this.slottedContent) {
const slotElement = this.querySelector('slot');
if (slotElement && this.options.length === 0) {
// Parse content safely using DOMParser instead of innerHTML
const parser = new DOMParser();
const doc = parser.parseFromString(`${this.slottedContent}
`, 'text/html');
const tempDiv = doc.querySelector('div');
if (tempDiv) {
slotElement.replaceWith(...Array.from(tempDiv.childNodes));
}
}
}
}
private updateSelectElement() {
if (!this.selectElement) return;
// Update select properties
this.selectElement.name = this.name;
this.selectElement.value = this.value;
this.selectElement.disabled = this.disabled;
this.selectElement.required = this.required;
// Update classes
// Remove existing USWDS classes
const classesToRemove = Array.from(this.selectElement.classList).filter((className) =>
className.startsWith('usa-select')
);
classesToRemove.forEach((className) => this.selectElement?.classList.remove(className));
// Always add base usa-select class
this.selectElement.classList.add('usa-select');
// Add error class if error exists
if (this.error) {
this.selectElement.classList.add('usa-select--error');
}
// Add success class if success exists
if (this.success) {
this.selectElement.classList.add('usa-select--success');
}
// Update ARIA attributes
const describedByIds: string[] = [];
if (this.hint) {
describedByIds.push(`${this.selectId}-hint`);
}
if (this.error) {
describedByIds.push(`${this.selectId}-error`);
}
if (this.success) {
describedByIds.push(`${this.selectId}-success`);
}
if (describedByIds.length > 0) {
this.selectElement.setAttribute('aria-describedby', describedByIds.join(' '));
} else {
this.selectElement.removeAttribute('aria-describedby');
}
if (this.error) {
this.selectElement.setAttribute('aria-invalid', 'true');
} else {
this.selectElement.removeAttribute('aria-invalid');
}
}
private handleChange(e: Event) {
const select = e.target as HTMLSelectElement;
this.value = select.value;
// Dispatch both change and input events for consistency with other form elements
this.dispatchEvent(
new CustomEvent('change', {
detail: { value: this.value },
bubbles: true,
composed: true,
})
);
this.dispatchEvent(
new CustomEvent('input', {
detail: { value: this.value },
bubbles: true,
composed: true,
})
);
}
private get selectId() {
// Always check for element id first, then use cached generated id
if (this.id) {
return this.id;
}
if (!this._selectId) {
this._selectId = `select-${Math.random().toString(36).substring(2, 11)}`;
}
return this._selectId;
}
private async initializeUSWDSSelect() {
// Prevent multiple initializations
if (this.usingUSWDSEnhancement) {
console.log(`⚠️ ${this.constructor.name}: Already initialized, skipping duplicate initialization`);
return;
}
// Check if select is CSS-only before attempting to load JavaScript
const { isCSSOnlyComponent } = await import('../../utils/uswds-loader.js');
if (isCSSOnlyComponent('select')) {
console.log('✅ USWDS select is CSS-only, using web component behavior');
this.setupFallbackBehavior();
return;
}
console.log(`🎯 Select: Initializing with tree-shaking optimization`);
try {
// Tree-shaking: Import only the specific USWDS component module
const module = await import('@uswds/uswds');
this.uswdsModule = module.default;
// Initialize the USWDS component
if (this.uswdsModule && typeof this.uswdsModule.on === 'function') {
this.uswdsModule.on(this);
console.log(`✅ Tree-shaken USWDS select initialized successfully`);
this.usingUSWDSEnhancement = true;
return; // USWDS will handle component behavior
} else {
console.warn(`⚠️ Select: Module doesn't have expected initialization methods`);
console.log(`🔍 Available methods:`, Object.keys(this.uswdsModule || {}));
this.setupFallbackBehavior();
}
} catch (error) {
console.warn(`⚠️ Tree-shaking failed for Select, falling back to full USWDS:`, error);
await this.loadFullUSWDSLibrary();
}
}
private async loadFullUSWDSLibrary() {
try {
if (typeof (window as any).USWDS === 'undefined') {
// Full USWDS library not available, setup fallback
console.warn('⚠️ Full USWDS library not available, using fallback behavior');
this.setupFallbackBehavior();
return;
}
await this.initializeWithGlobalUSWDS();
} catch (error) {
console.warn('⚠️ Full USWDS initialization failed:', error);
this.setupFallbackBehavior();
}
}
private async initializeWithGlobalUSWDS() {
// Prevent multiple initializations
if (this.uswdsInitialized) {
console.log(`⚠️ Select: Already initialized globally, skipping duplicate initialization`);
return;
}
const USWDS = (window as any).USWDS;
if (USWDS && USWDS.select && typeof USWDS.select.on === 'function') {
USWDS.select.on(this);
this.uswdsInitialized = true;
console.log('✅ Global USWDS select initialized successfully');
} else {
console.warn('⚠️ Global USWDS select not available');
this.setupFallbackBehavior();
}
}
private setupFallbackBehavior() {
console.log('🚀 Setting up fallback select behavior');
// Basic select functionality is handled by the browser
}
private cleanupUSWDS() {
try {
if (this.uswdsModule && typeof this.uswdsModule.off === 'function') {
this.uswdsModule.off(this);
console.log('✅ Tree-shaken USWDS select cleaned up');
} else if (typeof window !== 'undefined' && typeof (window as any).USWDS !== 'undefined') {
const USWDS = (window as any).USWDS;
if (USWDS.select && typeof USWDS.select.off === 'function') {
USWDS.select.off(this);
console.log('✅ Global USWDS select cleaned up');
}
}
} catch (error) {
console.warn('⚠️ USWDS cleanup failed:', error);
}
this.uswdsModule = null;
}
override disconnectedCallback() {
super.disconnectedCallback();
// Clean up tree-shaken USWDS module
this.cleanupUSWDS();
// Reset enhancement flag to allow reinitialization
this.usingUSWDSEnhancement = false;
}
private renderLabel(selectId: string) {
if (!this.label) return '';
return html`
`;
}
private renderRequiredIndicator() {
if (!this.required) return '';
return html`*`;
}
private renderHint(selectId: string) {
if (!this.hint) return '';
return html`${this.hint}`;
}
private renderError(selectId: string) {
if (!this.error) return '';
return html`
Error: ${this.error}
`;
}
private renderSuccess(selectId: string) {
if (!this.success) return '';
return html`
Success: ${this.success}
`;
}
private renderDefaultOption() {
if (!this.defaultOption) return '';
return html``;
}
private renderOption(option: SelectOption) {
return html`
`;
}
override render() {
const selectId = this.selectId;
const describedByIds: string[] = [];
if (this.hint) {
describedByIds.push(`${selectId}-hint`);
}
if (this.error) {
describedByIds.push(`${selectId}-error`);
}
if (this.success) {
describedByIds.push(`${selectId}-success`);
}
const formGroupClasses = ['usa-form-group', this.error ? 'usa-form-group--error' : '']
.filter(Boolean)
.join(' ');
return html`
${this.renderLabel(selectId)}
${this.renderHint(selectId)}
${this.renderError(selectId)}
${this.renderSuccess(selectId)}
`;
}
}