mirror of
https://github.com/home-assistant/frontend.git
synced 2026-04-17 15:45:43 +01:00
Cover tilt presets card feature (#29989)
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
import type { PropertyValues, TemplateResult } from "lit";
|
||||
import { html, LitElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { computeCssColor } from "../../../common/color/compute-color";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { stateColorCss } from "../../../common/entity/state_color";
|
||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||
import "../../../components/ha-control-select";
|
||||
import type { CoverEntity } from "../../../data/cover";
|
||||
import { CoverEntityFeature } from "../../../data/cover";
|
||||
import { UNAVAILABLE } from "../../../data/entity/entity";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
|
||||
import { cardFeatureStyles } from "./common/card-feature-styles";
|
||||
import type {
|
||||
CoverTiltPresetCardFeatureConfig,
|
||||
LovelaceCardFeatureContext,
|
||||
} from "./types";
|
||||
|
||||
export const DEFAULT_COVER_TILT_PRESETS = [0, 25, 75, 100];
|
||||
|
||||
export const supportsCoverTiltPresetCardFeature = (
|
||||
hass: HomeAssistant,
|
||||
context: LovelaceCardFeatureContext
|
||||
) => {
|
||||
const stateObj = context.entity_id
|
||||
? hass.states[context.entity_id]
|
||||
: undefined;
|
||||
if (!stateObj) return false;
|
||||
const domain = computeDomain(stateObj.entity_id);
|
||||
return (
|
||||
domain === "cover" &&
|
||||
supportsFeature(stateObj, CoverEntityFeature.SET_TILT_POSITION)
|
||||
);
|
||||
};
|
||||
|
||||
@customElement("hui-cover-tilt-preset-card-feature")
|
||||
class HuiCoverTiltPresetCardFeature
|
||||
extends LitElement
|
||||
implements LovelaceCardFeature
|
||||
{
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public context?: LovelaceCardFeatureContext;
|
||||
|
||||
@property({ attribute: false }) public color?: string;
|
||||
|
||||
@state() private _config?: CoverTiltPresetCardFeatureConfig;
|
||||
|
||||
@state() private _currentTiltPosition?: number;
|
||||
|
||||
private get _stateObj() {
|
||||
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||
return undefined;
|
||||
}
|
||||
return this.hass.states[this.context.entity_id!] as CoverEntity | undefined;
|
||||
}
|
||||
|
||||
static getStubConfig(): CoverTiltPresetCardFeatureConfig {
|
||||
return {
|
||||
type: "cover-tilt-preset",
|
||||
positions: DEFAULT_COVER_TILT_PRESETS,
|
||||
};
|
||||
}
|
||||
|
||||
public static async getConfigElement(): Promise<LovelaceCardFeatureEditor> {
|
||||
await import("../editor/config-elements/hui-cover-tilt-preset-card-feature-editor");
|
||||
return document.createElement("hui-cover-tilt-preset-card-feature-editor");
|
||||
}
|
||||
|
||||
public setConfig(config: CoverTiltPresetCardFeatureConfig): void {
|
||||
if (!config) {
|
||||
throw new Error("Invalid configuration");
|
||||
}
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
protected willUpdate(changedProp: PropertyValues): void {
|
||||
super.willUpdate(changedProp);
|
||||
if (
|
||||
(changedProp.has("hass") || changedProp.has("context")) &&
|
||||
this._stateObj
|
||||
) {
|
||||
const oldHass = changedProp.get("hass") as HomeAssistant | undefined;
|
||||
const oldStateObj = oldHass?.states[this.context!.entity_id!];
|
||||
if (oldStateObj !== this._stateObj) {
|
||||
this._currentTiltPosition =
|
||||
this._stateObj.attributes.current_tilt_position ?? undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async _valueChanged(
|
||||
ev: CustomEvent<{ value?: string; item?: { value: string } }>
|
||||
) {
|
||||
const value = ev.detail.value ?? ev.detail.item?.value;
|
||||
if (value == null) return;
|
||||
|
||||
const tiltPosition = Number(value);
|
||||
if (isNaN(tiltPosition)) return;
|
||||
|
||||
const oldTiltPosition = this._stateObj!.attributes.current_tilt_position;
|
||||
if (tiltPosition === oldTiltPosition) return;
|
||||
|
||||
this._currentTiltPosition = tiltPosition;
|
||||
try {
|
||||
await this.hass!.callService("cover", "set_cover_tilt_position", {
|
||||
entity_id: this._stateObj!.entity_id,
|
||||
tilt_position: tiltPosition,
|
||||
});
|
||||
} catch (_err) {
|
||||
this._currentTiltPosition = oldTiltPosition ?? undefined;
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | null {
|
||||
if (
|
||||
!this._config ||
|
||||
!this.hass ||
|
||||
!this.context ||
|
||||
!this._stateObj ||
|
||||
!supportsCoverTiltPresetCardFeature(this.hass, this.context)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const positions = this._config.positions ?? DEFAULT_COVER_TILT_PRESETS;
|
||||
|
||||
const options = positions.map((position) => ({
|
||||
value: String(position),
|
||||
label: `${position}%`,
|
||||
}));
|
||||
|
||||
const currentValue =
|
||||
this._currentTiltPosition != null
|
||||
? String(this._currentTiltPosition)
|
||||
: undefined;
|
||||
|
||||
const color = this.color
|
||||
? computeCssColor(this.color)
|
||||
: stateColorCss(this._stateObj);
|
||||
|
||||
const style = {
|
||||
"--feature-color": color,
|
||||
};
|
||||
|
||||
return html`
|
||||
<ha-control-select
|
||||
style=${styleMap(style)}
|
||||
.options=${options}
|
||||
.value=${currentValue}
|
||||
@value-changed=${this._valueChanged}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.features.types.cover-tilt-preset.label"
|
||||
)}
|
||||
.disabled=${this._stateObj!.state === UNAVAILABLE}
|
||||
>
|
||||
</ha-control-select>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return cardFeatureStyles;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-cover-tilt-preset-card-feature": HuiCoverTiltPresetCardFeature;
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,11 @@ export interface CoverPositionPresetCardFeatureConfig {
|
||||
positions?: number[];
|
||||
}
|
||||
|
||||
export interface CoverTiltPresetCardFeatureConfig {
|
||||
type: "cover-tilt-preset";
|
||||
positions?: number[];
|
||||
}
|
||||
|
||||
export interface LightBrightnessCardFeatureConfig {
|
||||
type: "light-brightness";
|
||||
}
|
||||
@@ -252,6 +257,7 @@ export type LovelaceCardFeatureConfig =
|
||||
| CoverOpenCloseCardFeatureConfig
|
||||
| CoverPositionCardFeatureConfig
|
||||
| CoverPositionPresetCardFeatureConfig
|
||||
| CoverTiltPresetCardFeatureConfig
|
||||
| CoverTiltPositionCardFeatureConfig
|
||||
| CoverTiltCardFeatureConfig
|
||||
| DateSetCardFeatureConfig
|
||||
|
||||
@@ -10,6 +10,7 @@ import "../card-features/hui-cover-open-close-card-feature";
|
||||
import "../card-features/hui-cover-position-card-feature";
|
||||
import "../card-features/hui-cover-position-preset-card-feature";
|
||||
import "../card-features/hui-cover-tilt-card-feature";
|
||||
import "../card-features/hui-cover-tilt-preset-card-feature";
|
||||
import "../card-features/hui-cover-tilt-position-card-feature";
|
||||
import "../card-features/hui-date-set-card-feature";
|
||||
import "../card-features/hui-fan-direction-card-feature";
|
||||
@@ -60,6 +61,7 @@ const TYPES = new Set<LovelaceCardFeatureConfig["type"]>([
|
||||
"cover-open-close",
|
||||
"cover-position",
|
||||
"cover-position-preset",
|
||||
"cover-tilt-preset",
|
||||
"cover-tilt-position",
|
||||
"cover-tilt",
|
||||
"date-set",
|
||||
|
||||
@@ -38,6 +38,7 @@ import { supportsCoverOpenCloseCardFeature } from "../../card-features/hui-cover
|
||||
import { supportsCoverPositionCardFeature } from "../../card-features/hui-cover-position-card-feature";
|
||||
import { supportsCoverPositionPresetCardFeature } from "../../card-features/hui-cover-position-preset-card-feature";
|
||||
import { supportsCoverTiltCardFeature } from "../../card-features/hui-cover-tilt-card-feature";
|
||||
import { supportsCoverTiltPresetCardFeature } from "../../card-features/hui-cover-tilt-preset-card-feature";
|
||||
import { supportsCoverTiltPositionCardFeature } from "../../card-features/hui-cover-tilt-position-card-feature";
|
||||
import { supportsDateSetCardFeature } from "../../card-features/hui-date-set-card-feature";
|
||||
import { supportsFanDirectionCardFeature } from "../../card-features/hui-fan-direction-card-feature";
|
||||
@@ -92,6 +93,7 @@ const UI_FEATURE_TYPES = [
|
||||
"cover-open-close",
|
||||
"cover-position",
|
||||
"cover-position-preset",
|
||||
"cover-tilt-preset",
|
||||
"cover-tilt-position",
|
||||
"cover-tilt",
|
||||
"date-set",
|
||||
@@ -136,6 +138,7 @@ const EDITABLES_FEATURE_TYPES = new Set<UiFeatureTypes>([
|
||||
"climate-swing-horizontal-modes",
|
||||
"counter-actions",
|
||||
"cover-position-preset",
|
||||
"cover-tilt-preset",
|
||||
"fan-preset-modes",
|
||||
"humidifier-modes",
|
||||
"lawn-mower-commands",
|
||||
@@ -166,6 +169,7 @@ const SUPPORTS_FEATURE_TYPES: Record<
|
||||
"cover-open-close": supportsCoverOpenCloseCardFeature,
|
||||
"cover-position": supportsCoverPositionCardFeature,
|
||||
"cover-position-preset": supportsCoverPositionPresetCardFeature,
|
||||
"cover-tilt-preset": supportsCoverTiltPresetCardFeature,
|
||||
"cover-tilt-position": supportsCoverTiltPositionCardFeature,
|
||||
"cover-tilt": supportsCoverTiltCardFeature,
|
||||
"date-set": supportsDateSetCardFeature,
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import "../../../../components/ha-multi-textfield";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { DEFAULT_COVER_TILT_PRESETS } from "../../card-features/hui-cover-tilt-preset-card-feature";
|
||||
import type {
|
||||
CoverTiltPresetCardFeatureConfig,
|
||||
LovelaceCardFeatureContext,
|
||||
} from "../../card-features/types";
|
||||
import type { LovelaceCardFeatureEditor } from "../../types";
|
||||
|
||||
@customElement("hui-cover-tilt-preset-card-feature-editor")
|
||||
export class HuiCoverTiltPresetCardFeatureEditor
|
||||
extends LitElement
|
||||
implements LovelaceCardFeatureEditor
|
||||
{
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public context?: LovelaceCardFeatureContext;
|
||||
|
||||
@state() private _config?: CoverTiltPresetCardFeatureConfig;
|
||||
|
||||
public setConfig(config: CoverTiltPresetCardFeatureConfig): void {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this.hass || !this._config) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const positions = this._config.positions ?? DEFAULT_COVER_TILT_PRESETS;
|
||||
|
||||
const stringValues = positions.map((p) => String(p));
|
||||
|
||||
return html`
|
||||
<ha-multi-textfield
|
||||
.hass=${this.hass}
|
||||
.value=${stringValues}
|
||||
.max=${6}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.features.types.cover-tilt-preset.position"
|
||||
)}
|
||||
.inputType=${"number"}
|
||||
.inputSuffix=${"%"}
|
||||
.addLabel=${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.features.types.cover-tilt-preset.add_position"
|
||||
)}
|
||||
.removeLabel=${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.features.types.cover-tilt-preset.remove_position"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-multi-textfield>
|
||||
`;
|
||||
}
|
||||
|
||||
private _valueChanged(ev: CustomEvent): void {
|
||||
ev.stopPropagation();
|
||||
const stringValues = ev.detail.value as (string | null | undefined)[];
|
||||
const positions = stringValues
|
||||
.filter((v): v is string => !!v && !isNaN(Number(v)))
|
||||
.map((v) => Math.min(100, Math.max(0, Number(v))));
|
||||
|
||||
const config: CoverTiltPresetCardFeatureConfig = {
|
||||
...this._config!,
|
||||
positions,
|
||||
};
|
||||
|
||||
this._config = config;
|
||||
|
||||
fireEvent(this, "config-changed", { config });
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-cover-tilt-preset-card-feature-editor": HuiCoverTiltPresetCardFeatureEditor;
|
||||
}
|
||||
}
|
||||
@@ -9359,6 +9359,12 @@
|
||||
"cover-tilt": {
|
||||
"label": "Cover tilt"
|
||||
},
|
||||
"cover-tilt-preset": {
|
||||
"label": "Cover tilt preset",
|
||||
"position": "Position",
|
||||
"add_position": "Add position",
|
||||
"remove_position": "Remove position"
|
||||
},
|
||||
"cover-tilt-position": {
|
||||
"label": "Cover tilt position"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user