diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 881d9ded40f0..42d7d54e6517 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -89,7 +89,7 @@ jobs:
env:
IS_TEST: "true"
- name: Upload bundle stats
- uses: actions/upload-artifact@v4.3.3
+ uses: actions/upload-artifact@v4.3.4
with:
name: frontend-bundle-stats
path: build/stats/*.json
@@ -113,7 +113,7 @@ jobs:
env:
IS_TEST: "true"
- name: Upload bundle stats
- uses: actions/upload-artifact@v4.3.3
+ uses: actions/upload-artifact@v4.3.4
with:
name: supervisor-bundle-stats
path: build/stats/*.json
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index 46d2063361ac..c095b89c2455 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -57,14 +57,14 @@ jobs:
run: tar -czvf translations.tar.gz translations
- name: Upload build artifacts
- uses: actions/upload-artifact@v4.3.3
+ uses: actions/upload-artifact@v4.3.4
with:
name: wheels
path: dist/home_assistant_frontend*.whl
if-no-files-found: error
- name: Upload translations
- uses: actions/upload-artifact@v4.3.3
+ uses: actions/upload-artifact@v4.3.4
with:
name: translations
path: translations.tar.gz
diff --git a/gallery/src/pages/misc/entity-state.ts b/gallery/src/pages/misc/entity-state.ts
index ab395b71a111..8d38fe9413d6 100644
--- a/gallery/src/pages/misc/entity-state.ts
+++ b/gallery/src/pages/misc/entity-state.ts
@@ -140,6 +140,9 @@ const ENTITIES: HassEntity[] = [
createEntity("climate.auto_preheating", "auto", undefined, {
hvac_action: "preheating",
}),
+ createEntity("climate.auto_defrosting", "auto", undefined, {
+ hvac_action: "defrosting",
+ }),
createEntity("climate.auto_heating", "auto", undefined, {
hvac_action: "heating",
}),
diff --git a/package.json b/package.json
index baf9e0afd94f..747e69769992 100644
--- a/package.json
+++ b/package.json
@@ -26,14 +26,14 @@
"type": "module",
"dependencies": {
"@babel/runtime": "7.24.7",
- "@braintree/sanitize-url": "7.0.3",
- "@codemirror/autocomplete": "6.16.3",
+ "@braintree/sanitize-url": "7.0.4",
+ "@codemirror/autocomplete": "6.17.0",
"@codemirror/commands": "6.6.0",
"@codemirror/language": "6.10.2",
"@codemirror/legacy-modes": "6.4.0",
"@codemirror/search": "6.5.6",
"@codemirror/state": "6.4.1",
- "@codemirror/view": "6.28.3",
+ "@codemirror/view": "6.28.4",
"@egjs/hammerjs": "2.0.17",
"@formatjs/intl-datetimeformat": "6.12.5",
"@formatjs/intl-displaynames": "6.6.8",
@@ -88,8 +88,8 @@
"@polymer/paper-tabs": "3.1.0",
"@polymer/polymer": "3.5.1",
"@thomasloven/round-slider": "0.6.0",
- "@vaadin/combo-box": "24.4.0",
- "@vaadin/vaadin-themable-mixin": "24.4.0",
+ "@vaadin/combo-box": "24.4.1",
+ "@vaadin/vaadin-themable-mixin": "24.4.1",
"@vibrant/color": "3.2.1-alpha.1",
"@vibrant/core": "3.2.1-alpha.1",
"@vibrant/quantizer-mmcq": "3.2.1-alpha.1",
@@ -118,7 +118,7 @@
"leaflet-draw": "1.0.4",
"lit": "2.8.0",
"luxon": "3.4.4",
- "marked": "12.0.2",
+ "marked": "13.0.2",
"memoize-one": "6.0.0",
"node-vibrant": "3.2.1-alpha.1",
"proxy-polyfill": "0.3.2",
@@ -205,7 +205,7 @@
"eslint-plugin-wc": "2.1.0",
"fancy-log": "2.0.0",
"fs-extra": "11.2.0",
- "glob": "10.4.2",
+ "glob": "10.4.3",
"gulp": "5.0.0",
"gulp-json-transform": "0.5.0",
"gulp-rename": "2.0.0",
diff --git a/pyproject.toml b/pyproject.toml
index 402d7c3b98b9..91ae7718f848 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
-version = "20240705.0"
+version = "20240710.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"
diff --git a/src/common/entity/get_states.ts b/src/common/entity/get_states.ts
index 24e9fa4a7eef..901cf95a8c52 100644
--- a/src/common/entity/get_states.ts
+++ b/src/common/entity/get_states.ts
@@ -125,6 +125,7 @@ const FIXED_DOMAIN_ATTRIBUTE_STATES = {
"off",
"idle",
"preheating",
+ "defrosting",
"heating",
"cooling",
"drying",
diff --git a/src/components/data-table/dialog-data-table-settings.ts b/src/components/data-table/dialog-data-table-settings.ts
index 1dfe8bbabf49..dd8a6f28888c 100644
--- a/src/components/data-table/dialog-data-table-settings.ts
+++ b/src/components/data-table/dialog-data-table-settings.ts
@@ -78,6 +78,8 @@ export class DialogDataTableSettings extends LitElement {
return nothing;
}
+ const localize = this._params.localizeFunc || this.hass.localize;
+
const columns = this._sortedColumns(
this._params.columns,
this._columnOrder,
@@ -90,7 +92,7 @@ export class DialogDataTableSettings extends LitElement {
@closed=${this.closeDialog}
.heading=${createCloseHeading(
this.hass,
- this.hass.localize("ui.components.data-table.settings.header")
+ localize("ui.components.data-table.settings.header")
)}
>
${this.hass.localize(
- "ui.components.data-table.settings.restore"
- )}${localize("ui.components.data-table.settings.restore")}
- ${this.hass.localize("ui.components.data-table.settings.done")}
+ ${localize("ui.components.data-table.settings.done")}
`;
diff --git a/src/components/data-table/show-dialog-data-table-settings.ts b/src/components/data-table/show-dialog-data-table-settings.ts
index b31e801acb11..954dd871bb26 100644
--- a/src/components/data-table/show-dialog-data-table-settings.ts
+++ b/src/components/data-table/show-dialog-data-table-settings.ts
@@ -1,4 +1,5 @@
import { fireEvent } from "../../common/dom/fire_event";
+import { LocalizeFunc } from "../../common/translations/localize";
import { DataTableColumnContainer } from "./ha-data-table";
export interface DataTableSettingsDialogParams {
@@ -9,6 +10,7 @@ export interface DataTableSettingsDialogParams {
) => void;
hiddenColumns?: string[];
columnOrder?: string[];
+ localizeFunc?: LocalizeFunc;
}
export const loadDataTableSettingsDialog = () =>
diff --git a/src/components/ha-selector/ha-selector-action.ts b/src/components/ha-selector/ha-selector-action.ts
index 2e203a62da4b..6ee30b5e675d 100644
--- a/src/components/ha-selector/ha-selector-action.ts
+++ b/src/components/ha-selector/ha-selector-action.ts
@@ -35,10 +35,6 @@ export class HaActionSelector extends LitElement {
display: block;
margin-bottom: 16px;
}
- :host([disabled]) ha-automation-action {
- opacity: var(--light-disabled-opacity);
- pointer-events: none;
- }
label {
display: block;
margin-bottom: 4px;
diff --git a/src/components/ha-selector/ha-selector-condition.ts b/src/components/ha-selector/ha-selector-condition.ts
index 756d43b1e4e3..721cf265ade0 100644
--- a/src/components/ha-selector/ha-selector-condition.ts
+++ b/src/components/ha-selector/ha-selector-condition.ts
@@ -35,10 +35,6 @@ export class HaConditionSelector extends LitElement {
display: block;
margin-bottom: 16px;
}
- :host([disabled]) ha-automation-condition {
- opacity: var(--light-disabled-opacity);
- pointer-events: none;
- }
label {
display: block;
margin-bottom: 4px;
diff --git a/src/components/ha-selector/ha-selector-trigger.ts b/src/components/ha-selector/ha-selector-trigger.ts
index 567a81c4d364..af4b814a76f9 100644
--- a/src/components/ha-selector/ha-selector-trigger.ts
+++ b/src/components/ha-selector/ha-selector-trigger.ts
@@ -35,10 +35,6 @@ export class HaTriggerSelector extends LitElement {
display: block;
margin-bottom: 16px;
}
- :host([disabled]) ha-automation-trigger {
- opacity: var(--light-disabled-opacity);
- pointer-events: none;
- }
label {
display: block;
margin-bottom: 4px;
diff --git a/src/data/climate.ts b/src/data/climate.ts
index 97a2557c71f7..30ee11d2b909 100644
--- a/src/data/climate.ts
+++ b/src/data/climate.ts
@@ -28,13 +28,14 @@ export type HvacMode = (typeof HVAC_MODES)[number];
export const CLIMATE_PRESET_NONE = "none";
export type HvacAction =
- | "off"
- | "preheating"
- | "heating"
| "cooling"
+ | "defrosting"
| "drying"
+ | "fan"
+ | "heating"
| "idle"
- | "fan";
+ | "off"
+ | "preheating";
export type ClimateEntity = HassEntityBase & {
attributes: HassEntityAttributeBase & {
@@ -89,12 +90,13 @@ export const compareClimateHvacModes = (mode1: HvacMode, mode2: HvacMode) =>
export const CLIMATE_HVAC_ACTION_TO_MODE: Record = {
cooling: "cool",
+ defrosting: "heat",
drying: "dry",
fan: "fan_only",
- preheating: "heat",
heating: "heat",
idle: "off",
off: "off",
+ preheating: "heat",
};
export const CLIMATE_HVAC_MODE_ICONS: Record = {
diff --git a/src/data/fan.ts b/src/data/fan.ts
index 5bcf32e75890..3320ff5353d8 100644
--- a/src/data/fan.ts
+++ b/src/data/fan.ts
@@ -17,6 +17,8 @@ export const enum FanEntityFeature {
OSCILLATE = 2,
DIRECTION = 4,
PRESET_MODE = 8,
+ TURN_OFF = 16,
+ TURN_ON = 32,
}
interface FanEntityAttributes extends HassEntityAttributeBase {
diff --git a/src/fake_data/entity_component_icons.ts b/src/fake_data/entity_component_icons.ts
index 90b580f977e7..242f301516a6 100644
--- a/src/fake_data/entity_component_icons.ts
+++ b/src/fake_data/entity_component_icons.ts
@@ -907,6 +907,7 @@ export const ENTITY_COMPONENT_ICONS: Record = {
idle: "mdi:clock-outline",
off: "mdi:power",
preheating: "mdi:heat-wave",
+ defrosting: "mdi:snowflake-melt",
},
},
preset_mode: {
diff --git a/src/layouts/hass-tabs-subpage-data-table.ts b/src/layouts/hass-tabs-subpage-data-table.ts
index 615fb2d5d056..79db1674e59a 100644
--- a/src/layouts/hass-tabs-subpage-data-table.ts
+++ b/src/layouts/hass-tabs-subpage-data-table.ts
@@ -638,6 +638,7 @@ export class HaTabsSubpageDataTable extends LitElement {
this.hiddenColumns = hiddenColumns;
fireEvent(this, "columns-changed", { columnOrder, hiddenColumns });
},
+ localizeFunc: this.localizeFunc,
});
}
diff --git a/src/panels/lovelace/cards/hui-card.ts b/src/panels/lovelace/cards/hui-card.ts
index ecc34ee4ca3d..34c47a691e93 100644
--- a/src/panels/lovelace/cards/hui-card.ts
+++ b/src/panels/lovelace/cards/hui-card.ts
@@ -23,7 +23,7 @@ declare global {
@customElement("hui-card")
export class HuiCard extends ReactiveElement {
- @property({ attribute: false }) public preview = false;
+ @property({ type: Boolean }) public preview = false;
@property({ attribute: false }) public isPanel = false;
diff --git a/src/panels/lovelace/cards/hui-entity-card.ts b/src/panels/lovelace/cards/hui-entity-card.ts
index 3e06cf7bf197..b042d7e7c354 100644
--- a/src/panels/lovelace/cards/hui-entity-card.ts
+++ b/src/panels/lovelace/cards/hui-entity-card.ts
@@ -136,7 +136,7 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
const colored = stateObj && this.getStateColor(stateObj, this._config);
const fixedFooter =
- this.layout === "grid" || this._footerElement !== undefined;
+ this.layout === "grid" && this._footerElement !== undefined;
return html`
): void {
assert(config, cardConfigStruct);
this._config = config;
}
- protected render() {
- if (!this.hass || !this._config) {
- return nothing;
- }
-
- const data = { square: true, ...this._config };
-
- return html`
-
- ${super.render()}
- `;
- }
-
- private _valueChanged(ev: CustomEvent): void {
- fireEvent(this, "config-changed", { config: ev.detail.value });
+ protected formData(): object {
+ return { square: true, ...this._config };
}
- private _computeLabelCallback = (schema: SchemaUnion) =>
+ protected _computeLabelCallback = (schema: SchemaUnion) =>
this.hass!.localize(`ui.panel.lovelace.editor.card.grid.${schema.name}`);
}
diff --git a/src/panels/lovelace/editor/config-elements/hui-stack-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-stack-card-editor.ts
index 0655f6dddb8b..c5e81164e134 100644
--- a/src/panels/lovelace/editor/config-elements/hui-stack-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-stack-card-editor.ts
@@ -20,6 +20,10 @@ import {
optional,
string,
} from "superstruct";
+import type {
+ HaFormSchema,
+ SchemaUnion,
+} from "../../../../components/ha-form/types";
import { storage } from "../../../../common/decorators/storage";
import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-icon-button";
@@ -46,6 +50,13 @@ const cardConfigStruct = assign(
})
);
+const SCHEMA = [
+ {
+ name: "title",
+ selector: { text: {} },
+ },
+] as const;
+
@customElement("hui-stack-card-editor")
export class HuiStackCardEditor
extends LitElement
@@ -71,6 +82,8 @@ export class HuiStackCardEditor
@state() protected _guiModeAvailable? = true;
+ protected _schema: readonly HaFormSchema[] = SCHEMA;
+
@query("hui-card-element-editor")
protected _cardEditorEl?: HuiCardElementEditor;
@@ -83,6 +96,10 @@ export class HuiStackCardEditor
this._cardEditorEl?.focusYamlEditor();
}
+ protected formData(): object {
+ return this._config!;
+ }
+
protected render() {
if (!this.hass || !this._config) {
return nothing;
@@ -93,6 +110,13 @@ export class HuiStackCardEditor
const isGuiMode = !this._cardEditorEl || this._GUImode;
return html`
+