diff --git a/src/components/ha-form/ha-form-conditional.ts b/src/components/ha-form/ha-form-conditional.ts
new file mode 100644
index 0000000000..03c2305880
--- /dev/null
+++ b/src/components/ha-form/ha-form-conditional.ts
@@ -0,0 +1,74 @@
+import {
+ css,
+ CSSResultGroup,
+ html,
+ LitElement,
+ nothing,
+ PropertyValues,
+} from "lit";
+import { customElement, property } from "lit/decorators";
+import type { HomeAssistant } from "../../types";
+import "./ha-form";
+import type {
+ HaFormDataContainer,
+ HaFormElement,
+ HaFormConditionalSchema,
+ HaFormSchema,
+} from "./types";
+
+@customElement("ha-form-conditional")
+export class HaFormConditional extends LitElement implements HaFormElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false }) public data!: HaFormDataContainer;
+
+ @property({ attribute: false }) public schema!: HaFormConditionalSchema;
+
+ @property({ type: Boolean }) public disabled = false;
+
+ @property() public computeLabel?: (
+ schema: HaFormSchema,
+ data?: HaFormDataContainer
+ ) => string;
+
+ @property() public computeHelper?: (schema: HaFormSchema) => string;
+
+ protected updated(changedProps: PropertyValues): void {
+ if (changedProps.has("schema") || changedProps.has("data")) {
+ this.toggleAttribute("hidden", !this.schema.condition(this.data));
+ }
+ }
+
+ protected render() {
+ if (!this.schema.condition(this.data)) {
+ return nothing;
+ }
+ return html`
+
+ `;
+ }
+
+ static get styles(): CSSResultGroup {
+ return css`
+ :host([hidden]) {
+ display: none !important;
+ }
+ :host ha-form {
+ display: block;
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ha-form-conditional": HaFormConditional;
+ }
+}
diff --git a/src/components/ha-form/ha-form.ts b/src/components/ha-form/ha-form.ts
index 3062c2317d..a583b4cde1 100644
--- a/src/components/ha-form/ha-form.ts
+++ b/src/components/ha-form/ha-form.ts
@@ -21,6 +21,7 @@ const LOAD_ELEMENTS = {
float: () => import("./ha-form-float"),
grid: () => import("./ha-form-grid"),
expandable: () => import("./ha-form-expandable"),
+ conditional: () => import("./ha-form-conditional"),
integer: () => import("./ha-form-integer"),
multi_select: () => import("./ha-form-multi_select"),
positive_time_period_dict: () =>
@@ -189,12 +190,13 @@ export class HaForm extends LitElement implements HaFormElement {
static get styles(): CSSResultGroup {
return css`
+ .root {
+ display: grid;
+ row-gap: 24px;
+ }
.root > * {
display: block;
}
- .root > *:not([own-margin]):not(:last-child) {
- margin-bottom: 24px;
- }
ha-alert[own-margin] {
margin-bottom: 4px;
}
diff --git a/src/components/ha-form/types.ts b/src/components/ha-form/types.ts
index 287b904780..b76d5a6bb5 100644
--- a/src/components/ha-form/types.ts
+++ b/src/components/ha-form/types.ts
@@ -13,7 +13,8 @@ export type HaFormSchema =
| HaFormTimeSchema
| HaFormSelector
| HaFormGridSchema
- | HaFormExpandableSchema;
+ | HaFormExpandableSchema
+ | HaFormConditionalSchema;
export interface HaFormBaseSchema {
name: string;
@@ -47,6 +48,13 @@ export interface HaFormExpandableSchema extends HaFormBaseSchema {
schema: readonly HaFormSchema[];
}
+export interface HaFormConditionalSchema extends HaFormBaseSchema {
+ type: "conditional";
+ name: "";
+ condition: (data: HaFormDataContainer) => boolean;
+ schema: readonly HaFormSchema[];
+}
+
export interface HaFormSelector extends HaFormBaseSchema {
type?: never;
selector: Selector;
@@ -99,7 +107,10 @@ export interface HaFormTimeSchema extends HaFormBaseSchema {
export type SchemaUnion<
SchemaArray extends readonly HaFormSchema[],
Schema = SchemaArray[number]
-> = Schema extends HaFormGridSchema | HaFormExpandableSchema
+> = Schema extends
+ | HaFormGridSchema
+ | HaFormExpandableSchema
+ | HaFormConditionalSchema
? SchemaUnion
: Schema;
diff --git a/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts
index 06f173b9b4..4e63a1749b 100644
--- a/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts
@@ -1,6 +1,5 @@
import { html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
-import memoizeOne from "memoize-one";
import {
array,
assert,
@@ -13,7 +12,10 @@ import {
} from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-form/ha-form";
-import type { SchemaUnion } from "../../../../components/ha-form/types";
+import type {
+ HaFormSchema,
+ SchemaUnion,
+} from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
import type { GaugeCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
@@ -41,6 +43,75 @@ const cardConfigStruct = assign(
})
);
+const SCHEMA = [
+ {
+ name: "entity",
+ selector: {
+ entity: {
+ domain: ["counter", "input_number", "number", "sensor"],
+ },
+ },
+ },
+ {
+ name: "",
+ type: "grid",
+ schema: [
+ { name: "name", selector: { text: {} } },
+ { name: "unit", selector: { text: {} } },
+ ],
+ },
+ { name: "theme", selector: { theme: {} } },
+ {
+ name: "",
+ type: "grid",
+ schema: [
+ {
+ name: "min",
+ default: DEFAULT_MIN,
+ selector: { number: { mode: "box" } },
+ },
+ {
+ name: "max",
+ default: DEFAULT_MAX,
+ selector: { number: { mode: "box" } },
+ },
+ ],
+ },
+ {
+ name: "",
+ type: "grid",
+ schema: [
+ { name: "needle", selector: { boolean: {} } },
+ { name: "show_severity", selector: { boolean: {} } },
+ ],
+ },
+ {
+ name: "",
+ type: "conditional",
+ condition: (data) => !!data.show_severity,
+ schema: [
+ {
+ name: "severity",
+ type: "grid",
+ schema: [
+ {
+ name: "green",
+ selector: { number: { mode: "box" } },
+ },
+ {
+ name: "yellow",
+ selector: { number: { mode: "box" } },
+ },
+ {
+ name: "red",
+ selector: { number: { mode: "box" } },
+ },
+ ],
+ },
+ ],
+ },
+] as const satisfies readonly HaFormSchema[];
+
@customElement("hui-gauge-card-editor")
export class HuiGaugeCardEditor
extends LitElement
@@ -55,81 +126,11 @@ export class HuiGaugeCardEditor
this._config = config;
}
- private _schema = memoizeOne(
- (showSeverity: boolean) =>
- [
- {
- name: "entity",
- selector: {
- entity: {
- domain: ["counter", "input_number", "number", "sensor"],
- },
- },
- },
- {
- name: "",
- type: "grid",
- schema: [
- { name: "name", selector: { text: {} } },
- { name: "unit", selector: { text: {} } },
- ],
- },
- { name: "theme", selector: { theme: {} } },
- {
- name: "",
- type: "grid",
- schema: [
- {
- name: "min",
- default: DEFAULT_MIN,
- selector: { number: { mode: "box" } },
- },
- {
- name: "max",
- default: DEFAULT_MAX,
- selector: { number: { mode: "box" } },
- },
- ],
- },
- {
- name: "",
- type: "grid",
- schema: [
- { name: "needle", selector: { boolean: {} } },
- { name: "show_severity", selector: { boolean: {} } },
- ],
- },
- ...(showSeverity
- ? ([
- {
- name: "severity",
- type: "grid",
- schema: [
- {
- name: "green",
- selector: { number: { mode: "box" } },
- },
- {
- name: "yellow",
- selector: { number: { mode: "box" } },
- },
- {
- name: "red",
- selector: { number: { mode: "box" } },
- },
- ],
- },
- ] as const)
- : []),
- ] as const
- );
-
protected render() {
if (!this.hass || !this._config) {
return nothing;
}
- const schema = this._schema(this._config!.severity !== undefined);
const data = {
show_severity: this._config!.severity !== undefined,
...this._config,
@@ -139,7 +140,7 @@ export class HuiGaugeCardEditor
@@ -153,7 +154,7 @@ export class HuiGaugeCardEditor
config = {
...config,
severity: {
- green: config.green || config.severity?.green || 0,
+ green: config.green || config.severity?.green,
yellow: config.yellow || config.severity?.yellow || 0,
red: config.red || config.severity?.red || 0,
},
@@ -170,9 +171,7 @@ export class HuiGaugeCardEditor
fireEvent(this, "config-changed", { config });
}
- private _computeLabelCallback = (
- schema: SchemaUnion>
- ) => {
+ private _computeLabelCallback = (schema: SchemaUnion) => {
switch (schema.name) {
case "name":
return this.hass!.localize(