) {
// ARCHITECTURE: Script Tag Pattern
// USWDS is loaded globally via script tag in .storybook/preview-head.html
// Components just render HTML - USWDS enhances automatically via window.USWDS
// ARCHITECTURE: USWDS-Mirrored Behavior Pattern
// Uses dedicated behavior file (usa-time-picker-behavior.ts) that replicates USWDS source exactly
super.firstUpdated?.(changedProperties);
// Wait for DOM to be fully rendered
await this.updateComplete;
await new Promise(resolve => requestAnimationFrame(() => resolve(undefined)));
// Initialize using mirrored USWDS behavior
this.cleanup = initializeTimePicker(this);
}
override disconnectedCallback() {
super.disconnectedCallback();
this.cleanup?.();
}
/**
* Format time value for display (convert 24-hour to 12-hour with AM/PM if needed)
* USWDS time-picker expects 12-hour format like "2:30pm"
*/
private formatTimeForDisplay(value: string): string {
if (!value) return '';
// If already has AM/PM, return as-is
if (/[ap]m/i.test(value)) return value;
// Parse 24-hour format (HH:MM or H:MM)
const match = value.match(/^(\d{1,2}):(\d{2})$/);
if (!match) return value;
const hours24 = parseInt(match[1], 10);
const minutes = match[2];
// Convert to 12-hour format
const hours12 = hours24 % 12 || 12;
const ampm = hours24 < 12 ? 'am' : 'pm';
return `${hours12}:${minutes}${ampm}`;
}
private handleTimeChange(e: Event) {
const input = e.target as HTMLInputElement;
this.value = input.value;
this.dispatchEvent(
new CustomEvent('time-change', {
detail: {
value: this.value,
displayValue: input.value,
} as TimeChangeDetail,
bubbles: true,
composed: true,
})
);
}
private renderError() {
if (!this.error) return '';
return html`
Error: ${this.error}
`;
}
private renderRequiredIndicator() {
if (!this.required) return '';
return html`* `;
}
private renderHint() {
if (!this.hint) return '';
return html`${this.hint}
`;
}
private renderInput(inputClasses: string, ariaDescribedBy: string) {
const formattedValue = this.formatTimeForDisplay(this.value);
return html`
`;
}
override render() {
const formGroupClasses = [
'usa-form-group',
this.error || this.errorState ? 'usa-form-group--error' : '',
this.required ? 'usa-form-group--required' : '',
]
.filter(Boolean)
.join(' ');
const inputClasses = ['usa-input', this.error || this.errorState ? 'usa-input--error' : '']
.filter(Boolean)
.join(' ');
const ariaDescribedBy = [
this.hint ? `${this.inputId}-hint` : '',
this.error ? `${this.inputId}-error` : '',
]
.filter(Boolean)
.join(' ');
// Provide EXACTLY what USWDS time-picker expects (from official template):
// Label OUTSIDE, only input directly inside .usa-time-picker container
// USWDS will transform this into a full combo-box
return html`
`;
}
// Public API methods for imperative control
show() {
console.log('Time Picker: Show triggered - delegating to USWDS');
// USWDS time picker will handle dropdown showing via its event listeners
}
hide() {
console.log('Time Picker: Hide triggered - delegating to USWDS');
// USWDS time picker will handle dropdown hiding via its event listeners
}
updateOptions() {
console.log('Time Picker: Update options triggered - delegating to USWDS');
// USWDS time picker will handle option generation automatically
}
}