import { StyledToggle } from '@/components/General/Toggle'; import { LitElement, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import '@components/General/Input'; import '@components/General/Fieldset'; import '@components/General/Select'; interface DateTimeFormatOptions { locale: string; weekday: 'long' | 'short' | 'narrow' | ''; year: 'numeric' | '2-digit' | ''; month: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow' | ''; day: 'numeric' | '2-digit' | ''; hour: 'numeric' | '2-digit' | ''; minute: 'numeric' | '2-digit' | ''; second: 'numeric' | '2-digit' | ''; hour12: boolean; } const DEFAULT_OPTIONS: DateTimeFormatOptions = { locale: 'en-US', weekday: 'short', year: 'numeric', month: 'long', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true, }; @customElement('arx-date-time-settings') export class DateTimeSettings extends LitElement { @state() private options: DateTimeFormatOptions = { ...DEFAULT_OPTIONS }; @state() private previewDate = new Date(); override connectedCallback() { super.connectedCallback(); this.loadFromLocalStorage(); setInterval(() => { this.previewDate = new Date(); this.requestUpdate(); }, 1000); } private loadFromLocalStorage() { const savedOptions = localStorage.getItem('dateTimeFormatOptions'); if (savedOptions) { try { this.options = { ...DEFAULT_OPTIONS, ...JSON.parse(savedOptions) }; } catch (e) { console.error('Failed to parse saved options', e); this.options = { ...DEFAULT_OPTIONS }; } } } private saveToLocalStorage() { localStorage.setItem('dateTimeFormatOptions', JSON.stringify(this.options)); this.dispatchEvent( new CustomEvent('settings-changed', { bubbles: true, composed: true, detail: { options: this.options }, }), ); } private handleChange(key: keyof DateTimeFormatOptions, e: Event) { const target = e.target as HTMLSelectElement | HTMLInputElement | StyledToggle; let value: string | boolean | undefined = target.value; if (key === 'hour12' && target instanceof StyledToggle) value = target.checked; this.options = { ...this.options, [key]: value, }; if (key === 'locale') this.requestUpdate(); this.saveToLocalStorage(); } private formatWithOption(option: string, type: keyof DateTimeFormatOptions): string { if (option === '') return ''; const date = this.previewDate; const locale = this.options.locale; const formatterOptions: Intl.DateTimeFormatOptions = { [type]: option, }; // Special case for hour to respect hour12 setting if (type === 'hour') formatterOptions.hour12 = this.options.hour12; try { return new Intl.DateTimeFormat(locale, formatterOptions).format(date); } catch (e) { console.error(`Error formatting with option ${option} for ${type}`, e); return 'Error: Invalid format'; } } private formatPreview(): string { return new Date(this.previewDate).toLocaleString(this.options.locale, { weekday: this.options.weekday === '' ? undefined : this.options.weekday, year: this.options.year === '' ? undefined : this.options.year, month: this.options.month === '' ? undefined : this.options.month, day: this.options.day === '' ? undefined : this.options.day, hour: this.options.hour === '' ? undefined : this.options.hour, minute: this.options.minute === '' ? undefined : this.options.minute, second: this.options.second === '' ? undefined : this.options.second, hour12: this.options.hour12, }); } override render() { return html` this.handleChange('locale', e)} > this.handleChange('weekday', e)} .options=${[ { value: 'long', label: `Long (${this.formatWithOption('long', 'weekday')})`, }, { value: 'short', label: `Short (${this.formatWithOption('short', 'weekday')})`, }, { value: 'narrow', label: `Narrow (${this.formatWithOption('narrow', 'weekday')})`, }, ]} > this.handleChange('year', e)} .options=${[ { value: 'numeric', label: `Numeric (${this.formatWithOption('numeric', 'year')})`, }, { value: '2-digit', label: `2-digit (${this.formatWithOption('2-digit', 'year')})`, }, { value: '', label: 'None', }, ]} > this.handleChange('month', e)} .options=${[ { value: 'long', label: `Long (${this.formatWithOption('long', 'month')})`, }, { value: 'short', label: `Short (${this.formatWithOption('short', 'month')})`, }, { value: 'narrow', label: `Narrow (${this.formatWithOption('narrow', 'month')})`, }, { value: 'numeric', label: `Numeric (${this.formatWithOption('numeric', 'month')})`, }, { value: '2-digit', label: `2-digit (${this.formatWithOption('2-digit', 'month')})`, }, { value: '', label: 'None', }, ]} > this.handleChange('day', e)} .options=${[ { value: 'numeric', label: `Numeric (${this.formatWithOption('numeric', 'day')})`, }, { value: '2-digit', label: `2-digit (${this.formatWithOption('2-digit', 'day')})`, }, { value: '', label: 'None', }, ]} > this.handleChange('hour', e)} .options=${[ { value: 'numeric', label: 'Numeric', }, { value: '2-digit', label: '2-digit', }, { value: '', label: 'None', }, ]} > this.handleChange('minute', e)} .options=${[ { value: 'numeric', label: 'Numeric', }, { value: '2-digit', label: '2-digit', }, { value: '', label: 'None', }, ]} > this.handleChange('second', e)} .options=${[ { value: 'numeric', label: 'Numeric', }, { value: '2-digit', label: '2-digit', }, { value: '', label: 'None', }, ]} > this.handleChange('hour12', e)} >

Preview

${this.formatPreview()}

`; } }