import type { DurationFormatConstructor } from "@formatjs/intl-durationformat/src/types"; import type { Auth, Connection, HassConfig, HassEntities, HassEntity, HassServices, HassServiceTarget, MessageBase, } from "home-assistant-js-websocket"; import type { LocalizeFunc } from "./common/translations/localize"; import type { AreaRegistryEntry } from "./data/area_registry"; import type { DeviceRegistryEntry } from "./data/device_registry"; import type { EntityRegistryDisplayEntry } from "./data/entity_registry"; import type { FloorRegistryEntry } from "./data/floor_registry"; import type { CoreFrontendUserData } from "./data/frontend"; import type { FrontendLocaleData, getHassTranslations, } from "./data/translation"; import type { Themes } from "./data/ws-themes"; import type { ExternalMessaging } from "./external_app/external_messaging"; declare global { /* eslint-disable no-var, @typescript-eslint/naming-convention */ var __DEV__: boolean; var __DEMO__: boolean; var __BUILD__: "modern" | "legacy"; var __VERSION__: string; var __STATIC_PATH__: string; var __BACKWARDS_COMPAT__: boolean; var __SUPERVISOR__: boolean; var __HASS_URL__: string; /* eslint-enable no-var, @typescript-eslint/naming-convention */ interface Window { // Custom panel entry point url customPanelJS: string; ShadyCSS: { nativeCss: boolean; nativeShadow: boolean; prepareTemplate(templateElement, elementName, elementExtension); styleElement(element); styleSubtree(element, overrideProperties); styleDocument(overrideProperties); getComputedStyleValue(element, propertyName); }; } // for fire event interface HASSDomEvents { "value-changed": { value: unknown; }; change: undefined; "hass-logout": undefined; "config-refresh": undefined; "hass-api-called": { success: boolean; response: unknown; }; } // For loading workers in rspack interface ImportMeta { url: string; } // Intl.DurationFormat is not yet part of the TypeScript standard // eslint-disable-next-line @typescript-eslint/no-namespace namespace Intl { // eslint-disable-next-line @typescript-eslint/naming-convention const DurationFormat: DurationFormatConstructor; } } export interface ValueChangedEvent extends CustomEvent { detail: { value: T; }; } export type Constructor = new (...args: any[]) => T; export interface ClassElement { kind: "field" | "method"; key: PropertyKey; placement: "static" | "prototype" | "own"; initializer?: (...args) => unknown; extras?: ClassElement[]; finisher?: (cls: Constructor) => undefined | Constructor; descriptor?: PropertyDescriptor; } export interface Credential { auth_provider_type: string; auth_provider_id: string; } export interface MFAModule { id: string; name: string; enabled: boolean; } export interface CurrentUser { id: string; is_owner: boolean; is_admin: boolean; name: string; credentials: Credential[]; mfa_modules: MFAModule[]; } // Currently selected theme and its settings. These are the values stored in local storage. // Note: These values are not meant to be used at runtime to check whether dark mode is active // or which theme name to use, as this interface represents the config data for the theme picker. // The actually active dark mode and theme name can be read from hass.themes. export interface ThemeSettings { theme: string; // Radio box selection for theme picker. Do not use in Lovelace rendering as // it can be undefined == auto. // Property hass.themes.darkMode carries effective current mode. dark?: boolean; primaryColor?: string; accentColor?: string; } export interface PanelInfo | null> { component_name: string; config: T; icon: string | null; title: string | null; url_path: string; config_panel_domain?: string; } export type Panels = Record; export interface CalendarViewChanged { end: Date; start: Date; view: string; } export type FullCalendarView = | "dayGridMonth" | "dayGridWeek" | "dayGridDay" | "listWeek"; export type ThemeMode = "auto" | "light" | "dark"; export interface ToggleButton { label: string; iconPath?: string; value: string; } export interface Translation { nativeName: string; isRTL: boolean; hash: string; } export interface TranslationMetadata { fragments: string[]; translations: Record; } // eslint-disable-next-line @typescript-eslint/consistent-type-imports export type TranslationDict = typeof import("./translations/en.json"); export interface IconMetaFile { version: string; parts: IconMeta[]; } export interface IconMeta { start: string; file: string; } export interface Notification { notification_id: string; message: string; title: string; status: "read" | "unread"; created_at: string; } export type Resources = Record>; export interface Context { id: string; parent_id?: string; user_id?: string | null; } export interface ServiceCallResponse { context: Context; response?: any; } export interface ServiceCallRequest { domain: string; service: string; serviceData?: Record; target?: HassServiceTarget; } export interface HomeAssistant { auth: Auth & { external?: ExternalMessaging }; connection: Connection; connected: boolean; states: HassEntities; entities: Record; devices: Record; areas: Record; floors: Record; services: HassServices; config: HassConfig; themes: Themes; selectedTheme: ThemeSettings | null; panels: Panels; panelUrl: string; // i18n // current effective language in that order: // - backend saved user selected language // - language in local app storage // - browser language // - english (en) language: string; // local stored language, keep that name for backward compatibility selectedLanguage: string | null; locale: FrontendLocaleData; resources: Resources; localize: LocalizeFunc; translationMetadata: TranslationMetadata; suspendWhenHidden: boolean; enableShortcuts: boolean; vibrate: boolean; debugConnection: boolean; dockedSidebar: "docked" | "always_hidden" | "auto"; defaultPanel: string; moreInfoEntityId: string | null; user?: CurrentUser; userData?: CoreFrontendUserData | null; hassUrl(path?): string; callService( domain: ServiceCallRequest["domain"], service: ServiceCallRequest["service"], serviceData?: ServiceCallRequest["serviceData"], target?: ServiceCallRequest["target"], notifyOnError?: boolean, returnResponse?: boolean ): Promise; callApi( method: "GET" | "POST" | "PUT" | "DELETE", path: string, parameters?: Record, headers?: Record ): Promise; callApiRaw( // introduced in 2024.11 method: "GET" | "POST" | "PUT" | "DELETE", path: string, parameters?: Record, headers?: Record, signal?: AbortSignal ): Promise; fetchWithAuth(path: string, init?: Record): Promise; sendWS(msg: MessageBase): void; callWS(msg: MessageBase): Promise; loadBackendTranslation( category: Parameters[2], integrations?: Parameters[3], configFlow?: Parameters[4] ): Promise; loadFragmentTranslation(fragment: string): Promise; formatEntityState(stateObj: HassEntity, state?: string): string; formatEntityAttributeValue( stateObj: HassEntity, attribute: string, value?: any ): string; formatEntityAttributeName(stateObj: HassEntity, attribute: string): string; } export interface Route { prefix: string; path: string; } export interface PanelElement extends HTMLElement { hass?: HomeAssistant; narrow?: boolean; route?: Route | null; panel?: PanelInfo; } export interface LocalizeMixin { hass?: HomeAssistant; localize: LocalizeFunc; } // https://www.jpwilliams.dev/how-to-unpack-the-return-type-of-a-promise-in-typescript export type AsyncReturnType any> = T extends ( ...args: any ) => Promise ? U : T extends (...args: any) => infer U ? U : never; export type Entries = [keyof T, T[keyof T]][];