Skip to content
Merged
73 changes: 73 additions & 0 deletions src/components/ha-form/ha-form-grid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import "./ha-form";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import type {
HaFormGridSchema,
HaFormDataContainer,
HaFormElement,
HaFormSchema,
} from "./types";
import type { HomeAssistant } from "../../types";

@customElement("ha-form-grid")
export class HaFormGrid extends LitElement implements HaFormElement {
@property({ attribute: false }) public hass!: HomeAssistant;

@property({ attribute: false }) public data!: HaFormDataContainer;

@property({ attribute: false }) public schema!: HaFormGridSchema;

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

@property() public computeLabel?: (
schema: HaFormSchema,
data?: HaFormDataContainer
) => string;

@property() public computeHelper?: (schema: HaFormSchema) => string;

protected firstUpdated() {
this.setAttribute("own-margin", "");
}

protected render(): TemplateResult {
return html`
${this.schema.schema.map(
(item) =>
html`
<ha-form
.hass=${this.hass}
.data=${this.data}
.schema=${[item]}
.disabled=${this.disabled}
.computeLabel=${this.computeLabel}
.computeHelper=${this.computeHelper}
></ha-form>
`
)}
`;
}

static get styles(): CSSResultGroup {
return css`
:host {
display: grid !important;
grid-template-columns: repeat(
var(--form-grid-column-count, auto-fit),
minmax(var(--form-grid-min-width, 200px), 1fr)
);
grid-gap: 8px;
}
:host > ha-form {
display: block;
margin-bottom: 24px;
}
`;
}
}

declare global {
interface HTMLElementTagNameMap {
"ha-form-grid": HaFormGrid;
}
}
30 changes: 23 additions & 7 deletions src/components/ha-form/ha-form.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property } from "lit/decorators";
import { dynamicElement } from "../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../common/dom/fire_event";
import "../ha-alert";
import "./ha-form-boolean";
import "./ha-form-constant";
import "./ha-form-grid";
import "./ha-form-float";
import "./ha-form-integer";
import "./ha-form-multi_select";
Expand All @@ -14,17 +22,18 @@ import "./ha-form-string";
import { HaFormElement, HaFormDataContainer, HaFormSchema } from "./types";
import { HomeAssistant } from "../../types";

const getValue = (obj, item) => (obj ? obj[item.name] : null);
const getValue = (obj, item) =>
obj ? (!item.name ? obj : obj[item.name]) : null;

let selectorImported = false;

@customElement("ha-form")
export class HaForm extends LitElement implements HaFormElement {
@property() public hass!: HomeAssistant;
@property({ attribute: false }) public hass!: HomeAssistant;

@property() public data!: HaFormDataContainer;
@property({ attribute: false }) public data!: HaFormDataContainer;

@property() public schema!: HaFormSchema[];
@property({ attribute: false }) public schema!: HaFormSchema[];

@property() public error?: Record<string, string>;

Expand Down Expand Up @@ -64,7 +73,7 @@ export class HaForm extends LitElement implements HaFormElement {
}
}

protected render() {
protected render(): TemplateResult {
return html`
<div class="root">
${this.error && this.error.base
Expand Down Expand Up @@ -101,6 +110,9 @@ export class HaForm extends LitElement implements HaFormElement {
data: getValue(this.data, item),
label: this._computeLabel(item, this.data),
disabled: this.disabled,
hass: this.hass,
computeLabel: this.computeLabel,
computeHelper: this.computeHelper,
})}
`;
})}
Expand All @@ -115,8 +127,12 @@ export class HaForm extends LitElement implements HaFormElement {
ev.stopPropagation();
const schema = (ev.target as HaFormElement).schema as HaFormSchema;

const newValue = !schema.name
? ev.detail.value
: { [schema.name]: ev.detail.value };

fireEvent(this, "value-changed", {
value: { ...this.data, [schema.name]: ev.detail.value },
value: { ...this.data, ...newValue },
});
});
return root;
Expand Down
9 changes: 8 additions & 1 deletion src/components/ha-form/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export type HaFormSchema =
| HaFormSelectSchema
| HaFormMultiSelectSchema
| HaFormTimeSchema
| HaFormSelector;
| HaFormSelector
| HaFormGridSchema;

export interface HaFormBaseSchema {
name: string;
Expand All @@ -25,6 +26,12 @@ export interface HaFormBaseSchema {
};
}

export interface HaFormGridSchema extends HaFormBaseSchema {
type: "grid";
name: "";
schema: HaFormSchema[];
}

export interface HaFormSelector extends HaFormBaseSchema {
type?: never;
selector: Selector;
Expand Down
5 changes: 4 additions & 1 deletion src/components/ha-selector/ha-selector-boolean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ export class HaBooleanSelector extends LitElement {

static get styles(): CSSResultGroup {
return css`
:host {
height: 56px;
display: flex;
}
ha-formfield {
width: 100%;
margin: 16px 0;
--mdc-typography-body2-font-size: 1em;
}
`;
Expand Down
2 changes: 2 additions & 0 deletions src/components/ha-selector/ha-selector-icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export class HaIconSelector extends LitElement {
<ha-icon-picker
.label=${this.label}
.value=${this.value}
.fallbackPath=${this.selector.icon.fallbackPath}
.placeholder=${this.selector.icon.placeholder}
@value-changed=${this._valueChanged}
></ha-icon-picker>
`;
Expand Down
34 changes: 34 additions & 0 deletions src/components/ha-selector/ha-selector-theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import "../../panels/lovelace/components/hui-theme-select-editor";
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import type { HomeAssistant } from "../../types";
import type { ThemeSelector } from "../../data/selector";

@customElement("ha-selector-theme")
export class HaThemeSelector extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;

@property({ attribute: false }) public selector!: ThemeSelector;

@property() public value?: string;

@property() public label?: string;

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

protected render() {
return html`
<hui-theme-select-editor
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not use a hui element here, but let's do that in a later PR

.hass=${this.hass}
.value=${this.value}
.label=${this.label}
></hui-theme-select-editor>
`;
}
}

declare global {
interface HTMLElementTagNameMap {
"ha-selector-theme": HaThemeSelector;
}
}
5 changes: 3 additions & 2 deletions src/components/ha-selector/ha-selector.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { dynamicElement } from "../../common/dom/dynamic-element-directive";
import { Selector } from "../../data/selector";
import { HomeAssistant } from "../../types";
import type { Selector } from "../../data/selector";
import type { HomeAssistant } from "../../types";
import "./ha-selector-action";
import "./ha-selector-addon";
import "./ha-selector-area";
Expand All @@ -19,6 +19,7 @@ import "./ha-selector-text";
import "./ha-selector-time";
import "./ha-selector-icon";
import "./ha-selector-media";
import "./ha-selector-theme";

@customElement("ha-selector")
export class HaSelector extends LitElement {
Expand Down
12 changes: 10 additions & 2 deletions src/data/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export type Selector =
| ObjectSelector
| SelectSelector
| IconSelector
| MediaSelector;
| MediaSelector
| ThemeSelector;

export interface EntitySelector {
entity: {
Expand Down Expand Up @@ -147,8 +148,15 @@ export interface SelectSelector {
}

export interface IconSelector {
icon: {
placeholder?: string;
fallbackPath?: string;
};
}

export interface ThemeSelector {
// eslint-disable-next-line @typescript-eslint/ban-types
icon: {};
theme: {};
}

export interface MediaSelector {
Expand Down
4 changes: 2 additions & 2 deletions src/panels/lovelace/components/hui-theme-select-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class HuiThemeSelectEditor extends LitElement {
.sort()
.map(
(theme) =>
html` <mwc-list-item .value=${theme}>${theme}</mwc-list-item> `
html`<mwc-list-item .value=${theme}>${theme}</mwc-list-item>`
)}
</mwc-select>
`;
Expand All @@ -57,7 +57,7 @@ export class HuiThemeSelectEditor extends LitElement {
if (!this.hass || ev.target.value === "") {
return;
}
this.value = ev.target.value === "remove" ? "" : ev.target.selected;
this.value = ev.target.value === "remove" ? "" : ev.target.value;
fireEvent(this, "value-changed", { value: this.value });
}
}
Expand Down
Loading