diff --git a/src/components/country-datalist.ts b/src/components/country-datalist.ts deleted file mode 100644 index 7692e58c0c..0000000000 --- a/src/components/country-datalist.ts +++ /dev/null @@ -1,286 +0,0 @@ -import memoizeOne from "memoize-one"; -import { caseInsensitiveStringCompare } from "../common/string/compare"; - -export const COUNTRIES = [ - "AD", - "AE", - "AF", - "AG", - "AI", - "AL", - "AM", - "AO", - "AQ", - "AR", - "AS", - "AT", - "AU", - "AW", - "AX", - "AZ", - "BA", - "BB", - "BD", - "BE", - "BF", - "BG", - "BH", - "BI", - "BJ", - "BL", - "BM", - "BN", - "BO", - "BQ", - "BR", - "BS", - "BT", - "BV", - "BW", - "BY", - "BZ", - "CA", - "CC", - "CD", - "CF", - "CG", - "CH", - "CI", - "CK", - "CL", - "CM", - "CN", - "CO", - "CR", - "CU", - "CV", - "CW", - "CX", - "CY", - "CZ", - "DE", - "DJ", - "DK", - "DM", - "DO", - "DZ", - "EC", - "EE", - "EG", - "EH", - "ER", - "ES", - "ET", - "FI", - "FJ", - "FK", - "FM", - "FO", - "FR", - "GA", - "GB", - "GD", - "GE", - "GF", - "GG", - "GH", - "GI", - "GL", - "GM", - "GN", - "GP", - "GQ", - "GR", - "GS", - "GT", - "GU", - "GW", - "GY", - "HK", - "HM", - "HN", - "HR", - "HT", - "HU", - "ID", - "IE", - "IL", - "IM", - "IN", - "IO", - "IQ", - "IR", - "IS", - "IT", - "JE", - "JM", - "JO", - "JP", - "KE", - "KG", - "KH", - "KI", - "KM", - "KN", - "KP", - "KR", - "KW", - "KY", - "KZ", - "LA", - "LB", - "LC", - "LI", - "LK", - "LR", - "LS", - "LT", - "LU", - "LV", - "LY", - "MA", - "MC", - "MD", - "ME", - "MF", - "MG", - "MH", - "MK", - "ML", - "MM", - "MN", - "MO", - "MP", - "MQ", - "MR", - "MS", - "MT", - "MU", - "MV", - "MW", - "MX", - "MY", - "MZ", - "NA", - "NC", - "NE", - "NF", - "NG", - "NI", - "NL", - "NO", - "NP", - "NR", - "NU", - "NZ", - "OM", - "PA", - "PE", - "PF", - "PG", - "PH", - "PK", - "PL", - "PM", - "PN", - "PR", - "PS", - "PT", - "PW", - "PY", - "QA", - "RE", - "RO", - "RS", - "RU", - "RW", - "SA", - "SB", - "SC", - "SD", - "SE", - "SG", - "SH", - "SI", - "SJ", - "SK", - "SL", - "SM", - "SN", - "SO", - "SR", - "SS", - "ST", - "SV", - "SX", - "SY", - "SZ", - "TC", - "TD", - "TF", - "TG", - "TH", - "TJ", - "TK", - "TL", - "TM", - "TN", - "TO", - "TR", - "TT", - "TV", - "TW", - "TZ", - "UA", - "UG", - "UM", - "US", - "UY", - "UZ", - "VA", - "VC", - "VE", - "VG", - "VI", - "VN", - "VU", - "WF", - "WS", - "YE", - "YT", - "ZA", - "ZM", - "ZW", -]; - -export const getCountryOptions = memoizeOne((language?: string) => { - const countryDisplayNames = - Intl && "DisplayNames" in Intl - ? new Intl.DisplayNames(language, { - type: "region", - fallback: "code", - }) - : undefined; - - const options = COUNTRIES.map((country) => ({ - value: country, - label: countryDisplayNames ? countryDisplayNames.of(country)! : country, - })); - options.sort((a, b) => - caseInsensitiveStringCompare(a.label, b.label, language) - ); - return options; -}); - -export const createCountryListEl = (language?: string) => { - const list = document.createElement("datalist"); - list.id = "countries"; - const options = getCountryOptions(language); - for (const country of options) { - const option = document.createElement("option"); - option.value = country.value; - option.innerText = country.label; - list.appendChild(option); - } - return list; -}; diff --git a/src/components/currency-datalist.ts b/src/components/currency-datalist.ts deleted file mode 100644 index ef29faf56c..0000000000 --- a/src/components/currency-datalist.ts +++ /dev/null @@ -1,192 +0,0 @@ -import memoizeOne from "memoize-one"; -import { caseInsensitiveStringCompare } from "../common/string/compare"; - -export const CURRENCIES = [ - "AED", - "AFN", - "ALL", - "AMD", - "ANG", - "AOA", - "ARS", - "AUD", - "AWG", - "AZN", - "BAM", - "BBD", - "BDT", - "BGN", - "BHD", - "BIF", - "BMD", - "BND", - "BOB", - "BRL", - "BSD", - "BTN", - "BWP", - "BYN", - "BYR", - "BZD", - "CAD", - "CDF", - "CHF", - "CLP", - "CNY", - "COP", - "CRC", - "CUP", - "CVE", - "CZK", - "DJF", - "DKK", - "DOP", - "DZD", - "EGP", - "ERN", - "ETB", - "EUR", - "FJD", - "FKP", - "GBP", - "GEL", - "GHS", - "GIP", - "GMD", - "GNF", - "GTQ", - "GYD", - "HKD", - "HNL", - "HRK", - "HTG", - "HUF", - "IDR", - "ILS", - "INR", - "IQD", - "IRR", - "ISK", - "JMD", - "JOD", - "JPY", - "KES", - "KGS", - "KHR", - "KMF", - "KPW", - "KRW", - "KWD", - "KYD", - "KZT", - "LAK", - "LBP", - "LKR", - "LRD", - "LSL", - "LTL", - "LYD", - "MAD", - "MDL", - "MGA", - "MKD", - "MMK", - "MNT", - "MOP", - "MRO", - "MUR", - "MVR", - "MWK", - "MXN", - "MYR", - "MZN", - "NAD", - "NGN", - "NIO", - "NOK", - "NPR", - "NZD", - "OMR", - "PAB", - "PEN", - "PGK", - "PHP", - "PKR", - "PLN", - "PYG", - "QAR", - "RON", - "RSD", - "RUB", - "RWF", - "SAR", - "SBD", - "SCR", - "SDG", - "SEK", - "SGD", - "SHP", - "SLL", - "SOS", - "SRD", - "SSP", - "STD", - "SYP", - "SZL", - "THB", - "TJS", - "TMT", - "TND", - "TOP", - "TRY", - "TTD", - "TWD", - "TZS", - "UAH", - "UGX", - "USD", - "UYU", - "UZS", - "VEF", - "VND", - "VUV", - "WST", - "XAF", - "XCD", - "XOF", - "XPF", - "YER", - "ZAR", - "ZMW", - "ZWL", -]; - -export const getCurrencyOptions = memoizeOne((language?: string) => { - const currencyDisplayNames = - Intl && "DisplayNames" in Intl - ? new Intl.DisplayNames(language, { - type: "currency", - fallback: "code", - }) - : undefined; - const options = CURRENCIES.map((currency) => ({ - value: currency, - label: currencyDisplayNames ? currencyDisplayNames.of(currency)! : currency, - })); - options.sort((a, b) => - caseInsensitiveStringCompare(a.label, b.label, language) - ); - return options; -}); - -export const createCurrencyListEl = (language: string) => { - const list = document.createElement("datalist"); - list.id = "currencies"; - for (const currency of getCurrencyOptions(language)) { - const option = document.createElement("option"); - option.value = currency.value; - option.innerText = currency.label; - list.appendChild(option); - } - return list; -}; diff --git a/src/components/ha-country-picker.ts b/src/components/ha-country-picker.ts new file mode 100644 index 0000000000..5fff71bdfa --- /dev/null +++ b/src/components/ha-country-picker.ts @@ -0,0 +1,340 @@ +import { css, CSSResultGroup, html, LitElement } from "lit"; +import { customElement, property } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../common/dom/fire_event"; +import { stopPropagation } from "../common/dom/stop_propagation"; +import { caseInsensitiveStringCompare } from "../common/string/compare"; +import "../resources/intl-polyfill"; +import "./ha-list-item"; +import "./ha-select"; +import type { HaSelect } from "./ha-select"; + +const COUNTRIES = [ + "AD", + "AE", + "AF", + "AG", + "AI", + "AL", + "AM", + "AO", + "AQ", + "AR", + "AS", + "AT", + "AU", + "AW", + "AX", + "AZ", + "BA", + "BB", + "BD", + "BE", + "BF", + "BG", + "BH", + "BI", + "BJ", + "BL", + "BM", + "BN", + "BO", + "BQ", + "BR", + "BS", + "BT", + "BV", + "BW", + "BY", + "BZ", + "CA", + "CC", + "CD", + "CF", + "CG", + "CH", + "CI", + "CK", + "CL", + "CM", + "CN", + "CO", + "CR", + "CU", + "CV", + "CW", + "CX", + "CY", + "CZ", + "DE", + "DJ", + "DK", + "DM", + "DO", + "DZ", + "EC", + "EE", + "EG", + "EH", + "ER", + "ES", + "ET", + "FI", + "FJ", + "FK", + "FM", + "FO", + "FR", + "GA", + "GB", + "GD", + "GE", + "GF", + "GG", + "GH", + "GI", + "GL", + "GM", + "GN", + "GP", + "GQ", + "GR", + "GS", + "GT", + "GU", + "GW", + "GY", + "HK", + "HM", + "HN", + "HR", + "HT", + "HU", + "ID", + "IE", + "IL", + "IM", + "IN", + "IO", + "IQ", + "IR", + "IS", + "IT", + "JE", + "JM", + "JO", + "JP", + "KE", + "KG", + "KH", + "KI", + "KM", + "KN", + "KP", + "KR", + "KW", + "KY", + "KZ", + "LA", + "LB", + "LC", + "LI", + "LK", + "LR", + "LS", + "LT", + "LU", + "LV", + "LY", + "MA", + "MC", + "MD", + "ME", + "MF", + "MG", + "MH", + "MK", + "ML", + "MM", + "MN", + "MO", + "MP", + "MQ", + "MR", + "MS", + "MT", + "MU", + "MV", + "MW", + "MX", + "MY", + "MZ", + "NA", + "NC", + "NE", + "NF", + "NG", + "NI", + "NL", + "NO", + "NP", + "NR", + "NU", + "NZ", + "OM", + "PA", + "PE", + "PF", + "PG", + "PH", + "PK", + "PL", + "PM", + "PN", + "PR", + "PS", + "PT", + "PW", + "PY", + "QA", + "RE", + "RO", + "RS", + "RU", + "RW", + "SA", + "SB", + "SC", + "SD", + "SE", + "SG", + "SH", + "SI", + "SJ", + "SK", + "SL", + "SM", + "SN", + "SO", + "SR", + "SS", + "ST", + "SV", + "SX", + "SY", + "SZ", + "TC", + "TD", + "TF", + "TG", + "TH", + "TJ", + "TK", + "TL", + "TM", + "TN", + "TO", + "TR", + "TT", + "TV", + "TW", + "TZ", + "UA", + "UG", + "UM", + "US", + "UY", + "UZ", + "VA", + "VC", + "VE", + "VG", + "VI", + "VN", + "VU", + "WF", + "WS", + "YE", + "YT", + "ZA", + "ZM", + "ZW", +]; + +@customElement("ha-country-picker") +export class HaCountryPicker extends LitElement { + @property() public language = "en"; + + @property() public value?: string; + + @property() public label?: string; + + @property({ type: Boolean }) public required = false; + + @property({ type: Boolean, reflect: true }) public disabled = false; + + private _getOptions = memoizeOne((language?: string) => { + const countryDisplayNames = + Intl && "DisplayNames" in Intl + ? new Intl.DisplayNames(language, { + type: "region", + fallback: "code", + }) + : undefined; + + const options = COUNTRIES.map((country) => ({ + value: country, + label: countryDisplayNames ? countryDisplayNames.of(country)! : country, + })); + options.sort((a, b) => + caseInsensitiveStringCompare(a.label, b.label, language) + ); + return options; + }); + + protected render() { + const options = this._getOptions(this.language); + + return html` + + ${options.map( + (option) => html` + ${option.label} + ` + )} + + `; + } + + static get styles(): CSSResultGroup { + return css` + ha-select { + width: 100%; + } + `; + } + + private _changed(ev): void { + const target = ev.target as HaSelect; + if (target.value === "" || target.value === this.value) { + return; + } + this.value = target.value; + fireEvent(this, "value-changed", { value: this.value }); + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-country-picker": HaCountryPicker; + } +} diff --git a/src/components/ha-currency-picker.ts b/src/components/ha-currency-picker.ts new file mode 100644 index 0000000000..10a3f90012 --- /dev/null +++ b/src/components/ha-currency-picker.ts @@ -0,0 +1,256 @@ +import { css, CSSResultGroup, html, LitElement } from "lit"; +import { customElement, property } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../common/dom/fire_event"; +import { stopPropagation } from "../common/dom/stop_propagation"; +import { caseInsensitiveStringCompare } from "../common/string/compare"; +import "../resources/intl-polyfill"; +import "./ha-list-item"; +import "./ha-select"; +import type { HaSelect } from "./ha-select"; + +const CURRENCIES = [ + "AED", + "AFN", + "ALL", + "AMD", + "ANG", + "AOA", + "ARS", + "AUD", + "AWG", + "AZN", + "BAM", + "BBD", + "BDT", + "BGN", + "BHD", + "BIF", + "BMD", + "BND", + "BOB", + "BRL", + "BSD", + "BTN", + "BWP", + "BYN", + "BYR", + "BZD", + "CAD", + "CDF", + "CHF", + "CLP", + "CNY", + "COP", + "CRC", + "CUP", + "CVE", + "CZK", + "DJF", + "DKK", + "DOP", + "DZD", + "EGP", + "ERN", + "ETB", + "EUR", + "FJD", + "FKP", + "GBP", + "GEL", + "GHS", + "GIP", + "GMD", + "GNF", + "GTQ", + "GYD", + "HKD", + "HNL", + "HRK", + "HTG", + "HUF", + "IDR", + "ILS", + "INR", + "IQD", + "IRR", + "ISK", + "JMD", + "JOD", + "JPY", + "KES", + "KGS", + "KHR", + "KMF", + "KPW", + "KRW", + "KWD", + "KYD", + "KZT", + "LAK", + "LBP", + "LKR", + "LRD", + "LSL", + "LTL", + "LYD", + "MAD", + "MDL", + "MGA", + "MKD", + "MMK", + "MNT", + "MOP", + "MRO", + "MUR", + "MVR", + "MWK", + "MXN", + "MYR", + "MZN", + "NAD", + "NGN", + "NIO", + "NOK", + "NPR", + "NZD", + "OMR", + "PAB", + "PEN", + "PGK", + "PHP", + "PKR", + "PLN", + "PYG", + "QAR", + "RON", + "RSD", + "RUB", + "RWF", + "SAR", + "SBD", + "SCR", + "SDG", + "SEK", + "SGD", + "SHP", + "SLL", + "SOS", + "SRD", + "SSP", + "STD", + "SYP", + "SZL", + "THB", + "TJS", + "TMT", + "TND", + "TOP", + "TRY", + "TTD", + "TWD", + "TZS", + "UAH", + "UGX", + "USD", + "UYU", + "UZS", + "VEF", + "VND", + "VUV", + "WST", + "XAF", + "XCD", + "XOF", + "XPF", + "YER", + "ZAR", + "ZMW", + "ZWL", +]; + +const curSymbol = (currency: string, locale?: string) => + Intl && "NumberFormat" in Intl + ? new Intl.NumberFormat(locale, { style: "currency", currency }) + .formatToParts(1) + .find((x) => x.type === "currency")?.value + : currency; + +@customElement("ha-currency-picker") +export class HaCurrencyPicker extends LitElement { + @property() public language = "en"; + + @property() public value?: string; + + @property() public label?: string; + + @property({ type: Boolean }) public required = false; + + @property({ type: Boolean, reflect: true }) public disabled = false; + + private _getOptions = memoizeOne((language?: string) => { + const currencyDisplayNames = + Intl && "DisplayNames" in Intl + ? new Intl.DisplayNames(language, { + type: "currency", + fallback: "code", + }) + : undefined; + const options = CURRENCIES.map((currency) => ({ + value: currency, + label: `${ + currencyDisplayNames ? currencyDisplayNames.of(currency)! : currency + } (${curSymbol(currency, language)})`, + })); + options.sort((a, b) => + caseInsensitiveStringCompare(a.label, b.label, language) + ); + return options; + }); + + protected render() { + const options = this._getOptions(this.language); + + return html` + + ${options.map( + (option) => html` + ${option.label} + ` + )} + + `; + } + + static get styles(): CSSResultGroup { + return css` + ha-select { + width: 100%; + } + `; + } + + private _changed(ev): void { + const target = ev.target as HaSelect; + if (target.value === "" || target.value === this.value) { + return; + } + this.value = target.value; + fireEvent(this, "value-changed", { value: this.value }); + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-currency-picker": HaCurrencyPicker; + } +} diff --git a/src/components/ha-language-picker.ts b/src/components/ha-language-picker.ts index 618709c980..5d1ece061b 100644 --- a/src/components/ha-language-picker.ts +++ b/src/components/ha-language-picker.ts @@ -6,6 +6,7 @@ import { stopPropagation } from "../common/dom/stop_propagation"; import { formatLanguageCode } from "../common/language/format_language"; import { caseInsensitiveStringCompare } from "../common/string/compare"; import { FrontendLocaleData } from "../data/translation"; +import "../resources/intl-polyfill"; import { HomeAssistant } from "../types"; import "./ha-list-item"; import "./ha-select"; diff --git a/src/components/ha-timezone-picker.ts b/src/components/ha-timezone-picker.ts new file mode 100644 index 0000000000..8388f8ac8c --- /dev/null +++ b/src/components/ha-timezone-picker.ts @@ -0,0 +1,62 @@ +import timezones from "google-timezones-json"; +import { css, CSSResultGroup, html, LitElement } from "lit"; +import { customElement, property } from "lit/decorators"; +import { fireEvent } from "../common/dom/fire_event"; +import { stopPropagation } from "../common/dom/stop_propagation"; +import "./ha-list-item"; +import "./ha-select"; +import type { HaSelect } from "./ha-select"; + +@customElement("ha-timezone-picker") +export class HaTimeZonePicker extends LitElement { + @property() public value?: string; + + @property() public label?: string; + + @property({ type: Boolean }) public required = false; + + @property({ type: Boolean, reflect: true }) public disabled = false; + + protected render() { + return html` + + ${Object.entries(timezones).map( + ([key, value]) => + html`${value}` + )} + + `; + } + + static get styles(): CSSResultGroup { + return css` + ha-select { + width: 100%; + } + `; + } + + private _changed(ev): void { + const target = ev.target as HaSelect; + if (target.value === "" || target.value === this.value) { + return; + } + this.value = target.value; + fireEvent(this, "value-changed", { value: this.value }); + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-timezone-picker": HaTimeZonePicker; + } +} diff --git a/src/data/currency.ts b/src/data/currency.ts deleted file mode 100644 index d8ddf7933e..0000000000 --- a/src/data/currency.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const SYMBOL_TO_ISO = { - $: "USD", - "€": "EUR", - "¥": "JPY", - "£": "GBP", - "₽": "RUB", - "₹": "INR", -}; diff --git a/src/onboarding/onboarding-core-config.ts b/src/onboarding/onboarding-core-config.ts index 80a652ab94..9bf3be1ddb 100644 --- a/src/onboarding/onboarding-core-config.ts +++ b/src/onboarding/onboarding-core-config.ts @@ -11,29 +11,28 @@ import { customElement, property, query, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../common/dom/fire_event"; import type { LocalizeFunc } from "../common/translations/localize"; -import { createCountryListEl } from "../components/country-datalist"; -import { createCurrencyListEl } from "../components/currency-datalist"; import "../components/ha-alert"; +import "../components/ha-country-picker"; +import "../components/ha-currency-picker"; import "../components/ha-formfield"; +import "../components/ha-language-picker"; import "../components/ha-radio"; import type { HaRadio } from "../components/ha-radio"; import "../components/ha-textfield"; import type { HaTextField } from "../components/ha-textfield"; -import { createLanguageListEl } from "../components/language-datalist"; +import "../components/ha-timezone-picker"; import "../components/map/ha-locations-editor"; import type { HaLocationsEditor, MarkerLocation, } from "../components/map/ha-locations-editor"; -import { createTimezoneListEl } from "../components/timezone-datalist"; import { ConfigUpdateValues, detectCoreConfig, saveCoreConfig, } from "../data/core"; -import { SYMBOL_TO_ISO } from "../data/currency"; import { onboardCoreConfigStep } from "../data/onboarding"; -import type { ValueChangedEvent, HomeAssistant } from "../types"; +import type { HomeAssistant, ValueChangedEvent } from "../types"; import { getLocalLanguage } from "../util/common-translation"; const amsterdam: [number, number] = [52.3731339, 4.8903147]; @@ -58,9 +57,11 @@ class OnboardingCoreConfig extends LitElement { @state() private _currency?: ConfigUpdateValues["currency"]; - @state() private _timeZone?: string; + @state() private _timeZone? = + Intl.DateTimeFormat?.().resolvedOptions?.().timeZone; - @state() private _language?: ConfigUpdateValues["language"]; + @state() private _language: ConfigUpdateValues["language"] = + getLocalLanguage(); @state() private _country?: ConfigUpdateValues["country"]; @@ -127,45 +128,50 @@ class OnboardingCoreConfig extends LitElement {
- - + + + .disabled=${this._working} + @value-changed=${this._handleValueChanged} + > +
- + +
- - + + @@ -279,45 +286,6 @@ class OnboardingCoreConfig extends LitElement { this._save(ev); } }); - const tzInput = this.renderRoot.querySelector( - "[name=timeZone]" - ) as HaTextField; - tzInput.updateComplete.then(() => { - tzInput.renderRoot.appendChild(createTimezoneListEl()); - tzInput.formElement.setAttribute("list", "timezones"); - }); - - const curInput = this.renderRoot.querySelector( - "[name=currency]" - ) as HaTextField; - curInput.updateComplete.then(() => { - curInput.renderRoot.appendChild( - createCurrencyListEl(this.hass.locale.language) - ); - curInput.formElement.setAttribute("list", "currencies"); - }); - - const countryInput = this.renderRoot.querySelector( - "[name=country]" - ) as HaTextField; - countryInput.updateComplete.then(() => { - countryInput.renderRoot.appendChild( - createCountryListEl(this.hass.locale.language) - ); - - countryInput.formElement.setAttribute("list", "countries"); - }); - - const langInput = this.renderRoot.querySelector( - "[name=language]" - ) as HaTextField; - langInput.updateComplete.then(() => { - langInput.renderRoot.appendChild(createLanguageListEl(this.hass)); - langInput.renderRoot - .querySelector("#label") - ?.classList.add("mdc-floating-label--required"); - langInput.formElement.setAttribute("list", "languages"); - }); } private get _nameValue() { @@ -367,18 +335,14 @@ class OnboardingCoreConfig extends LitElement { ] ); + private _handleValueChanged(ev) { + const target = ev.currentTarget; + this[`_${target.getAttribute("name")}`] = ev.detail.value; + } + private _handleChange(ev: ValueChangedEvent) { const target = ev.currentTarget as HaTextField; - - let value = target.value; - - if (target.name === "currency" && value) { - if (value in SYMBOL_TO_ISO) { - value = SYMBOL_TO_ISO[value]; - } - } - - this[`_${target.name}`] = value; + this[`_${target.name}`] = target.value; } private _locationChanged(ev) { @@ -465,6 +429,7 @@ class OnboardingCoreConfig extends LitElement { flex-direction: row; margin: 0 -8px; align-items: center; + --ha-select-min-width: 100px; } .secondary { diff --git a/src/panels/config/core/ha-config-section-general.ts b/src/panels/config/core/ha-config-section-general.ts index 0d6e95dbc7..59899d0984 100644 --- a/src/panels/config/core/ha-config-section-general.ts +++ b/src/panels/config/core/ha-config-section-general.ts @@ -1,5 +1,4 @@ import "@material/mwc-list/mwc-list-item"; -import timezones from "google-timezones-json"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; @@ -8,12 +7,12 @@ import { stopPropagation } from "../../../common/dom/stop_propagation"; import { navigate } from "../../../common/navigate"; import "../../../components/buttons/ha-progress-button"; import type { HaProgressButton } from "../../../components/buttons/ha-progress-button"; -import { getCountryOptions } from "../../../components/country-datalist"; -import { getCurrencyOptions } from "../../../components/currency-datalist"; import "../../../components/ha-alert"; import "../../../components/ha-card"; import "../../../components/ha-checkbox"; import type { HaCheckbox } from "../../../components/ha-checkbox"; +import "../../../components/ha-country-picker"; +import "../../../components/ha-currency-picker"; import "../../../components/ha-formfield"; import "../../../components/ha-language-picker"; import "../../../components/ha-radio"; @@ -21,10 +20,10 @@ import type { HaRadio } from "../../../components/ha-radio"; import "../../../components/ha-select"; import "../../../components/ha-settings-row"; import "../../../components/ha-textfield"; +import "../../../components/ha-timezone-picker"; import "../../../components/map/ha-locations-editor"; import type { MarkerLocation } from "../../../components/map/ha-locations-editor"; import { ConfigUpdateValues, saveCoreConfig } from "../../../data/core"; -import { SYMBOL_TO_ISO } from "../../../data/currency"; import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-subpage"; import { haStyle } from "../../../resources/styles"; @@ -94,25 +93,16 @@ class HaConfigSectionGeneral extends LitElement { .value=${this._name} @change=${this._handleChange} > - - ${Object.keys(timezones).map( - (tz) => - html`${timezones[tz]}` - )} - +
- - ${getCurrencyOptions(this.hass.locale.language).map( - ({ value, label }) => - html` - ${label} - ` - )} +
- - ${getCountryOptions(this.hass.locale.language).map( - ({ value, label }) => - html` - ${label} - ` - )} + @value-changed=${this._handleValueChanged} + > @@ -319,26 +293,22 @@ class HaConfigSectionGeneral extends LitElement { this._country = this.hass.config.country; this._language = this.hass.config.language; this._elevation = this.hass.config.elevation; - this._timeZone = this.hass.config.time_zone || "Etc/GMT"; + this._timeZone = + this.hass.config.time_zone || + Intl.DateTimeFormat?.().resolvedOptions?.().timeZone || + "Etc/GMT"; this._name = this.hass.config.location_name; this._updateUnits = true; } - private _handleLanguageChange(ev) { - this._language = ev.detail.value; + private _handleValueChanged(ev) { + const target = ev.currentTarget; + this[`_${target.name}`] = ev.detail.value; } private _handleChange(ev) { const target = ev.currentTarget; - let value = target.value; - - if (target.name === "currency" && value) { - if (value in SYMBOL_TO_ISO) { - value = SYMBOL_TO_ISO[value]; - } - } - - this[`_${target.name}`] = value; + this[`_${target.name}`] = target.value; } private _unitSystemChanged(ev: CustomEvent) { diff --git a/src/resources/intl-polyfill.ts b/src/resources/intl-polyfill.ts index ec57044ecb..8b09aea77a 100644 --- a/src/resources/intl-polyfill.ts +++ b/src/resources/intl-polyfill.ts @@ -1,8 +1,8 @@ -import { shouldPolyfill as shouldPolyfillDateTime } from "@formatjs/intl-datetimeformat/lib/should-polyfill"; -import { shouldPolyfill as shouldPolyfillDisplayName } from "@formatjs/intl-displaynames/lib/should-polyfill"; -import { shouldPolyfill as shouldPolyfillLocale } from "@formatjs/intl-locale/lib/should-polyfill"; -import { shouldPolyfill as shouldPolyfillPluralRules } from "@formatjs/intl-pluralrules/lib/should-polyfill"; -import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/lib/should-polyfill"; +import { shouldPolyfill as shouldPolyfillDateTime } from "@formatjs/intl-datetimeformat/should-polyfill"; +import { shouldPolyfill as shouldPolyfillDisplayName } from "@formatjs/intl-displaynames/should-polyfill"; +import { shouldPolyfill as shouldPolyfillLocale } from "@formatjs/intl-locale/should-polyfill"; +import { shouldPolyfill as shouldPolyfillPluralRules } from "@formatjs/intl-pluralrules/should-polyfill"; +import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/should-polyfill"; import { getLocalLanguage } from "../util/common-translation"; import { polyfillLocaleData } from "./locale-data-polyfill"; @@ -14,11 +14,7 @@ const polyfillIntl = async () => { await import("@formatjs/intl-locale/polyfill-force"); } if (shouldPolyfillPluralRules(locale)) { - polyfills.push( - import("@formatjs/intl-pluralrules/polyfill-force").then( - () => import("@formatjs/intl-pluralrules/locale-data/en") - ) - ); + polyfills.push(import("@formatjs/intl-pluralrules/polyfill-force")); } if (shouldPolyfillRelativeTime(locale)) { polyfills.push(import("@formatjs/intl-relativetimeformat/polyfill-force")); @@ -31,11 +27,10 @@ const polyfillIntl = async () => { ); } if (shouldPolyfillDisplayName(locale)) { - polyfills.push( - import("@formatjs/intl-displaynames/polyfill-force").then( - () => import("@formatjs/intl-displaynames/locale-data/en") - ) - ); + polyfills.push(import("@formatjs/intl-displaynames/polyfill-force")); + } + if (polyfills.length === 0) { + return; } await Promise.all(polyfills).then(() => // Load the default language