world-clock-strip 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/world-clock.ts"],"sourcesContent":["import styles from \"./world-clock.css?inline\";\n\nexport interface ClockLocation {\n label: string;\n timeZone: string;\n weatherQuery?: string;\n}\n\nexport interface ClockWeatherSnapshot {\n state: \"pass\" | \"fail\";\n condition: string;\n description: string;\n code?: number;\n isDay?: boolean;\n temperature?: number | null;\n temperatureUnit?: string;\n cloudCover?: number | null;\n precipitation?: number | null;\n latitude?: number;\n longitude?: number;\n locationName?: string;\n}\n\nexport type VisualPreset = \"default\" | \"minimal\" | \"cinematic\" | \"wallboard\";\n\nexport interface WorldClockConfig {\n locations: ClockLocation[];\n weatherEnabled: boolean;\n weatherEndpoint: string;\n visualPreset: VisualPreset;\n}\n\nexport interface WorldClockStripOptions {\n locations?: ClockLocation[];\n weatherEnabled?: boolean;\n weatherEndpoint?: string;\n weatherOverrides?: Record<string, ClockWeatherSnapshot>;\n visualPreset?: VisualPreset;\n readOnly?: boolean;\n persistKey?: string;\n enableUrlState?: boolean;\n shareQueryParam?: string;\n cityCatalog?: CommonClockCity[];\n}\n\ninterface ConfigDraftLocation {\n label: string;\n timeZone: string;\n weatherQuery: string;\n}\n\ninterface ConfigDrawerDraft {\n locations: ConfigDraftLocation[];\n weatherEnabled: boolean;\n weatherEndpoint: string;\n visualPreset: VisualPreset;\n}\n\nexport interface CommonClockCity {\n label: string;\n timeZone: string;\n weatherQuery: string;\n country: string;\n}\n\ninterface RenderFocusSnapshot {\n selector: string;\n start: number | null;\n end: number | null;\n}\n\ninterface WorldClockConfigChangeDetail {\n config: WorldClockConfig;\n source: \"api\" | \"drawer\" | \"url\" | \"storage\" | \"preset\" | \"attribute\";\n}\n\ninterface ClockWeatherEntry {\n label: string;\n timeZone: string;\n weatherQuery: string;\n weather: ClockWeatherSnapshot | null;\n}\n\ninterface ClockWeatherPayload {\n fetchedAt: string;\n locations: ClockWeatherEntry[];\n}\n\ninterface ClockDescriptor {\n label: string;\n timeZone: string;\n weatherQuery: string;\n positionPercent: number;\n lane: number;\n labelOffsetPx: number;\n edgeInsetPx?: number;\n timeParts: {\n hour24: number;\n minute24: number;\n timeText: string;\n dayText: string;\n zoneText: string;\n };\n weather: ClockWeatherSnapshot | null;\n}\n\ntype GeocodeResult = {\n latitude: number;\n longitude: number;\n displayName: string;\n};\n\ntype WeatherResult = {\n temperature_2m?: number;\n weather_code?: number;\n is_day?: number;\n cloud_cover?: number;\n precipitation?: number;\n};\n\nconst CLOCK_WEATHER_TTL_MS = 15 * 60 * 1000;\nconst GEOCODE_TTL_MS = 24 * 60 * 60 * 1000;\nconst WORLD_CLOCK_TAG_NAME = \"world-clock-strip\";\nconst WORLD_CLOCK_TIME_ZONE_DATALIST_ID = \"world-clock-time-zone-options\";\nconst DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM = \"worldClock\";\nconst DEFAULT_WORLD_CLOCK_PRESET_STORAGE_KEY = \"world-clock-strip:presets\";\n\nconst geocodeCache = new Map<string, { expiresAt: number; value: GeocodeResult }>();\nconst weatherCache = new Map<string, { expiresAt: number; value: WeatherResult }>();\n\nconst US_FAHRENHEIT_TIME_ZONES = new Set([\n \"America/Adak\",\n \"America/Anchorage\",\n \"America/Boise\",\n \"America/Chicago\",\n \"America/Denver\",\n \"America/Detroit\",\n \"America/Indiana/Indianapolis\",\n \"America/Indiana/Knox\",\n \"America/Indiana/Marengo\",\n \"America/Indiana/Petersburg\",\n \"America/Indiana/Tell_City\",\n \"America/Indiana/Vevay\",\n \"America/Indiana/Vincennes\",\n \"America/Indiana/Winamac\",\n \"America/Juneau\",\n \"America/Kentucky/Louisville\",\n \"America/Kentucky/Monticello\",\n \"America/Los_Angeles\",\n \"America/Menominee\",\n \"America/Metlakatla\",\n \"America/New_York\",\n \"America/Nome\",\n \"America/North_Dakota/Beulah\",\n \"America/North_Dakota/Center\",\n \"America/North_Dakota/New_Salem\",\n \"America/Phoenix\",\n \"America/Puerto_Rico\",\n \"America/Sitka\",\n \"America/Yakutat\",\n \"Pacific/Guam\",\n \"Pacific/Honolulu\",\n \"Pacific/Pago_Pago\",\n \"Pacific/Saipan\",\n]);\n\nconst WEATHER_IMAGE_BY_CONDITION: Record<string, string> = {\n \"clear-day\": resolveWeatherAssetUrl(\"Sunny.webp\"),\n \"clear-night\": resolveWeatherAssetUrl(\"starry-night.webp\"),\n cloudy: resolveWeatherAssetUrl(\"Cloudy.webp\"),\n rain: resolveWeatherAssetUrl(\"Rainy.webp\"),\n storm: resolveWeatherAssetUrl(\"storm.webp\"),\n snow: resolveWeatherAssetUrl(\"Snow.webp\"),\n fog: resolveWeatherAssetUrl(\"Foggy.webp\"),\n};\n\nexport const defaultClockLocations: ClockLocation[] = [\n { label: \"Las Vegas\", timeZone: \"America/Los_Angeles\", weatherQuery: \"Las Vegas, Nevada\" },\n { label: \"Israel\", timeZone: \"Asia/Jerusalem\", weatherQuery: \"Jerusalem, Israel\" },\n { label: \"New Delhi\", timeZone: \"Asia/Kolkata\", weatherQuery: \"New Delhi, India\" },\n { label: \"Macau\", timeZone: \"Asia/Macau\", weatherQuery: \"Macau\" },\n { label: \"Sydney\", timeZone: \"Australia/Sydney\", weatherQuery: \"Sydney, Australia\" },\n];\n\nconst fallbackClockTimeZones = [\n \"America/Los_Angeles\",\n \"America/Denver\",\n \"America/Chicago\",\n \"America/New_York\",\n \"Europe/London\",\n \"Europe/Paris\",\n \"Asia/Jerusalem\",\n \"Asia/Dubai\",\n \"Asia/Kolkata\",\n \"Asia/Singapore\",\n \"Asia/Tokyo\",\n \"Australia/Sydney\",\n];\n\nconst commonClockCities: CommonClockCity[] = [\n { label: \"Los Angeles\", timeZone: \"America/Los_Angeles\", weatherQuery: \"Los Angeles, California\", country: \"United States\" },\n { label: \"Las Vegas\", timeZone: \"America/Los_Angeles\", weatherQuery: \"Las Vegas, Nevada\", country: \"United States\" },\n { label: \"Denver\", timeZone: \"America/Denver\", weatherQuery: \"Denver, Colorado\", country: \"United States\" },\n { label: \"Chicago\", timeZone: \"America/Chicago\", weatherQuery: \"Chicago, Illinois\", country: \"United States\" },\n { label: \"New York\", timeZone: \"America/New_York\", weatherQuery: \"New York, New York\", country: \"United States\" },\n { label: \"Honolulu\", timeZone: \"Pacific/Honolulu\", weatherQuery: \"Honolulu, Hawaii\", country: \"United States\" },\n { label: \"London\", timeZone: \"Europe/London\", weatherQuery: \"London, United Kingdom\", country: \"United Kingdom\" },\n { label: \"Paris\", timeZone: \"Europe/Paris\", weatherQuery: \"Paris, France\", country: \"France\" },\n { label: \"Berlin\", timeZone: \"Europe/Berlin\", weatherQuery: \"Berlin, Germany\", country: \"Germany\" },\n { label: \"Jerusalem\", timeZone: \"Asia/Jerusalem\", weatherQuery: \"Jerusalem, Israel\", country: \"Israel\" },\n { label: \"Dubai\", timeZone: \"Asia/Dubai\", weatherQuery: \"Dubai, United Arab Emirates\", country: \"United Arab Emirates\" },\n { label: \"New Delhi\", timeZone: \"Asia/Kolkata\", weatherQuery: \"New Delhi, India\", country: \"India\" },\n { label: \"Singapore\", timeZone: \"Asia/Singapore\", weatherQuery: \"Singapore\", country: \"Singapore\" },\n { label: \"Hong Kong\", timeZone: \"Asia/Hong_Kong\", weatherQuery: \"Hong Kong\", country: \"Hong Kong\" },\n { label: \"Macau\", timeZone: \"Asia/Macau\", weatherQuery: \"Macau\", country: \"Macau\" },\n { label: \"Tokyo\", timeZone: \"Asia/Tokyo\", weatherQuery: \"Tokyo, Japan\", country: \"Japan\" },\n { label: \"Seoul\", timeZone: \"Asia/Seoul\", weatherQuery: \"Seoul, South Korea\", country: \"South Korea\" },\n { label: \"Sydney\", timeZone: \"Australia/Sydney\", weatherQuery: \"Sydney, Australia\", country: \"Australia\" },\n { label: \"Auckland\", timeZone: \"Pacific/Auckland\", weatherQuery: \"Auckland, New Zealand\", country: \"New Zealand\" },\n { label: \"Sao Paulo\", timeZone: \"America/Sao_Paulo\", weatherQuery: \"Sao Paulo, Brazil\", country: \"Brazil\" },\n];\n\nexport class WorldClockStripElement extends HTMLElement {\n static get observedAttributes(): string[] {\n return [\n \"locations\",\n \"weather-enabled\",\n \"weather-endpoint\",\n \"visual-preset\",\n \"read-only\",\n \"persist-key\",\n \"enable-url-state\",\n \"share-query-param\",\n ];\n }\n\n private readonly root: ShadowRoot;\n private locationsState: ClockLocation[] = normalizeClockLocations(defaultClockLocations);\n private weatherEnabledState = true;\n private weatherEndpointState = \"\";\n private visualPresetState: VisualPreset = \"default\";\n private readOnlyState = false;\n private persistKeyState = \"\";\n private enableUrlState = false;\n private shareQueryParamState = DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM;\n private cityCatalogState: CommonClockCity[] = commonClockCities;\n private weatherOverridesState: Record<string, ClockWeatherSnapshot> = {};\n private weatherByKey = new Map<string, ClockWeatherSnapshot | null>();\n private weatherFetchedAt = 0;\n private weatherRequestKey = \"\";\n private clockTimer: number | null = null;\n private weatherTimer: number | null = null;\n private inFlightWeatherRequest: AbortController | null = null;\n private configDrawerOpen = false;\n private advancedSettingsOpen = false;\n private configDraftState: ConfigDrawerDraft = this.createConfigDraft();\n private addLocationOpen = false;\n private addLocationQuery = \"\";\n private addLocationPreferredName = \"\";\n private selectedCommonCityKey = \"\";\n private pendingDeleteIndex: number | null = null;\n private selectedLocationIndex: number | null = null;\n private customLocationDraft: ConfigDraftLocation = { label: \"\", timeZone: \"\", weatherQuery: \"\" };\n private presetNameDraft = \"\";\n private importExportDraft = \"\";\n private importExportOpen = false;\n private statusMessage = \"\";\n\n constructor() {\n super();\n this.root = this.attachShadow({ mode: \"open\" });\n this.readAttributes();\n this.configDraftState = this.createConfigDraft();\n this.root.addEventListener(\"click\", this.handleRootClick.bind(this));\n this.root.addEventListener(\"input\", this.handleRootInput.bind(this));\n this.root.addEventListener(\"change\", this.handleRootChange.bind(this));\n this.root.addEventListener(\"focusout\", this.handleRootFocusOut.bind(this));\n }\n\n connectedCallback(): void {\n this.initializeSharedState();\n this.render();\n this.startClockRefresh();\n this.startWeatherRefresh(true);\n }\n\n disconnectedCallback(): void {\n this.stopClockRefresh();\n this.stopWeatherRefresh();\n this.inFlightWeatherRequest?.abort();\n this.inFlightWeatherRequest = null;\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (name === \"locations\") {\n this.locationsState = parseLocationsAttribute(newValue, this.locationsState);\n this.handleConfigurationChange(true);\n return;\n }\n\n if (name === \"weather-enabled\") {\n this.weatherEnabledState = newValue == null ? true : newValue !== \"false\";\n this.handleConfigurationChange(true);\n return;\n }\n\n if (name === \"weather-endpoint\") {\n this.weatherEndpointState = String(newValue || \"\").trim();\n this.handleConfigurationChange(true, \"attribute\");\n return;\n }\n\n if (name === \"visual-preset\") {\n this.visualPresetState = normalizeVisualPreset(newValue);\n this.handleConfigurationChange(false, \"attribute\");\n return;\n }\n\n if (name === \"read-only\") {\n this.readOnlyState = newValue != null && newValue !== \"false\";\n this.render();\n return;\n }\n\n if (name === \"persist-key\") {\n this.persistKeyState = String(newValue || \"\").trim();\n return;\n }\n\n if (name === \"enable-url-state\") {\n this.enableUrlState = newValue != null && newValue !== \"false\";\n return;\n }\n\n if (name === \"share-query-param\") {\n this.shareQueryParamState = String(newValue || DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM).trim() || DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM;\n }\n\n }\n\n get locations(): ClockLocation[] {\n return this.locationsState.map((location) => ({ ...location }));\n }\n\n set locations(value: ClockLocation[]) {\n this.locationsState = normalizeClockLocations(value);\n this.handleConfigurationChange(true, \"api\");\n }\n\n get weatherEnabled(): boolean {\n return this.weatherEnabledState;\n }\n\n set weatherEnabled(value: boolean) {\n this.weatherEnabledState = Boolean(value);\n this.handleConfigurationChange(true, \"api\");\n }\n\n get weatherEndpoint(): string {\n return this.weatherEndpointState;\n }\n\n set weatherEndpoint(value: string) {\n this.weatherEndpointState = String(value || \"\").trim();\n this.handleConfigurationChange(true, \"api\");\n }\n\n get visualPreset(): VisualPreset {\n return this.visualPresetState;\n }\n\n set visualPreset(value: VisualPreset) {\n this.visualPresetState = normalizeVisualPreset(value);\n this.handleConfigurationChange(false, \"api\");\n }\n\n get readOnly(): boolean {\n return this.readOnlyState;\n }\n\n set readOnly(value: boolean) {\n this.readOnlyState = Boolean(value);\n this.render();\n }\n\n get persistKey(): string {\n return this.persistKeyState;\n }\n\n set persistKey(value: string) {\n this.persistKeyState = String(value || \"\").trim();\n }\n\n get shareQueryParam(): string {\n return this.shareQueryParamState;\n }\n\n set shareQueryParam(value: string) {\n this.shareQueryParamState = String(value || DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM).trim() || DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM;\n }\n\n get cityCatalog(): CommonClockCity[] {\n return this.cityCatalogState.map((city) => ({ ...city }));\n }\n\n set cityCatalog(value: CommonClockCity[]) {\n this.cityCatalogState = normalizeCommonClockCities(value);\n this.render();\n }\n\n get weatherOverrides(): Record<string, ClockWeatherSnapshot> {\n return { ...this.weatherOverridesState };\n }\n\n set weatherOverrides(value: Record<string, ClockWeatherSnapshot>) {\n this.weatherOverridesState = value && typeof value === \"object\" ? { ...value } : {};\n this.handleConfigurationChange(false);\n }\n\n get config(): WorldClockConfig {\n return {\n locations: this.locations,\n weatherEnabled: this.weatherEnabledState,\n weatherEndpoint: this.weatherEndpointState,\n visualPreset: this.visualPresetState,\n };\n }\n\n set config(value: WorldClockConfig) {\n this.applyConfigValue(value, \"api\");\n }\n\n private readAttributes(): void {\n if (this.hasAttribute(\"locations\")) {\n this.locationsState = parseLocationsAttribute(this.getAttribute(\"locations\"), this.locationsState);\n }\n\n if (this.hasAttribute(\"weather-enabled\")) {\n this.weatherEnabledState = this.getAttribute(\"weather-enabled\") !== \"false\";\n }\n\n if (this.hasAttribute(\"weather-endpoint\")) {\n this.weatherEndpointState = String(this.getAttribute(\"weather-endpoint\") || \"\").trim();\n }\n\n if (this.hasAttribute(\"visual-preset\")) {\n this.visualPresetState = normalizeVisualPreset(this.getAttribute(\"visual-preset\"));\n }\n\n if (this.hasAttribute(\"read-only\")) {\n this.readOnlyState = this.getAttribute(\"read-only\") !== \"false\";\n }\n\n if (this.hasAttribute(\"persist-key\")) {\n this.persistKeyState = String(this.getAttribute(\"persist-key\") || \"\").trim();\n }\n\n if (this.hasAttribute(\"enable-url-state\")) {\n this.enableUrlState = this.getAttribute(\"enable-url-state\") !== \"false\";\n }\n\n if (this.hasAttribute(\"share-query-param\")) {\n this.shareQueryParamState = String(this.getAttribute(\"share-query-param\") || DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM).trim() || DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM;\n }\n\n }\n\n private initializeSharedState(): void {\n if (this.persistKeyState) {\n const stored = readWorldClockConfigFromStorage(this.persistKeyState);\n if (stored) {\n this.applyConfigValue(stored, \"storage\");\n }\n }\n\n if (this.enableUrlState) {\n const configFromUrl = readWorldClockConfigFromUrl(this.shareQueryParamState);\n if (configFromUrl) {\n this.applyConfigValue(configFromUrl, \"url\");\n }\n }\n }\n\n private handleConfigurationChange(refreshWeather: boolean, source: WorldClockConfigChangeDetail[\"source\"] = \"api\"): void {\n if (!this.weatherEnabledState) {\n this.weatherByKey = new Map();\n this.weatherFetchedAt = 0;\n this.weatherRequestKey = \"\";\n this.inFlightWeatherRequest?.abort();\n this.inFlightWeatherRequest = null;\n }\n\n this.persistCurrentConfig();\n this.dispatchConfigChange(source);\n\n this.render();\n\n if (this.isConnected) {\n if (refreshWeather) {\n this.startWeatherRefresh(true);\n } else {\n this.render();\n }\n }\n }\n\n private applyConfigValue(value: Partial<WorldClockConfig>, source: WorldClockConfigChangeDetail[\"source\"]): void {\n if (value.locations) {\n this.locationsState = normalizeClockLocations(value.locations);\n }\n if (typeof value.weatherEnabled === \"boolean\") {\n this.weatherEnabledState = value.weatherEnabled;\n }\n if (typeof value.weatherEndpoint === \"string\") {\n this.weatherEndpointState = value.weatherEndpoint.trim();\n }\n if (value.visualPreset) {\n this.visualPresetState = normalizeVisualPreset(value.visualPreset);\n }\n\n this.syncConfigDraftFromState();\n this.handleConfigurationChange(true, source);\n }\n\n private persistCurrentConfig(): void {\n if (this.persistKeyState) {\n writeWorldClockConfigToStorage(this.persistKeyState, this.config);\n }\n }\n\n private dispatchConfigChange(source: WorldClockConfigChangeDetail[\"source\"]): void {\n this.dispatchEvent(\n new CustomEvent<WorldClockConfigChangeDetail>(\"configchange\", {\n detail: {\n config: this.config,\n source,\n },\n })\n );\n }\n\n private startClockRefresh(): void {\n this.stopClockRefresh();\n\n const renderOnMinute = () => {\n this.render();\n const delay = 60000 - (Date.now() % 60000) + 50;\n this.clockTimer = window.setTimeout(renderOnMinute, delay);\n };\n\n renderOnMinute();\n }\n\n private stopClockRefresh(): void {\n if (this.clockTimer != null) {\n window.clearTimeout(this.clockTimer);\n this.clockTimer = null;\n }\n }\n\n private startWeatherRefresh(force: boolean): void {\n this.stopWeatherRefresh();\n\n if (!this.weatherEnabledState || !this.locationsState.length) {\n this.render();\n return;\n }\n\n void this.refreshWeather(force);\n this.weatherTimer = window.setInterval(() => {\n void this.refreshWeather(false);\n }, CLOCK_WEATHER_TTL_MS);\n }\n\n private stopWeatherRefresh(): void {\n if (this.weatherTimer != null) {\n window.clearInterval(this.weatherTimer);\n this.weatherTimer = null;\n }\n }\n\n private async refreshWeather(force: boolean): Promise<void> {\n const requestKey = this.buildWeatherRequestKey();\n const isFresh = this.weatherFetchedAt > 0 && Date.now() - this.weatherFetchedAt < CLOCK_WEATHER_TTL_MS;\n\n if (!force && isFresh && requestKey === this.weatherRequestKey) {\n return;\n }\n\n this.inFlightWeatherRequest?.abort();\n const controller = new AbortController();\n this.inFlightWeatherRequest = controller;\n\n try {\n const payload = await fetchClockWeather(this.locationsState, this.weatherEndpointState, controller.signal);\n if (controller.signal.aborted || requestKey !== this.buildWeatherRequestKey()) {\n return;\n }\n\n const byKey = new Map<string, ClockWeatherSnapshot | null>();\n for (const entry of payload.locations) {\n byKey.set(getClockLocationKey(entry), entry.weather ?? null);\n }\n\n this.weatherByKey = byKey;\n this.weatherFetchedAt = Date.now();\n this.weatherRequestKey = requestKey;\n } catch (error) {\n if (controller.signal.aborted) {\n return;\n }\n\n console.error(\"World clock weather refresh failed\", error);\n this.weatherFetchedAt = Date.now();\n this.weatherRequestKey = requestKey;\n } finally {\n if (this.inFlightWeatherRequest === controller) {\n this.inFlightWeatherRequest = null;\n }\n this.render();\n }\n }\n\n private buildWeatherRequestKey(): string {\n return JSON.stringify({\n endpoint: this.weatherEndpointState,\n locations: this.locationsState.map((location) => ({\n key: getClockLocationKey(location),\n weatherQuery: location.weatherQuery || location.label,\n })),\n });\n }\n\n private createConfigDraft(): ConfigDrawerDraft {\n return {\n locations: this.locationsState.map((location) => ({\n label: location.label,\n timeZone: location.timeZone,\n weatherQuery: location.weatherQuery || location.label,\n })),\n weatherEnabled: this.weatherEnabledState,\n weatherEndpoint: this.weatherEndpointState,\n visualPreset: this.visualPresetState,\n };\n }\n\n private syncConfigDraftFromState(): void {\n this.configDraftState = this.createConfigDraft();\n }\n\n private handleRootClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) {\n return;\n }\n\n const actionElement = target.closest<HTMLElement>(\"[data-action]\");\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.dataset.action || \"\";\n\n if (action === \"toggle-config\") {\n this.configDrawerOpen = !this.configDrawerOpen;\n this.syncConfigDraftFromState();\n this.resetTransientConfigUi();\n this.render();\n return;\n }\n\n if (action === \"toggle-advanced\") {\n this.advancedSettingsOpen = !this.advancedSettingsOpen;\n this.render();\n return;\n }\n\n if (action === \"copy-share-link\") {\n void this.copyShareLink();\n return;\n }\n\n if (action === \"copy-config-json\") {\n void this.copyConfigJson();\n return;\n }\n\n if (action === \"toggle-import-export\") {\n this.importExportOpen = !this.importExportOpen;\n this.importExportDraft = this.importExportOpen ? JSON.stringify(this.config, null, 2) : \"\";\n this.render();\n return;\n }\n\n if (action === \"import-config-json\") {\n this.importConfigJson();\n return;\n }\n\n if (action === \"save-preset\") {\n this.saveCurrentPreset();\n return;\n }\n\n if (action === \"load-preset\") {\n const presetName = String(actionElement.dataset.presetName || \"\");\n this.loadSavedPreset(presetName);\n return;\n }\n\n if (action === \"delete-preset\") {\n const presetName = String(actionElement.dataset.presetName || \"\");\n this.deleteSavedPreset(presetName);\n return;\n }\n\n if (action === \"toggle-add-location\") {\n this.addLocationOpen = !this.addLocationOpen;\n if (!this.addLocationOpen) {\n this.resetAddLocationUi();\n }\n this.render();\n return;\n }\n\n if (action === \"select-common-city\") {\n const key = String(actionElement.dataset.cityKey || \"\");\n const city = commonClockCities.find((entry) => getCommonClockCityKey(entry) === key);\n if (!city) {\n return;\n }\n this.selectedCommonCityKey = key;\n this.addLocationPreferredName = city.label;\n this.render();\n return;\n }\n\n if (action === \"confirm-add-location\") {\n const city = this.getSelectedCommonCity();\n if (!city) {\n return;\n }\n this.configDraftState.locations.push({\n label: (this.addLocationPreferredName || city.label).trim(),\n timeZone: city.timeZone,\n weatherQuery: city.weatherQuery,\n });\n this.applyConfigDraft(true);\n this.resetAddLocationUi();\n this.render();\n return;\n }\n\n if (action === \"cancel-add-location\") {\n this.resetAddLocationUi();\n this.addLocationOpen = false;\n this.render();\n return;\n }\n\n if (action === \"request-remove-location\") {\n const index = Number.parseInt(actionElement.dataset.index || \"-1\", 10);\n if (Number.isInteger(index) && index >= 0) {\n this.pendingDeleteIndex = index;\n this.selectedLocationIndex = null;\n this.render();\n }\n return;\n }\n\n if (action === \"cancel-remove-location\") {\n this.pendingDeleteIndex = null;\n this.render();\n return;\n }\n\n if (action === \"confirm-remove-location\") {\n const index = Number.parseInt(actionElement.dataset.index || \"-1\", 10);\n if (Number.isInteger(index) && index >= 0) {\n this.configDraftState.locations.splice(index, 1);\n this.pendingDeleteIndex = null;\n this.selectedLocationIndex = null;\n this.applyConfigDraft(true);\n this.render();\n }\n return;\n }\n\n if (action === \"select-location\") {\n const index = Number.parseInt(actionElement.dataset.index || \"-1\", 10);\n if (Number.isInteger(index) && index >= 0) {\n this.pendingDeleteIndex = null;\n this.selectedLocationIndex = this.selectedLocationIndex === index ? null : index;\n this.render();\n }\n return;\n }\n\n if (action === \"add-custom-location\") {\n const next = {\n label: this.customLocationDraft.label.trim(),\n timeZone: this.customLocationDraft.timeZone.trim(),\n weatherQuery: this.customLocationDraft.weatherQuery.trim(),\n };\n if (!next.label || !next.timeZone || !next.weatherQuery) {\n return;\n }\n this.configDraftState.locations.push(next);\n this.customLocationDraft = { label: \"\", timeZone: \"\", weatherQuery: \"\" };\n this.applyConfigDraft(true);\n this.render();\n return;\n }\n }\n\n private handleRootInput(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) {\n return;\n }\n\n const setting = target.dataset.setting || \"\";\n if (setting === \"addLocationQuery\") {\n this.addLocationQuery = target.value;\n this.selectedCommonCityKey = \"\";\n this.addLocationPreferredName = \"\";\n this.render();\n return;\n }\n\n if (setting === \"addLocationPreferredName\") {\n this.addLocationPreferredName = target.value;\n return;\n }\n\n if (setting === \"customLabel\") {\n this.customLocationDraft.label = target.value;\n return;\n }\n\n if (setting === \"customTimeZone\") {\n this.customLocationDraft.timeZone = target.value;\n return;\n }\n\n if (setting === \"customWeatherQuery\") {\n this.customLocationDraft.weatherQuery = target.value;\n return;\n }\n\n if (setting === \"presetName\") {\n this.presetNameDraft = target.value;\n return;\n }\n\n if (setting === \"importExportDraft\") {\n this.importExportDraft = target.value;\n return;\n }\n\n const field = target.dataset.field || \"\";\n const index = Number.parseInt(target.dataset.index || \"-1\", 10);\n if (!Number.isInteger(index) || index < 0 || index >= this.configDraftState.locations.length) {\n return;\n }\n\n const location = this.configDraftState.locations[index];\n if (field === \"label\") {\n location.label = target.value;\n return;\n }\n if (field === \"timeZone\") {\n location.timeZone = target.value;\n return;\n }\n if (field === \"weatherQuery\") {\n location.weatherQuery = target.value;\n }\n }\n\n private handleRootChange(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement || target instanceof HTMLSelectElement)) {\n return;\n }\n\n const setting = target.dataset.setting || \"\";\n if (setting === \"weatherEnabled\" && target instanceof HTMLInputElement) {\n this.configDraftState.weatherEnabled = target.checked;\n this.applyConfigDraft(true);\n return;\n }\n\n if (setting === \"weatherEndpoint\" && target instanceof HTMLInputElement) {\n this.configDraftState.weatherEndpoint = target.value;\n return;\n }\n\n if (setting === \"visualPreset\" && target instanceof HTMLSelectElement) {\n this.configDraftState.visualPreset = normalizeVisualPreset(target.value);\n this.applyConfigDraft(true);\n return;\n }\n\n }\n\n private handleRootFocusOut(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement || target instanceof HTMLSelectElement || target instanceof HTMLTextAreaElement)) {\n return;\n }\n\n if (!target.closest(\".clock-config-drawer\")) {\n return;\n }\n\n window.setTimeout(() => {\n if (!this.configDrawerOpen) {\n return;\n }\n this.applyConfigDraft(true);\n }, 0);\n }\n\n private applyConfigDraft(keepDrawerOpen = false): void {\n const nextLocations = normalizeClockLocations(\n this.configDraftState.locations.map((location) => ({\n label: location.label.trim(),\n timeZone: location.timeZone.trim(),\n weatherQuery: (location.weatherQuery || location.label).trim(),\n }))\n );\n\n this.locationsState = nextLocations.length ? nextLocations : normalizeClockLocations(defaultClockLocations);\n this.weatherEnabledState = this.configDraftState.weatherEnabled;\n this.weatherEndpointState = this.configDraftState.weatherEndpoint.trim();\n this.visualPresetState = this.configDraftState.visualPreset;\n this.configDrawerOpen = keepDrawerOpen ? this.configDrawerOpen : false;\n this.syncConfigDraftFromState();\n this.handleConfigurationChange(true, \"drawer\");\n }\n\n private render(): void {\n const focusSnapshot = this.captureRenderFocus();\n\n if (!this.locationsState.length) {\n this.root.innerHTML = `<style>${styles}</style>`;\n this.restoreRenderFocus(focusSnapshot);\n return;\n }\n\n const now = new Date();\n const descriptors = this.locationsState.map((location, index) => {\n const timeParts = getClockTimeParts(location.timeZone, now);\n\n return {\n label: location.label,\n timeZone: location.timeZone,\n weatherQuery: location.weatherQuery || location.label,\n timeParts,\n weather: resolveWeatherForLocation(location, this.weatherByKey, this.weatherOverridesState),\n positionPercent: getClockSlotPercent(index, this.locationsState.length),\n };\n });\n\n const markers = assignClockMarkerOffsets(descriptors);\n const laneCount = markers.reduce((max, marker) => Math.max(max, marker.lane + 1), 1);\n\n this.root.innerHTML = `\n <style>${styles}</style>\n <section class=\"clock-strip clock-strip--preset-${this.visualPresetState} ${this.configDrawerOpen && !this.readOnlyState ? \"clock-strip--config-open\" : \"\"}\" part=\"base\">\n <section\n class=\"clock-strip__band\"\n part=\"band\"\n style=\"--clock-lane-count:${laneCount};--clock-strip-background:${buildClockStripBackground(markers)};\"\n aria-label=\"World clock strip\"\n >\n <div class=\"clock-strip__markers\" part=\"markers\">\n ${markers.map((descriptor) => this.renderClockMarker(descriptor)).join(\"\")}\n </div>\n </section>\n ${this.readOnlyState ? \"\" : `\n <div class=\"clock-strip__hover-zone\" part=\"config-hover-zone\" aria-hidden=\"true\">\n <button\n class=\"clock-strip__config-trigger\"\n type=\"button\"\n part=\"config-trigger\"\n data-action=\"toggle-config\"\n aria-label=\"${this.configDrawerOpen ? \"Close world time settings\" : \"Open world time settings\"}\"\n aria-expanded=\"${this.configDrawerOpen ? \"true\" : \"false\"}\"\n >\n ${this.configDrawerOpen ? \"Close\" : \"World Time Settings\"}\n </button>\n </div>\n ${this.renderConfigDrawer()}\n `}\n </section>\n `;\n this.restoreRenderFocus(focusSnapshot);\n }\n\n private renderConfigDrawer(): string {\n const draft = this.configDrawerOpen ? this.configDraftState : this.createConfigDraft();\n const commonCityResults = this.getFilteredCommonCities();\n const selectedCommonCity = this.getSelectedCommonCity();\n const savedPresets = this.getSavedPresets();\n\n return `\n <section\n class=\"clock-config-drawer ${this.configDrawerOpen ? \"clock-config-drawer--open\" : \"\"}\"\n part=\"config-drawer\"\n aria-hidden=\"${this.configDrawerOpen ? \"false\" : \"true\"}\"\n >\n <div class=\"clock-config-drawer__form\">\n <div class=\"clock-config-drawer__section-head\">\n <div class=\"clock-config-drawer__section-copy\">Add from the common city list. Use <code>Advanced</code> for custom entries.</div>\n <div class=\"clock-config-drawer__head-actions\">\n <button type=\"button\" class=\"clock-config-drawer__ghost\" data-action=\"copy-share-link\">Share</button>\n <button type=\"button\" class=\"clock-config-drawer__ghost\" data-action=\"toggle-import-export\" aria-expanded=\"${this.importExportOpen ? \"true\" : \"false\"}\">JSON</button>\n <button type=\"button\" class=\"clock-config-drawer__ghost\" data-action=\"toggle-advanced\" aria-expanded=\"${this.advancedSettingsOpen ? \"true\" : \"false\"}\">Advanced</button>\n <button type=\"button\" class=\"clock-config-drawer__ghost\" data-action=\"toggle-add-location\" aria-expanded=\"${this.addLocationOpen ? \"true\" : \"false\"}\">+</button>\n </div>\n </div>\n ${this.statusMessage ? `<div class=\"clock-config-status\">${escapeHtml(this.statusMessage)}</div>` : \"\"}\n ${this.renderAddLocationPanel(commonCityResults, selectedCommonCity)}\n ${this.renderPresetPanel(savedPresets)}\n ${this.renderImportExportPanel()}\n <div class=\"clock-config-drawer__list\">\n <div class=\"clock-config-drawer__list-title\">Current locations</div>\n <ul class=\"clock-config-location-list\">\n ${draft.locations.map((location, index) => this.renderConfigLocationListItem(location, index)).join(\"\")}\n </ul>\n </div>\n ${this.renderAdvancedSettings(draft)}\n <datalist id=\"${WORLD_CLOCK_TIME_ZONE_DATALIST_ID}\">\n ${getSupportedClockTimeZones().map((timeZone) => `<option value=\"${escapeHtml(timeZone)}\"></option>`).join(\"\")}\n </datalist>\n </div>\n </section>\n `;\n }\n\n private renderPresetPanel(savedPresets: Array<{ name: string; config: WorldClockConfig }>): string {\n return `\n <section class=\"clock-config-drawer__list\">\n <div class=\"clock-config-drawer__list-title\">Saved presets</div>\n <div class=\"clock-config-preset-save\">\n <input\n type=\"text\"\n value=\"${escapeHtml(this.presetNameDraft)}\"\n data-setting=\"presetName\"\n placeholder=\"Preset name\"\n />\n <button type=\"button\" class=\"clock-config-drawer__ghost\" data-action=\"save-preset\">Save current</button>\n </div>\n <div class=\"clock-config-presets\">\n ${savedPresets.length\n ? savedPresets.map((preset) => `\n <div class=\"clock-config-preset\">\n <button type=\"button\" class=\"clock-config-search-result\" data-action=\"load-preset\" data-preset-name=\"${escapeHtml(preset.name)}\">${escapeHtml(preset.name)}</button>\n <button type=\"button\" class=\"clock-config-location__remove\" data-action=\"delete-preset\" data-preset-name=\"${escapeHtml(preset.name)}\">Delete</button>\n </div>\n `).join(\"\")\n : `<div class=\"clock-config-search-empty\">No saved presets yet.</div>`}\n </div>\n </section>\n `;\n }\n\n private renderImportExportPanel(): string {\n if (!this.importExportOpen) {\n return \"\";\n }\n\n return `\n <section class=\"clock-config-drawer__list\">\n <div class=\"clock-config-drawer__list-title\">Import / export JSON</div>\n <label class=\"clock-config-field\">\n <textarea\n class=\"clock-config-textarea\"\n data-setting=\"importExportDraft\"\n placeholder=\"Paste config JSON\"\n >${escapeHtml(this.importExportDraft)}</textarea>\n </label>\n <div class=\"clock-config-add-confirm__actions\">\n <button type=\"button\" class=\"clock-config-drawer__ghost\" data-action=\"copy-config-json\">Copy current</button>\n <button type=\"button\" class=\"clock-config-drawer__primary\" data-action=\"import-config-json\">Import</button>\n </div>\n </section>\n `;\n }\n\n private renderAddLocationPanel(results: CommonClockCity[], selectedCity: CommonClockCity | null): string {\n if (!this.addLocationOpen) {\n return \"\";\n }\n\n return `\n <section class=\"clock-config-add-panel\">\n <label class=\"clock-config-field\">\n <span class=\"clock-config-field__label\">Search city</span>\n <input\n type=\"search\"\n value=\"${escapeHtml(this.addLocationQuery)}\"\n data-setting=\"addLocationQuery\"\n placeholder=\"Start typing a city\"\n spellcheck=\"false\"\n autocapitalize=\"words\"\n autocomplete=\"off\"\n />\n </label>\n <div class=\"clock-config-search-results\">\n ${results.length\n ? results.map((city) => `\n <button\n type=\"button\"\n class=\"clock-config-search-result ${this.selectedCommonCityKey === getCommonClockCityKey(city) ? \"clock-config-search-result--selected\" : \"\"}\"\n data-action=\"select-common-city\"\n data-city-key=\"${escapeHtml(getCommonClockCityKey(city))}\"\n >\n <span>${escapeHtml(city.label)}</span>\n <span>${escapeHtml(city.country)} · ${escapeHtml(city.timeZone)}</span>\n </button>\n `).join(\"\")\n : `<div class=\"clock-config-search-empty\">No common city match. Use <strong>Advanced</strong> to add a custom city.</div>`}\n </div>\n ${selectedCity ? `\n <div class=\"clock-config-add-confirm\">\n <div class=\"clock-config-add-confirm__city\">\n Weather will use ${escapeHtml(selectedCity.weatherQuery)}.\n </div>\n <label class=\"clock-config-field\">\n <span class=\"clock-config-field__label\">Preferred name</span>\n <input\n type=\"text\"\n value=\"${escapeHtml(this.addLocationPreferredName)}\"\n data-setting=\"addLocationPreferredName\"\n placeholder=\"${escapeHtml(selectedCity.label)}\"\n />\n </label>\n <div class=\"clock-config-add-confirm__actions\">\n <button type=\"button\" class=\"clock-config-drawer__ghost\" data-action=\"cancel-add-location\">Cancel</button>\n <button type=\"button\" class=\"clock-config-drawer__primary\" data-action=\"confirm-add-location\">Add city</button>\n </div>\n </div>\n ` : \"\"}\n </section>\n `;\n }\n\n private renderAdvancedSettings(draft: ConfigDrawerDraft): string {\n return `\n <section class=\"clock-config-advanced ${this.advancedSettingsOpen ? \"clock-config-advanced--open\" : \"\"}\">\n <div class=\"clock-config-advanced__grid\">\n <label class=\"clock-config-field clock-config-field--toggle\">\n <span class=\"clock-config-field__label\">Weather</span>\n <span class=\"clock-config-field__toggle-row\">\n <input\n type=\"checkbox\"\n data-setting=\"weatherEnabled\"\n ${draft.weatherEnabled ? \"checked\" : \"\"}\n />\n <span>${draft.weatherEnabled ? \"Enabled\" : \"Disabled\"}</span>\n </span>\n </label>\n <label class=\"clock-config-field clock-config-field--wide\">\n <span class=\"clock-config-field__label\">Weather endpoint</span>\n <input\n type=\"text\"\n value=\"${escapeHtml(draft.weatherEndpoint)}\"\n placeholder=\"/api/weather/clocks\"\n data-setting=\"weatherEndpoint\"\n />\n </label>\n <label class=\"clock-config-field clock-config-field--wide\">\n <span class=\"clock-config-field__label\">Visual preset</span>\n <select data-setting=\"visualPreset\">\n ${[\"default\", \"minimal\", \"cinematic\", \"wallboard\"]\n .map((preset) => `<option value=\"${preset}\" ${draft.visualPreset === preset ? \"selected\" : \"\"}>${preset}</option>`)\n .join(\"\")}\n </select>\n </label>\n </div>\n <div class=\"clock-config-advanced__custom\">\n <div class=\"clock-config-drawer__list-title\">Custom city</div>\n <div class=\"clock-config-location\">\n <label class=\"clock-config-field\">\n <span class=\"clock-config-field__label\">Preferred name</span>\n <input type=\"text\" value=\"${escapeHtml(this.customLocationDraft.label)}\" data-setting=\"customLabel\" placeholder=\"Reykjavik\" />\n </label>\n <label class=\"clock-config-field\">\n <span class=\"clock-config-field__label\">Weather city</span>\n <input type=\"text\" value=\"${escapeHtml(this.customLocationDraft.weatherQuery)}\" data-setting=\"customWeatherQuery\" placeholder=\"Reykjavik, Iceland\" />\n </label>\n <label class=\"clock-config-field clock-config-field--time-zone\">\n <span class=\"clock-config-field__label\">Time zone</span>\n <input\n type=\"search\"\n list=\"${WORLD_CLOCK_TIME_ZONE_DATALIST_ID}\"\n value=\"${escapeHtml(this.customLocationDraft.timeZone)}\"\n data-setting=\"customTimeZone\"\n placeholder=\"Search IANA time zone\"\n spellcheck=\"false\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n />\n </label>\n <button type=\"button\" class=\"clock-config-location__remove\" data-action=\"add-custom-location\">Add</button>\n </div>\n </div>\n </section>\n `;\n }\n\n private renderConfigLocationListItem(location: ConfigDraftLocation, index: number): string {\n if (this.pendingDeleteIndex === index) {\n return `\n <li class=\"clock-config-location-list__item clock-config-location-list__item--confirm\">\n <span class=\"clock-config-location-list__bullet\">-</span>\n <div class=\"clock-config-location-list__body\">\n <div class=\"clock-config-location-list__confirm\">Remove ${escapeHtml(location.label)}?</div>\n <div class=\"clock-config-location-list__actions\">\n <button type=\"button\" class=\"clock-config-drawer__ghost\" data-action=\"cancel-remove-location\">No</button>\n <button type=\"button\" class=\"clock-config-location__remove\" data-action=\"confirm-remove-location\" data-index=\"${index}\">Remove</button>\n </div>\n </div>\n </li>\n `;\n }\n\n if (this.selectedLocationIndex === index) {\n return `\n <li class=\"clock-config-location-list__item clock-config-location-list__item--selected\" part=\"config-location\">\n <span class=\"clock-config-location-list__bullet\">-</span>\n <div class=\"clock-config-location-list__body clock-config-location-list__body--edit\">\n <label class=\"clock-config-field\">\n <span class=\"clock-config-field__label\">Screen name</span>\n <input\n type=\"text\"\n value=\"${escapeHtml(location.label)}\"\n data-index=\"${index}\"\n data-field=\"label\"\n placeholder=\"Macau\"\n />\n </label>\n <label class=\"clock-config-field\">\n <span class=\"clock-config-field__label\">Weather city</span>\n <input\n type=\"text\"\n value=\"${escapeHtml(location.weatherQuery)}\"\n data-index=\"${index}\"\n data-field=\"weatherQuery\"\n placeholder=\"Macau\"\n />\n </label>\n <div class=\"clock-config-location-list__meta\">${escapeHtml(location.timeZone)}</div>\n </div>\n <button type=\"button\" class=\"clock-config-location__remove\" data-action=\"request-remove-location\" data-index=\"${index}\">Remove</button>\n </li>\n `;\n }\n\n return `\n <li class=\"clock-config-location-list__item\" part=\"config-location\">\n <span class=\"clock-config-location-list__bullet\">-</span>\n <button type=\"button\" class=\"clock-config-location-list__body clock-config-location-list__body--button\" data-action=\"select-location\" data-index=\"${index}\">\n <div class=\"clock-config-location-list__title\">${escapeHtml(location.label)}</div>\n <div class=\"clock-config-location-list__meta\">${escapeHtml(location.timeZone)}</div>\n </button>\n <button type=\"button\" class=\"clock-config-location__remove\" data-action=\"request-remove-location\" data-index=\"${index}\">Remove</button>\n </li>\n `;\n }\n\n private getFilteredCommonCities(): CommonClockCity[] {\n const existingKeys = new Set(\n this.configDraftState.locations.map((location) => getClockLocationKey(location))\n );\n const query = this.addLocationQuery.trim().toLowerCase();\n return commonClockCities\n .filter((city) => !existingKeys.has(getClockLocationKey(city)))\n .filter((city) => {\n if (!query) {\n return true;\n }\n const haystack = `${city.label} ${city.country} ${city.timeZone} ${city.weatherQuery}`.toLowerCase();\n return haystack.includes(query);\n })\n .slice(0, 8);\n }\n\n private getSelectedCommonCity(): CommonClockCity | null {\n return commonClockCities.find((city) => getCommonClockCityKey(city) === this.selectedCommonCityKey) ?? null;\n }\n\n private resetAddLocationUi(): void {\n this.addLocationQuery = \"\";\n this.addLocationPreferredName = \"\";\n this.selectedCommonCityKey = \"\";\n }\n\n private resetTransientConfigUi(): void {\n this.pendingDeleteIndex = null;\n this.selectedLocationIndex = null;\n this.advancedSettingsOpen = false;\n this.addLocationOpen = false;\n this.resetAddLocationUi();\n this.customLocationDraft = { label: \"\", timeZone: \"\", weatherQuery: \"\" };\n }\n\n private async copyShareLink(): Promise<void> {\n const url = buildWorldClockShareUrl(this.config, this.shareQueryParamState);\n await copyTextToClipboard(url);\n this.setStatusMessage(\"Share link copied\");\n }\n\n private async copyConfigJson(): Promise<void> {\n const text = JSON.stringify(this.config, null, 2);\n await copyTextToClipboard(text);\n this.importExportDraft = text;\n this.setStatusMessage(\"Config JSON copied\");\n this.render();\n }\n\n private importConfigJson(): void {\n try {\n const parsed = JSON.parse(this.importExportDraft) as Partial<WorldClockConfig>;\n const normalized = normalizeWorldClockConfig(parsed);\n this.applyConfigValue(normalized, \"api\");\n this.setStatusMessage(\"Config imported\");\n this.render();\n } catch (error) {\n this.setStatusMessage(error instanceof Error ? error.message : \"Invalid config JSON\");\n this.render();\n }\n }\n\n private getSavedPresets(): Array<{ name: string; config: WorldClockConfig }> {\n try {\n const raw = window.localStorage.getItem(DEFAULT_WORLD_CLOCK_PRESET_STORAGE_KEY);\n if (!raw) {\n return [];\n }\n const parsed = JSON.parse(raw) as Array<{ name: string; config: WorldClockConfig }>;\n return Array.isArray(parsed)\n ? parsed\n .filter((entry) => entry && typeof entry.name === \"string\" && entry.config)\n .map((entry) => ({ name: entry.name, config: normalizeWorldClockConfig(entry.config) }))\n : [];\n } catch {\n return [];\n }\n }\n\n private writeSavedPresets(value: Array<{ name: string; config: WorldClockConfig }>): void {\n window.localStorage.setItem(DEFAULT_WORLD_CLOCK_PRESET_STORAGE_KEY, JSON.stringify(value));\n }\n\n private saveCurrentPreset(): void {\n const name = this.presetNameDraft.trim();\n if (!name) {\n this.setStatusMessage(\"Enter a preset name\");\n this.render();\n return;\n }\n const presets = this.getSavedPresets().filter((entry) => entry.name !== name);\n presets.unshift({ name, config: this.config });\n this.writeSavedPresets(presets);\n this.presetNameDraft = \"\";\n this.setStatusMessage(\"Preset saved\");\n this.render();\n }\n\n private loadSavedPreset(name: string): void {\n const preset = this.getSavedPresets().find((entry) => entry.name === name);\n if (!preset) {\n return;\n }\n this.applyConfigValue(preset.config, \"preset\");\n this.setStatusMessage(`Loaded preset: ${name}`);\n this.render();\n }\n\n private deleteSavedPreset(name: string): void {\n const presets = this.getSavedPresets().filter((entry) => entry.name !== name);\n this.writeSavedPresets(presets);\n this.setStatusMessage(`Deleted preset: ${name}`);\n this.render();\n }\n\n private setStatusMessage(message: string): void {\n this.statusMessage = message;\n window.setTimeout(() => {\n if (this.statusMessage === message) {\n this.statusMessage = \"\";\n this.render();\n }\n }, 2200);\n }\n\n private captureRenderFocus(): RenderFocusSnapshot | null {\n const active = this.root.activeElement;\n if (!(active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement)) {\n return null;\n }\n\n const setting = active.dataset.setting;\n if (setting) {\n return {\n selector: `[data-setting=\"${setting}\"]`,\n start: active.selectionStart,\n end: active.selectionEnd,\n };\n }\n\n const field = active.dataset.field;\n const index = active.dataset.index;\n if (field && index != null) {\n return {\n selector: `[data-field=\"${field}\"][data-index=\"${index}\"]`,\n start: active.selectionStart,\n end: active.selectionEnd,\n };\n }\n\n return null;\n }\n\n private restoreRenderFocus(snapshot: RenderFocusSnapshot | null): void {\n if (!snapshot) {\n return;\n }\n\n const next = this.root.querySelector<HTMLInputElement | HTMLTextAreaElement>(snapshot.selector);\n if (!next) {\n return;\n }\n\n next.focus();\n if (snapshot.start != null && snapshot.end != null) {\n try {\n next.setSelectionRange(snapshot.start, snapshot.end);\n } catch {\n return;\n }\n }\n }\n\n private renderClockMarker(descriptor: ClockDescriptor): string {\n const labelText = descriptor.label;\n const timeLabel = descriptor.timeParts.timeText;\n const metaLabel = descriptor.timeParts.dayText;\n const temperatureText = formatClockTemperature(\n descriptor.weather,\n getSystemTimeZone()\n );\n const edgeClass = getClockMarkerEdgeClass(descriptor.positionPercent);\n const leftStyle =\n edgeClass === \"clock-marker--edge-left\"\n ? `left:${descriptor.edgeInsetPx != null ? descriptor.edgeInsetPx : Math.max(10, descriptor.labelOffsetPx || 0)}px;`\n : edgeClass === \"clock-marker--edge-right\"\n ? `right:${descriptor.edgeInsetPx != null ? descriptor.edgeInsetPx : Math.max(10, -(descriptor.labelOffsetPx || 0))}px;left:auto;`\n : `left:calc(${descriptor.positionPercent}% ${formatClockOffsetPx(descriptor.labelOffsetPx || 0)});`;\n\n const titleText = [labelText, timeLabel, metaLabel, temperatureText].filter(Boolean).join(\" · \");\n\n return `\n <article\n class=\"clock-marker ${edgeClass}\"\n part=\"marker\"\n title=\"${escapeHtml(titleText)}\"\n style=\"${leftStyle}--clock-lane:${descriptor.lane};\"\n >\n ${this.renderClockWeatherBackdrop(descriptor)}\n <div class=\"clock-marker__text\" part=\"label\">${escapeHtml(labelText)}</div>\n <div class=\"clock-marker__text clock-marker__text--time\" part=\"time\">${escapeHtml(timeLabel)}</div>\n <div class=\"clock-marker__meta\" part=\"meta\">${escapeHtml(metaLabel)}</div>\n ${temperatureText ? `<div class=\"clock-marker__temp\" part=\"temperature\">${escapeHtml(temperatureText)}</div>` : \"\"}\n </article>\n `;\n }\n\n private renderClockWeatherBackdrop(descriptor: ClockDescriptor): string {\n if (!this.weatherEnabledState) {\n return \"\";\n }\n\n const weather = descriptor.weather;\n const condition = weather && weather.state === \"pass\"\n ? String(weather.condition || \"cloudy\")\n : getFallbackWeatherCondition(descriptor.timeParts.hour24);\n const image = resolveWeatherImage(condition, weather, descriptor.timeParts.hour24);\n\n return `\n <div\n class=\"clock-weather clock-weather--image clock-weather--${escapeHtml(condition)}\"\n aria-hidden=\"true\"\n style=\"--clock-weather-image:url('${image}')\"\n ></div>\n `;\n }\n}\n\nexport function defineWorldClockStrip(tagName = WORLD_CLOCK_TAG_NAME): typeof WorldClockStripElement {\n const existing = customElements.get(tagName);\n if (existing) {\n return existing as typeof WorldClockStripElement;\n }\n\n customElements.define(tagName, WorldClockStripElement);\n return WorldClockStripElement;\n}\n\nexport function createWorldClockStrip(options: WorldClockStripOptions = {}): WorldClockStripElement {\n defineWorldClockStrip();\n const element = document.createElement(WORLD_CLOCK_TAG_NAME) as WorldClockStripElement;\n\n if (options.locations) {\n element.locations = options.locations;\n }\n\n if (options.weatherEnabled != null) {\n element.weatherEnabled = options.weatherEnabled;\n }\n\n if (options.weatherEndpoint) {\n element.weatherEndpoint = options.weatherEndpoint;\n }\n\n if (options.visualPreset) {\n element.visualPreset = options.visualPreset;\n }\n\n if (options.readOnly != null) {\n element.readOnly = options.readOnly;\n }\n\n if (options.persistKey) {\n element.persistKey = options.persistKey;\n }\n\n if (options.enableUrlState != null) {\n element.setAttribute(\"enable-url-state\", String(options.enableUrlState));\n }\n\n if (options.shareQueryParam) {\n element.shareQueryParam = options.shareQueryParam;\n }\n\n if (options.cityCatalog) {\n element.cityCatalog = options.cityCatalog;\n }\n\n if (options.weatherOverrides) {\n element.weatherOverrides = options.weatherOverrides;\n }\n\n return element;\n}\n\nexport function normalizeClockLocations(locations?: ClockLocation[]): ClockLocation[] {\n const normalized = (Array.isArray(locations) ? locations : defaultClockLocations)\n .map((location) => ({\n label: String(location?.label || \"\").trim(),\n timeZone: String(location?.timeZone || \"\").trim(),\n weatherQuery: String(location?.weatherQuery || location?.label || \"\").trim(),\n }))\n .filter((location) => location.label && location.timeZone);\n\n const deduped: ClockLocation[] = [];\n let sharedAsiaAdded = false;\n\n for (const location of normalized) {\n if (isGoldCoastClockLocation(location)) {\n continue;\n }\n\n if (isMacauManilaClockLocation(location)) {\n if (!sharedAsiaAdded) {\n deduped.push({ label: \"Macau\", timeZone: \"Asia/Macau\", weatherQuery: \"Macau\" });\n sharedAsiaAdded = true;\n }\n continue;\n }\n\n const alreadyPresent = deduped.some(\n (entry) =>\n entry.label.toLowerCase() === location.label.toLowerCase() &&\n entry.timeZone.toLowerCase() === location.timeZone.toLowerCase()\n );\n\n if (!alreadyPresent) {\n deduped.push(location);\n }\n }\n\n return deduped.sort(compareClockLocations);\n}\n\nfunction normalizeWorldClockConfig(value: Partial<WorldClockConfig>): WorldClockConfig {\n return {\n locations: normalizeClockLocations(value.locations),\n weatherEnabled: value.weatherEnabled !== false,\n weatherEndpoint: String(value.weatherEndpoint || \"\").trim(),\n visualPreset: normalizeVisualPreset(value.visualPreset),\n };\n}\n\nfunction normalizeVisualPreset(value: string | null | undefined): VisualPreset {\n return value === \"minimal\" || value === \"cinematic\" || value === \"wallboard\" ? value : \"default\";\n}\n\nfunction normalizeCommonClockCities(value?: CommonClockCity[]): CommonClockCity[] {\n const items = Array.isArray(value) ? value : commonClockCities;\n return items\n .map((city) => ({\n label: String(city?.label || \"\").trim(),\n timeZone: String(city?.timeZone || \"\").trim(),\n weatherQuery: String(city?.weatherQuery || city?.label || \"\").trim(),\n country: String(city?.country || \"\").trim(),\n }))\n .filter((city) => city.label && city.timeZone && city.weatherQuery);\n}\n\nfunction parseLocationsAttribute(\n value: string | null,\n fallback: ClockLocation[]\n): ClockLocation[] {\n if (!value) {\n return normalizeClockLocations(fallback);\n }\n\n try {\n const parsed = JSON.parse(value);\n return normalizeClockLocations(parsed);\n } catch (error) {\n console.error(\"Invalid world clock locations attribute\", error);\n return normalizeClockLocations(fallback);\n }\n}\n\nfunction buildClockGradientFromStops(stops: Array<{ color: string; percent: number }>): string {\n return `linear-gradient(90deg, ${stops.map((stop) => `${stop.color} ${stop.percent}%`).join(\", \")})`;\n}\n\nfunction assignClockMarkerOffsets(\n descriptors: Array<\n Omit<ClockDescriptor, \"lane\" | \"labelOffsetPx\"> & { lane?: number; labelOffsetPx?: number }\n >\n): ClockDescriptor[] {\n return descriptors.map((descriptor) => ({\n ...descriptor,\n lane: 0,\n labelOffsetPx: 0,\n }));\n}\n\nfunction formatClockOffsetPx(value: number): string {\n const amount = Number(value || 0);\n return amount < 0 ? `- ${Math.abs(amount)}px` : `+ ${amount}px`;\n}\n\nfunction getClockMarkerEdgeClass(positionPercent: number): string {\n if (positionPercent <= 8) {\n return \"clock-marker--edge-left\";\n }\n\n if (positionPercent >= 92) {\n return \"clock-marker--edge-right\";\n }\n\n return \"\";\n}\n\nfunction getClockTimeParts(timeZone: string, now: Date): ClockDescriptor[\"timeParts\"] {\n try {\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n weekday: \"long\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n timeZoneName: \"short\",\n });\n const parts = formatter.formatToParts(now);\n const map = Object.fromEntries(parts.map((part) => [part.type, part.value]));\n const hour12 = Number(map.hour || \"0\");\n const dayPeriod = String(map.dayPeriod || \"\").toUpperCase();\n const hour24 =\n dayPeriod === \"PM\" && hour12 < 12 ? hour12 + 12 : dayPeriod === \"AM\" && hour12 === 12 ? 0 : hour12;\n\n return {\n hour24,\n minute24: Number(map.minute || \"0\"),\n timeText: `${map.hour || \"\"}:${map.minute || \"\"} ${map.dayPeriod || \"\"}`.trim(),\n dayText: buildClockDayText(timeZone, now, String(map.weekday || \"\")),\n zoneText: String(map.timeZoneName || timeZone),\n };\n } catch {\n return {\n hour24: now.getHours(),\n minute24: now.getMinutes(),\n timeText: now.toLocaleTimeString(\"en-US\", { hour: \"numeric\", minute: \"2-digit\" }),\n dayText: buildClockDayText(timeZone, now, now.toLocaleDateString(\"en-US\", { weekday: \"long\" })),\n zoneText: timeZone,\n };\n }\n}\n\nfunction buildClockDayText(timeZone: string, now: Date, weekdayText: string): string {\n const dayNumber = getDayOfMonthForTimeZone(timeZone, now);\n if (!dayNumber) {\n return weekdayText;\n }\n\n return `${weekdayText} ${dayNumber}${getOrdinalSuffix(dayNumber)}`;\n}\n\nfunction getDayOfMonthForTimeZone(timeZone: string, now: Date): number | null {\n try {\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n day: \"numeric\",\n });\n const parts = formatter.formatToParts(now);\n const dayPart = parts.find((part) => part.type === \"day\");\n const value = Number(dayPart?.value || \"\");\n return Number.isFinite(value) ? value : null;\n } catch {\n const value = now.getDate();\n return Number.isFinite(value) ? value : null;\n }\n}\n\nfunction getOrdinalSuffix(value: number): string {\n const mod100 = value % 100;\n if (mod100 >= 11 && mod100 <= 13) {\n return \"th\";\n }\n\n const mod10 = value % 10;\n if (mod10 === 1) {\n return \"st\";\n }\n if (mod10 === 2) {\n return \"nd\";\n }\n if (mod10 === 3) {\n return \"rd\";\n }\n\n return \"th\";\n}\n\nfunction formatClockTemperature(\n weather: ClockWeatherSnapshot | null,\n systemTimeZone: string\n): string {\n const celsius = weather?.state === \"pass\" ? Number(weather.temperature) : Number.NaN;\n if (!Number.isFinite(celsius)) {\n return \"\";\n }\n\n const unit = getSystemTemperatureUnit(systemTimeZone);\n const value = unit === \"F\" ? celsiusToFahrenheit(celsius) : celsius;\n return `${Math.round(value)}°${unit}`;\n}\n\nfunction getSystemTemperatureUnit(timeZone: string): \"C\" | \"F\" {\n return US_FAHRENHEIT_TIME_ZONES.has(timeZone) ? \"F\" : \"C\";\n}\n\nfunction getSystemTimeZone(): string {\n try {\n return String(Intl.DateTimeFormat().resolvedOptions().timeZone || \"\").trim();\n } catch {\n return \"\";\n }\n}\n\nfunction celsiusToFahrenheit(value: number): number {\n return (value * 9) / 5 + 32;\n}\n\nfunction resolveWeatherForLocation(\n location: ClockLocation,\n weatherByKey: Map<string, ClockWeatherSnapshot | null>,\n overrides: Record<string, ClockWeatherSnapshot>\n): ClockWeatherSnapshot | null {\n const key = getClockLocationKey(location);\n if (Object.prototype.hasOwnProperty.call(overrides, key)) {\n return overrides[key];\n }\n\n return weatherByKey.get(key) ?? null;\n}\n\nexport function getFallbackWeatherCondition(hour24: number): string {\n if (hour24 >= 6 && hour24 < 18) {\n return \"clear-day\";\n }\n\n return \"clear-night\";\n}\n\nfunction buildClockStripBackground(descriptors: ClockDescriptor[]): string {\n if (!descriptors.length) {\n return buildClockGradientFromStops(getClockGradientStops());\n }\n\n const baseAnchors = descriptors.map((descriptor) => ({\n x: descriptor.positionPercent,\n time: getClockTimePercent(descriptor.timeParts),\n }));\n const unwrappedAnchors = unwrapClockAnchors(baseAnchors);\n const extendedAnchors = [\n ...unwrappedAnchors.map((anchor) => ({ x: anchor.x - 100, time: anchor.time - 100 })),\n ...unwrappedAnchors,\n ...unwrappedAnchors.map((anchor) => ({ x: anchor.x + 100, time: anchor.time + 100 })),\n ].sort((left, right) => left.x - right.x);\n\n const sampleCount = 72;\n const stops = [];\n\n for (let index = 0; index <= sampleCount; index += 1) {\n const x = Number(((index / sampleCount) * 100).toFixed(2));\n const timePercent = interpolateClockTimeAtX(x, extendedAnchors);\n stops.push({\n color: sampleClockGradientColor(timePercent),\n percent: x,\n });\n }\n\n return buildClockGradientFromStops(stops);\n}\n\nfunction getClockSlotPercent(index: number, total: number): number {\n if (total <= 1) {\n return 50;\n }\n\n const gutterPercent = 12;\n const usablePercent = 100 - gutterPercent * 2;\n return Number((gutterPercent + (usablePercent * index) / (total - 1)).toFixed(2));\n}\n\nfunction getClockGradientStops(): Array<{ color: string; percent: number }> {\n return [\n { color: \"#08111b\", percent: 0 },\n { color: \"#0d1c30\", percent: 18 },\n { color: \"#1f3048\", percent: 20.83 },\n { color: \"#5f5163\", percent: 24 },\n { color: \"#d18b59\", percent: 29.17 },\n { color: \"#5e8bb9\", percent: 36 },\n { color: \"#8cc4e7\", percent: 45.83 },\n { color: \"#dceff8\", percent: 58 },\n { color: \"#7ab6df\", percent: 70.83 },\n { color: \"#5e7692\", percent: 74.5 },\n { color: \"#9c6149\", percent: 76.5 },\n { color: \"#d98d55\", percent: 77.8 },\n { color: \"#402e43\", percent: 79.17 },\n { color: \"#111d31\", percent: 81.25 },\n { color: \"#08111b\", percent: 86 },\n { color: \"#08111b\", percent: 100 },\n ];\n}\n\nfunction getClockTimePercent(timeParts: ClockDescriptor[\"timeParts\"]): number {\n const minutes = ((Number(timeParts.hour24 || 0) * 60) + Number(timeParts.minute24 || 0)) % 1440;\n return (minutes / 1440) * 100;\n}\n\nfunction unwrapClockAnchors(anchors: Array<{ x: number; time: number }>): Array<{ x: number; time: number }> {\n if (!anchors.length) {\n return [];\n }\n\n const unwrapped = [{ ...anchors[0] }];\n let previous = anchors[0].time;\n\n for (let index = 1; index < anchors.length; index += 1) {\n let current = anchors[index].time;\n while (current < previous) {\n current += 100;\n }\n unwrapped.push({\n x: anchors[index].x,\n time: current,\n });\n previous = current;\n }\n\n return unwrapped;\n}\n\nfunction interpolateClockTimeAtX(\n x: number,\n anchors: Array<{ x: number; time: number }>\n): number {\n if (!anchors.length) {\n return 0;\n }\n\n for (let index = 0; index < anchors.length - 1; index += 1) {\n const left = anchors[index];\n const right = anchors[index + 1];\n if (x < left.x || x > right.x) {\n continue;\n }\n\n const span = right.x - left.x;\n if (span <= 0) {\n return left.time;\n }\n\n const progress = (x - left.x) / span;\n return left.time + (right.time - left.time) * progress;\n }\n\n return anchors[anchors.length - 1].time;\n}\n\nfunction sampleClockGradientColor(timePercent: number): string {\n const normalized = ((timePercent % 100) + 100) % 100;\n const stops = getClockGradientStops();\n\n for (let index = 0; index < stops.length - 1; index += 1) {\n const left = stops[index];\n const right = stops[index + 1];\n if (normalized < left.percent || normalized > right.percent) {\n continue;\n }\n\n const span = right.percent - left.percent;\n if (span <= 0) {\n return left.color;\n }\n\n const progress = (normalized - left.percent) / span;\n return interpolateHexColor(left.color, right.color, progress);\n }\n\n return stops[stops.length - 1].color;\n}\n\nfunction interpolateHexColor(left: string, right: string, progress: number): string {\n const leftRgb = hexToRgb(left);\n const rightRgb = hexToRgb(right);\n\n return rgbToHex({\n r: Math.round(leftRgb.r + (rightRgb.r - leftRgb.r) * progress),\n g: Math.round(leftRgb.g + (rightRgb.g - leftRgb.g) * progress),\n b: Math.round(leftRgb.b + (rightRgb.b - leftRgb.b) * progress),\n });\n}\n\nfunction hexToRgb(value: string): { r: number; g: number; b: number } {\n const normalized = value.replace(\"#\", \"\");\n return {\n r: Number.parseInt(normalized.slice(0, 2), 16),\n g: Number.parseInt(normalized.slice(2, 4), 16),\n b: Number.parseInt(normalized.slice(4, 6), 16),\n };\n}\n\nfunction rgbToHex(value: { r: number; g: number; b: number }): string {\n return `#${[value.r, value.g, value.b]\n .map((channel) => channel.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n}\n\nfunction getSupportedClockTimeZones(): string[] {\n try {\n if (typeof Intl.supportedValuesOf === \"function\") {\n return Intl.supportedValuesOf(\"timeZone\");\n }\n } catch {\n return fallbackClockTimeZones;\n }\n\n return fallbackClockTimeZones;\n}\n\nfunction resolveWeatherAssetUrl(fileName: string): string {\n const relativePath = [\"..\", \"assets\", \"weather\", fileName].join(\"/\");\n return new URL(relativePath, import.meta.url).href;\n}\n\nfunction readWorldClockConfigFromUrl(queryParam: string): WorldClockConfig | null {\n try {\n const url = new URL(window.location.href);\n const encoded = url.searchParams.get(queryParam);\n if (!encoded) {\n return null;\n }\n return deserializeWorldClockConfig(encoded);\n } catch {\n return null;\n }\n}\n\nfunction buildWorldClockShareUrl(config: WorldClockConfig, queryParam: string): string {\n const url = new URL(window.location.href);\n url.searchParams.set(queryParam, serializeWorldClockConfig(config));\n return url.toString();\n}\n\nfunction readWorldClockConfigFromStorage(key: string): WorldClockConfig | null {\n try {\n const raw = window.localStorage.getItem(key);\n if (!raw) {\n return null;\n }\n return normalizeWorldClockConfig(JSON.parse(raw) as Partial<WorldClockConfig>);\n } catch {\n return null;\n }\n}\n\nfunction writeWorldClockConfigToStorage(key: string, config: WorldClockConfig): void {\n window.localStorage.setItem(key, JSON.stringify(config));\n}\n\nexport function serializeWorldClockConfig(config: Partial<WorldClockConfig>): string {\n return encodeBase64Url(JSON.stringify(normalizeWorldClockConfig(config)));\n}\n\nexport function deserializeWorldClockConfig(value: string): WorldClockConfig {\n const json = decodeBase64Url(value);\n return normalizeWorldClockConfig(JSON.parse(json) as Partial<WorldClockConfig>);\n}\n\nfunction encodeBase64Url(value: string): string {\n const encoded = btoa(unescape(encodeURIComponent(value)));\n return encoded.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nfunction decodeBase64Url(value: string): string {\n const padded = value.replace(/-/g, \"+\").replace(/_/g, \"/\").padEnd(Math.ceil(value.length / 4) * 4, \"=\");\n return decodeURIComponent(escape(atob(padded)));\n}\n\nasync function copyTextToClipboard(value: string): Promise<void> {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(value);\n return;\n }\n\n const input = document.createElement(\"textarea\");\n input.value = value;\n document.body.append(input);\n input.select();\n document.execCommand(\"copy\");\n input.remove();\n}\n\nfunction resolveWeatherImage(\n condition: string,\n weather: ClockWeatherSnapshot | null,\n hour24: number\n): string {\n if (condition === \"partly-cloudy\") {\n return isDaytimeWeather(weather, hour24)\n ? resolveWeatherAssetUrl(\"Partly_Cloudy_Day.webp\")\n : resolveWeatherAssetUrl(\"Partly_Cloudy.webp\");\n }\n\n return WEATHER_IMAGE_BY_CONDITION[condition] || WEATHER_IMAGE_BY_CONDITION.cloudy;\n}\n\nexport function isDaytimeWeather(weather: ClockWeatherSnapshot | null, hour24: number): boolean {\n if (weather && typeof weather.isDay === \"boolean\") {\n return weather.isDay;\n }\n\n return hour24 >= 6 && hour24 < 18;\n}\n\n\nfunction buildShiftedClockBackground(offsetPercent: number): string {\n const normalizedOffset = ((Number(offsetPercent) % 100) + 100) % 100;\n const shifted = getClockGradientStops()\n .flatMap((stop) => [\n { color: stop.color, percent: stop.percent - normalizedOffset },\n { color: stop.color, percent: stop.percent - normalizedOffset + 100 },\n ])\n .sort((left, right) => left.percent - right.percent);\n\n const visible = shifted.filter((stop) => stop.percent >= 0 && stop.percent <= 100);\n const before = shifted.filter((stop) => stop.percent < 0).slice(-1)[0];\n const after = shifted.find((stop) => stop.percent > 100);\n const normalized: Array<{ color: string; percent: number }> = [];\n\n if (before) {\n normalized.push({ color: before.color, percent: 0 });\n }\n\n for (const stop of visible) {\n normalized.push({ color: stop.color, percent: Number(stop.percent.toFixed(2)) });\n }\n\n if (after) {\n normalized.push({ color: after.color, percent: 100 });\n }\n\n return buildClockGradientFromStops(normalized);\n}\n\nfunction getClockLocationKey(location: Pick<ClockLocation, \"label\" | \"timeZone\" | \"weatherQuery\">): string {\n const weatherQuery = String(location.weatherQuery || location.label || \"\").trim().toLowerCase();\n const timeZone = String(location.timeZone || \"\").trim().toLowerCase();\n return `${weatherQuery}__${timeZone}`;\n}\n\nfunction getCommonClockCityKey(city: CommonClockCity): string {\n return `${city.label.toLowerCase()}__${city.timeZone.toLowerCase()}`;\n}\n\nasync function fetchClockWeather(\n locations: ClockLocation[],\n weatherEndpoint: string,\n signal: AbortSignal\n): Promise<ClockWeatherPayload> {\n if (weatherEndpoint) {\n return fetchClockWeatherFromEndpoint(locations, weatherEndpoint, signal);\n }\n\n return fetchClockWeatherFromOpenMeteo(locations, signal);\n}\n\nasync function fetchClockWeatherFromEndpoint(\n locations: ClockLocation[],\n weatherEndpoint: string,\n signal: AbortSignal\n): Promise<ClockWeatherPayload> {\n const response = await fetch(weatherEndpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ locations }),\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`Weather endpoint returned ${response.status}`);\n }\n\n const payload = (await response.json()) as ClockWeatherPayload;\n return {\n fetchedAt: String(payload?.fetchedAt || new Date().toISOString()),\n locations: Array.isArray(payload?.locations) ? payload.locations : [],\n };\n}\n\nasync function fetchClockWeatherFromOpenMeteo(\n locations: ClockLocation[],\n signal: AbortSignal\n): Promise<ClockWeatherPayload> {\n const items = await Promise.all(\n locations.map(async (location) => {\n try {\n return await fetchSingleLocationWeather(location, signal);\n } catch (error) {\n return {\n label: location.label,\n timeZone: location.timeZone,\n weatherQuery: String(location.weatherQuery || location.label || \"\").trim(),\n weather: {\n state: \"fail\",\n condition: \"unknown\",\n description: error instanceof Error ? error.message : \"Weather request failed\",\n } satisfies ClockWeatherSnapshot,\n };\n }\n })\n );\n\n return {\n fetchedAt: new Date().toISOString(),\n locations: items,\n };\n}\n\nasync function fetchSingleLocationWeather(\n location: ClockLocation,\n signal: AbortSignal\n): Promise<ClockWeatherEntry> {\n const label = String(location.label || \"\").trim();\n const timeZone = String(location.timeZone || \"\").trim();\n const weatherQuery = String(location.weatherQuery || location.label || \"\").trim();\n\n if (!weatherQuery) {\n throw new Error(\"Weather place missing\");\n }\n\n const geo = await geocodeLocation(weatherQuery, signal);\n const current = await fetchCurrentWeather(geo.latitude, geo.longitude, timeZone, signal);\n const weatherCode = Number(current.weather_code);\n const isDay = Number(current.is_day) === 1;\n const mapped = mapWeatherCode(weatherCode, isDay);\n\n return {\n label,\n timeZone,\n weatherQuery,\n weather: {\n state: \"pass\",\n condition: mapped.condition,\n description: mapped.description,\n code: weatherCode,\n isDay,\n temperature: Number.isFinite(Number(current.temperature_2m)) ? Number(current.temperature_2m) : null,\n temperatureUnit: \"°C\",\n cloudCover: Number.isFinite(Number(current.cloud_cover)) ? Number(current.cloud_cover) : null,\n precipitation: Number.isFinite(Number(current.precipitation)) ? Number(current.precipitation) : null,\n latitude: geo.latitude,\n longitude: geo.longitude,\n locationName: geo.displayName,\n },\n };\n}\n\nasync function geocodeLocation(query: string, signal: AbortSignal): Promise<GeocodeResult> {\n const cacheKey = query.toLowerCase();\n const cached = geocodeCache.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.value;\n }\n\n const attempts = Array.from(\n new Set([query, query.split(\",\")[0].trim(), query.replace(/\\s+/g, \" \").trim()].filter(Boolean))\n );\n\n let result: Record<string, unknown> | null = null;\n for (const attempt of attempts) {\n const url = new URL(\"https://geocoding-api.open-meteo.com/v1/search\");\n url.searchParams.set(\"name\", attempt);\n url.searchParams.set(\"count\", \"1\");\n url.searchParams.set(\"language\", \"en\");\n url.searchParams.set(\"format\", \"json\");\n\n const response = await fetch(url, { signal });\n if (!response.ok) {\n throw new Error(`Geocoding failed with ${response.status}`);\n }\n\n const payload = (await response.json()) as { results?: Record<string, unknown>[] };\n result = Array.isArray(payload.results) ? payload.results[0] || null : null;\n if (result) {\n break;\n }\n }\n\n if (!result) {\n throw new Error(`No weather location found for ${query}`);\n }\n\n const normalized = {\n latitude: Number(result.latitude),\n longitude: Number(result.longitude),\n displayName: [result.name, result.admin1 || result.country].filter(Boolean).join(\", \"),\n };\n\n geocodeCache.set(cacheKey, {\n expiresAt: Date.now() + GEOCODE_TTL_MS,\n value: normalized,\n });\n\n return normalized;\n}\n\nasync function fetchCurrentWeather(\n latitude: number,\n longitude: number,\n timeZone: string,\n signal: AbortSignal\n): Promise<WeatherResult> {\n const cacheKey = `${latitude}:${longitude}:${timeZone}`;\n const cached = weatherCache.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.value;\n }\n\n const url = new URL(\"https://api.open-meteo.com/v1/forecast\");\n url.searchParams.set(\"latitude\", String(latitude));\n url.searchParams.set(\"longitude\", String(longitude));\n url.searchParams.set(\"current\", \"temperature_2m,weather_code,is_day,cloud_cover,precipitation\");\n url.searchParams.set(\"timezone\", timeZone || \"auto\");\n url.searchParams.set(\"forecast_days\", \"1\");\n\n const response = await fetch(url, { signal });\n if (!response.ok) {\n throw new Error(`Weather fetch failed with ${response.status}`);\n }\n\n const payload = (await response.json()) as { current?: WeatherResult };\n if (!payload.current) {\n throw new Error(\"Current weather unavailable\");\n }\n\n weatherCache.set(cacheKey, {\n expiresAt: Date.now() + CLOCK_WEATHER_TTL_MS,\n value: payload.current,\n });\n\n return payload.current;\n}\n\nexport function mapWeatherCode(code: number, isDay: boolean): { condition: string; description: string } {\n if (code === 0) {\n return {\n condition: isDay ? \"clear-day\" : \"clear-night\",\n description: isDay ? \"Clear sky\" : \"Clear night\",\n };\n }\n\n if (code === 1 || code === 2) {\n return {\n condition: \"partly-cloudy\",\n description: \"Partly cloudy\",\n };\n }\n\n if (code === 3) {\n return {\n condition: \"cloudy\",\n description: \"Overcast\",\n };\n }\n\n if (code === 45 || code === 48) {\n return {\n condition: \"fog\",\n description: \"Fog\",\n };\n }\n\n if ([51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82].includes(code)) {\n return {\n condition: \"rain\",\n description: \"Rain\",\n };\n }\n\n if ([71, 73, 75, 77, 85, 86].includes(code)) {\n return {\n condition: \"snow\",\n description: \"Snow\",\n };\n }\n\n if ([95, 96, 99].includes(code)) {\n return {\n condition: \"storm\",\n description: \"Thunderstorm\",\n };\n }\n\n return {\n condition: \"cloudy\",\n description: \"Cloudy\",\n };\n}\n\nfunction isMacauManilaClockLocation(location: ClockLocation): boolean {\n const label = String(location.label || \"\").trim().toLowerCase();\n const timeZone = String(location.timeZone || \"\").trim().toLowerCase();\n const weatherQuery = String(location.weatherQuery || \"\").trim().toLowerCase();\n\n return (\n label === \"macau\" ||\n label === \"manila\" ||\n label === \"macau / manila\" ||\n weatherQuery === \"macau\" ||\n weatherQuery === \"manila\" ||\n timeZone === \"asia/macau\" ||\n timeZone === \"asia/manila\"\n );\n}\n\nfunction isGoldCoastClockLocation(location: ClockLocation): boolean {\n const label = String(location.label || \"\").trim().toLowerCase();\n const timeZone = String(location.timeZone || \"\").trim().toLowerCase();\n const weatherQuery = String(location.weatherQuery || \"\").trim().toLowerCase();\n\n return (\n label === \"gold coast\" ||\n weatherQuery === \"gold coast\" ||\n weatherQuery === \"gold coast, australia\" ||\n timeZone === \"australia/brisbane\"\n );\n}\n\nfunction compareClockLocations(left: ClockLocation, right: ClockLocation): number {\n const leftOrder = getClockTimezoneOrder(left.timeZone);\n const rightOrder = getClockTimezoneOrder(right.timeZone);\n\n if (leftOrder !== rightOrder) {\n return leftOrder - rightOrder;\n }\n\n return left.label.localeCompare(right.label);\n}\n\nfunction getClockTimezoneOrder(timeZone: string): number {\n const order: Record<string, number> = {\n \"America/Los_Angeles\": 0,\n \"Asia/Jerusalem\": 1,\n \"Asia/Kolkata\": 2,\n \"Asia/Macau\": 3,\n \"Australia/Sydney\": 4,\n };\n\n return Object.prototype.hasOwnProperty.call(order, timeZone) ? order[timeZone] : Number.MAX_SAFE_INTEGER;\n}\n\nfunction escapeHtml(value: string): string {\n return String(value)\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&#39;\");\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"world-clock-strip\": WorldClockStripElement;\n }\n}\n\nexport { WORLD_CLOCK_TAG_NAME };\n"],"names":["WORLD_CLOCK_TAG_NAME","WORLD_CLOCK_TIME_ZONE_DATALIST_ID","DEFAULT_WORLD_CLOCK_SHARE_QUERY_PARAM","DEFAULT_WORLD_CLOCK_PRESET_STORAGE_KEY","geocodeCache","weatherCache","US_FAHRENHEIT_TIME_ZONES","WEATHER_IMAGE_BY_CONDITION","resolveWeatherAssetUrl","defaultClockLocations","fallbackClockTimeZones","commonClockCities","WorldClockStripElement","normalizeClockLocations","name","_oldValue","newValue","parseLocationsAttribute","normalizeVisualPreset","location","value","city","normalizeCommonClockCities","stored","readWorldClockConfigFromStorage","configFromUrl","readWorldClockConfigFromUrl","refreshWeather","source","writeWorldClockConfigToStorage","renderOnMinute","delay","force","requestKey","isFresh","controller","payload","fetchClockWeather","byKey","entry","getClockLocationKey","error","event","target","actionElement","action","presetName","key","getCommonClockCityKey","index","next","setting","field","keepDrawerOpen","nextLocations","focusSnapshot","styles","now","descriptors","timeParts","getClockTimeParts","resolveWeatherForLocation","getClockSlotPercent","markers","assignClockMarkerOffsets","laneCount","max","marker","buildClockStripBackground","descriptor","draft","commonCityResults","selectedCommonCity","savedPresets","escapeHtml","getSupportedClockTimeZones","timeZone","preset","results","selectedCity","existingKeys","query","url","buildWorldClockShareUrl","copyTextToClipboard","text","parsed","normalized","normalizeWorldClockConfig","raw","presets","message","active","snapshot","labelText","timeLabel","metaLabel","temperatureText","formatClockTemperature","getSystemTimeZone","edgeClass","getClockMarkerEdgeClass","leftStyle","formatClockOffsetPx","titleText","weather","condition","getFallbackWeatherCondition","image","resolveWeatherImage","defineWorldClockStrip","tagName","existing","createWorldClockStrip","options","element","locations","deduped","sharedAsiaAdded","isGoldCoastClockLocation","isMacauManilaClockLocation","compareClockLocations","fallback","buildClockGradientFromStops","stops","stop","amount","positionPercent","parts","map","part","hour12","dayPeriod","buildClockDayText","weekdayText","dayNumber","getDayOfMonthForTimeZone","getOrdinalSuffix","dayPart","mod100","mod10","systemTimeZone","celsius","unit","getSystemTemperatureUnit","celsiusToFahrenheit","weatherByKey","overrides","hour24","getClockGradientStops","baseAnchors","getClockTimePercent","unwrappedAnchors","unwrapClockAnchors","extendedAnchors","anchor","left","right","sampleCount","x","timePercent","interpolateClockTimeAtX","sampleClockGradientColor","total","gutterPercent","usablePercent","anchors","unwrapped","previous","current","span","progress","interpolateHexColor","leftRgb","hexToRgb","rightRgb","rgbToHex","channel","fileName","relativePath","queryParam","encoded","deserializeWorldClockConfig","config","serializeWorldClockConfig","encodeBase64Url","json","decodeBase64Url","padded","input","isDaytimeWeather","weatherQuery","weatherEndpoint","signal","fetchClockWeatherFromEndpoint","fetchClockWeatherFromOpenMeteo","response","items","fetchSingleLocationWeather","label","geo","geocodeLocation","fetchCurrentWeather","weatherCode","isDay","mapped","mapWeatherCode","cacheKey","cached","attempts","result","attempt","latitude","longitude","code","leftOrder","getClockTimezoneOrder","rightOrder","order"],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ export interface ClockLocation {
2
+ label: string;
3
+ timeZone: string;
4
+ weatherQuery?: string;
5
+ }
6
+ export interface ClockWeatherSnapshot {
7
+ state: "pass" | "fail";
8
+ condition: string;
9
+ description: string;
10
+ code?: number;
11
+ isDay?: boolean;
12
+ temperature?: number | null;
13
+ temperatureUnit?: string;
14
+ cloudCover?: number | null;
15
+ precipitation?: number | null;
16
+ latitude?: number;
17
+ longitude?: number;
18
+ locationName?: string;
19
+ }
20
+ export type VisualPreset = "default" | "minimal" | "cinematic" | "wallboard";
21
+ export interface WorldClockConfig {
22
+ locations: ClockLocation[];
23
+ weatherEnabled: boolean;
24
+ weatherEndpoint: string;
25
+ visualPreset: VisualPreset;
26
+ }
27
+ export interface WorldClockStripOptions {
28
+ locations?: ClockLocation[];
29
+ weatherEnabled?: boolean;
30
+ weatherEndpoint?: string;
31
+ weatherOverrides?: Record<string, ClockWeatherSnapshot>;
32
+ visualPreset?: VisualPreset;
33
+ readOnly?: boolean;
34
+ persistKey?: string;
35
+ enableUrlState?: boolean;
36
+ shareQueryParam?: string;
37
+ cityCatalog?: CommonClockCity[];
38
+ }
39
+ export interface CommonClockCity {
40
+ label: string;
41
+ timeZone: string;
42
+ weatherQuery: string;
43
+ country: string;
44
+ }
45
+ declare const WORLD_CLOCK_TAG_NAME = "world-clock-strip";
46
+ export declare const defaultClockLocations: ClockLocation[];
47
+ export declare class WorldClockStripElement extends HTMLElement {
48
+ static get observedAttributes(): string[];
49
+ private readonly root;
50
+ private locationsState;
51
+ private weatherEnabledState;
52
+ private weatherEndpointState;
53
+ private visualPresetState;
54
+ private readOnlyState;
55
+ private persistKeyState;
56
+ private enableUrlState;
57
+ private shareQueryParamState;
58
+ private cityCatalogState;
59
+ private weatherOverridesState;
60
+ private weatherByKey;
61
+ private weatherFetchedAt;
62
+ private weatherRequestKey;
63
+ private clockTimer;
64
+ private weatherTimer;
65
+ private inFlightWeatherRequest;
66
+ private configDrawerOpen;
67
+ private advancedSettingsOpen;
68
+ private configDraftState;
69
+ private addLocationOpen;
70
+ private addLocationQuery;
71
+ private addLocationPreferredName;
72
+ private selectedCommonCityKey;
73
+ private pendingDeleteIndex;
74
+ private selectedLocationIndex;
75
+ private customLocationDraft;
76
+ private presetNameDraft;
77
+ private importExportDraft;
78
+ private importExportOpen;
79
+ private statusMessage;
80
+ constructor();
81
+ connectedCallback(): void;
82
+ disconnectedCallback(): void;
83
+ attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void;
84
+ get locations(): ClockLocation[];
85
+ set locations(value: ClockLocation[]);
86
+ get weatherEnabled(): boolean;
87
+ set weatherEnabled(value: boolean);
88
+ get weatherEndpoint(): string;
89
+ set weatherEndpoint(value: string);
90
+ get visualPreset(): VisualPreset;
91
+ set visualPreset(value: VisualPreset);
92
+ get readOnly(): boolean;
93
+ set readOnly(value: boolean);
94
+ get persistKey(): string;
95
+ set persistKey(value: string);
96
+ get shareQueryParam(): string;
97
+ set shareQueryParam(value: string);
98
+ get cityCatalog(): CommonClockCity[];
99
+ set cityCatalog(value: CommonClockCity[]);
100
+ get weatherOverrides(): Record<string, ClockWeatherSnapshot>;
101
+ set weatherOverrides(value: Record<string, ClockWeatherSnapshot>);
102
+ get config(): WorldClockConfig;
103
+ set config(value: WorldClockConfig);
104
+ private readAttributes;
105
+ private initializeSharedState;
106
+ private handleConfigurationChange;
107
+ private applyConfigValue;
108
+ private persistCurrentConfig;
109
+ private dispatchConfigChange;
110
+ private startClockRefresh;
111
+ private stopClockRefresh;
112
+ private startWeatherRefresh;
113
+ private stopWeatherRefresh;
114
+ private refreshWeather;
115
+ private buildWeatherRequestKey;
116
+ private createConfigDraft;
117
+ private syncConfigDraftFromState;
118
+ private handleRootClick;
119
+ private handleRootInput;
120
+ private handleRootChange;
121
+ private handleRootFocusOut;
122
+ private applyConfigDraft;
123
+ private render;
124
+ private renderConfigDrawer;
125
+ private renderPresetPanel;
126
+ private renderImportExportPanel;
127
+ private renderAddLocationPanel;
128
+ private renderAdvancedSettings;
129
+ private renderConfigLocationListItem;
130
+ private getFilteredCommonCities;
131
+ private getSelectedCommonCity;
132
+ private resetAddLocationUi;
133
+ private resetTransientConfigUi;
134
+ private copyShareLink;
135
+ private copyConfigJson;
136
+ private importConfigJson;
137
+ private getSavedPresets;
138
+ private writeSavedPresets;
139
+ private saveCurrentPreset;
140
+ private loadSavedPreset;
141
+ private deleteSavedPreset;
142
+ private setStatusMessage;
143
+ private captureRenderFocus;
144
+ private restoreRenderFocus;
145
+ private renderClockMarker;
146
+ private renderClockWeatherBackdrop;
147
+ }
148
+ export declare function defineWorldClockStrip(tagName?: string): typeof WorldClockStripElement;
149
+ export declare function createWorldClockStrip(options?: WorldClockStripOptions): WorldClockStripElement;
150
+ export declare function normalizeClockLocations(locations?: ClockLocation[]): ClockLocation[];
151
+ export declare function getFallbackWeatherCondition(hour24: number): string;
152
+ export declare function serializeWorldClockConfig(config: Partial<WorldClockConfig>): string;
153
+ export declare function deserializeWorldClockConfig(value: string): WorldClockConfig;
154
+ export declare function isDaytimeWeather(weather: ClockWeatherSnapshot | null, hour24: number): boolean;
155
+ export declare function mapWeatherCode(code: number, isDay: boolean): {
156
+ condition: string;
157
+ description: string;
158
+ };
159
+ declare global {
160
+ interface HTMLElementTagNameMap {
161
+ "world-clock-strip": WorldClockStripElement;
162
+ }
163
+ }
164
+ export { WORLD_CLOCK_TAG_NAME };
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "world-clock-strip",
3
+ "version": "0.2.0",
4
+ "description": "Reusable world clock strip extracted from the Dashboard web app.",
5
+ "type": "module",
6
+ "files": [
7
+ "dist",
8
+ "assets/weather/Cloudy.webp",
9
+ "assets/weather/Foggy.webp",
10
+ "assets/weather/Partly_Cloudy.webp",
11
+ "assets/weather/Partly_Cloudy_Day.webp",
12
+ "assets/weather/Rainy.webp",
13
+ "assets/weather/Snow.webp",
14
+ "assets/weather/starry-night.webp",
15
+ "assets/weather/storm.webp",
16
+ "assets/weather/Sunny.webp"
17
+ ],
18
+ "main": "./dist/index.js",
19
+ "module": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ }
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/steve777/World-Clock.git"
30
+ },
31
+ "homepage": "https://github.com/steve777/World-Clock",
32
+ "bugs": {
33
+ "url": "https://github.com/steve777/World-Clock/issues"
34
+ },
35
+ "scripts": {
36
+ "clean": "rm -rf dist demo-dist",
37
+ "dev": "vite",
38
+ "build": "npm run clean && vite build -c vite.lib.config.ts && tsc -p tsconfig.build.json",
39
+ "build:demo": "vite build",
40
+ "preview": "vite preview --host 127.0.0.1 --port 4173",
41
+ "typecheck": "tsc --noEmit",
42
+ "test": "npm run build && node --test test/**/*.test.mjs",
43
+ "test:smoke": "playwright test",
44
+ "test:package": "npm run build && node scripts/package-smoke.mjs",
45
+ "verify": "npm run typecheck && npm run test && npm run test:package && npm run test:smoke",
46
+ "prepublishOnly": "npm run verify"
47
+ },
48
+ "keywords": [
49
+ "world-clock",
50
+ "web-component",
51
+ "dashboard",
52
+ "weather"
53
+ ],
54
+ "author": "",
55
+ "license": "ISC",
56
+ "devDependencies": {
57
+ "@playwright/test": "^1.58.2",
58
+ "typescript": "^5.9.3",
59
+ "vite": "^7.1.6"
60
+ }
61
+ }