Skip to content

Commit

Permalink
CountrySelector (#18035)
Browse files Browse the repository at this point in the history
  • Loading branch information
gjohansson-ST authored Oct 12, 2023
1 parent 6d1e923 commit 4c94ac5
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 18 deletions.
60 changes: 42 additions & 18 deletions src/components/ha-country-picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,37 +269,61 @@ export class HaCountryPicker extends LitElement {

@property() public label?: string;

@property() public countries?: string[];

@property() public helper?: 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;
@property({ type: Boolean }) public noSort = false;

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;
});
private _getOptions = memoizeOne(
(language?: string, countries?: string[]) => {
let options: { label: string; value: string }[] = [];
const countryDisplayNames =
Intl && "DisplayNames" in Intl
? new Intl.DisplayNames(language, {
type: "region",
fallback: "code",
})
: undefined;

if (countries) {
options = countries.map((country) => ({
value: country,
label: countryDisplayNames
? countryDisplayNames.of(country)!
: country,
}));
} else {
options = COUNTRIES.map((country) => ({
value: country,
label: countryDisplayNames
? countryDisplayNames.of(country)!
: country,
}));
}

if (!this.noSort) {
options.sort((a, b) =>
caseInsensitiveStringCompare(a.label, b.label, language)
);
}
return options;
}
);

protected render() {
const options = this._getOptions(this.language);
const options = this._getOptions(this.language, this.countries);

return html`
<ha-select
.label=${this.label}
.value=${this.value}
.required=${this.required}
.helper=${this.helper}
.disabled=${this.disabled}
@selected=${this._changed}
@closed=${stopPropagation}
Expand Down
4 changes: 4 additions & 0 deletions src/components/ha-form/compute-initial-ha-form-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ export const computeInitialHaFormData = (
typeof firstOption === "string" ? firstOption : firstOption.value;
data[field.name] = selector.select.multiple ? [val] : val;
}
} else if ("country" in selector) {
if (selector.country?.countries?.length) {
data[field.name] = selector.country.countries[0];
}
} else if ("duration" in selector) {
data[field.name] = {
hours: 0,
Expand Down
49 changes: 49 additions & 0 deletions src/components/ha-selector/ha-selector-country.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { CountrySelector } from "../../data/selector";
import { HomeAssistant } from "../../types";
import "../ha-country-picker";

@customElement("ha-selector-country")
export class HaCountrySelector extends LitElement {
@property() public hass!: HomeAssistant;

@property() public selector!: CountrySelector;

@property() public value?: any;

@property() public label?: string;

@property() public helper?: string;

@property({ type: Boolean }) public disabled = false;

@property({ type: Boolean }) public required = true;

protected render() {
return html`
<ha-country-picker
.hass=${this.hass}
.value=${this.value}
.label=${this.label}
.helper=${this.helper}
.countries=${this.selector.country?.countries}
.noSort=${this.selector.country?.no_sort}
.disabled=${this.disabled}
.required=${this.required}
></ha-country-picker>
`;
}

static styles = css`
ha-country-picker {
width: 100%;
}
`;
}

declare global {
interface HTMLElementTagNameMap {
"ha-selector-country": HaCountrySelector;
}
}
1 change: 1 addition & 0 deletions src/components/ha-selector/ha-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const LOAD_ELEMENTS = {
config_entry: () => import("./ha-selector-config-entry"),
conversation_agent: () => import("./ha-selector-conversation-agent"),
constant: () => import("./ha-selector-constant"),
country: () => import("./ha-selector-country"),
date: () => import("./ha-selector-date"),
datetime: () => import("./ha-selector-datetime"),
device: () => import("./ha-selector-device"),
Expand Down
8 changes: 8 additions & 0 deletions src/data/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type Selector =
| ConversationAgentSelector
| ConfigEntrySelector
| ConstantSelector
| CountrySelector
| DateSelector
| DateTimeSelector
| DeviceSelector
Expand Down Expand Up @@ -124,6 +125,13 @@ export interface ConstantSelector {
} | null;
}

export interface CountrySelector {
country: {
countries: string[];
no_sort?: boolean;
} | null;
}

export interface DateSelector {
// eslint-disable-next-line @typescript-eslint/ban-types
date: {} | null;
Expand Down
3 changes: 3 additions & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,9 @@
"conversation_agent": "Conversation agent",
"none": "None"
},
"country-picker": {
"country": "Country"
},
"pipeline-picker": {
"pipeline": "Assistant",
"preferred": "Preferred assistant ({preferred})",
Expand Down

0 comments on commit 4c94ac5

Please sign in to comment.