mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-19 19:07:23 +00:00
Use switch and add support for light, fan and valve (#24426)
* Use switch and add support for light and fan * Add icon per domains
This commit is contained in:
parent
51193cf441
commit
8848911b34
@ -3,8 +3,8 @@ import {
|
||||
mdiBrightness6,
|
||||
mdiCreation,
|
||||
mdiFileWordBox,
|
||||
mdiLightbulb,
|
||||
mdiLightbulbOff,
|
||||
mdiLightbulbOn,
|
||||
mdiPower,
|
||||
} from "@mdi/js";
|
||||
import type { CSSResultGroup, PropertyValues } from "lit";
|
||||
@ -12,8 +12,8 @@ import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||
import "../../../components/ha-attributes";
|
||||
import "../../../components/ha-attribute-icon";
|
||||
import "../../../components/ha-attributes";
|
||||
import "../../../components/ha-control-select-menu";
|
||||
import "../../../components/ha-icon-button-group";
|
||||
import "../../../components/ha-icon-button-toggle";
|
||||
@ -121,7 +121,7 @@ class MoreInfoLight extends LitElement {
|
||||
<ha-state-control-toggle
|
||||
.stateObj=${this.stateObj}
|
||||
.hass=${this.hass}
|
||||
.iconPathOn=${mdiLightbulb}
|
||||
.iconPathOn=${mdiLightbulbOn}
|
||||
.iconPathOff=${mdiLightbulbOff}
|
||||
></ha-state-control-toggle>
|
||||
`
|
||||
|
@ -27,4 +27,12 @@ export const cardFeatureStyles = css`
|
||||
--control-slider-thickness: var(--feature-height);
|
||||
--control-slider-border-radius: var(--feature-border-radius);
|
||||
}
|
||||
ha-control-switch {
|
||||
--control-switch-on-color: var(--feature-color);
|
||||
--control-switch-off-color: var(--feature-color);
|
||||
--control-switch-background-opacity: 0.2;
|
||||
--control-switch-thickness: var(--feature-height);
|
||||
--control-switch-border-radius: var(--feature-border-radius);
|
||||
--control-switch-padding: 0px;
|
||||
}
|
||||
`;
|
||||
|
@ -1,23 +1,50 @@
|
||||
import { mdiPowerOff, mdiPower } from "@mdi/js";
|
||||
import {
|
||||
mdiFan,
|
||||
mdiFanOff,
|
||||
mdiLightbulbOff,
|
||||
mdiLightbulbOn,
|
||||
mdiPower,
|
||||
mdiPowerOff,
|
||||
mdiVolumeHigh,
|
||||
mdiVolumeOff,
|
||||
} from "@mdi/js";
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import type { TemplateResult } from "lit";
|
||||
import { LitElement, html } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { stateColorCss } from "../../../common/entity/state_color";
|
||||
import "../../../components/ha-control-select";
|
||||
import type { ControlSelectOption } from "../../../components/ha-control-select";
|
||||
import { UNAVAILABLE } from "../../../data/entity";
|
||||
import "../../../components/ha-control-button";
|
||||
import "../../../components/ha-control-button-group";
|
||||
import "../../../components/ha-control-switch";
|
||||
import { UNAVAILABLE, UNKNOWN } from "../../../data/entity";
|
||||
import { forwardHaptic } from "../../../data/haptics";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { LovelaceCardFeature } from "../types";
|
||||
import { cardFeatureStyles } from "./common/card-feature-styles";
|
||||
import type { ToggleCardFeatureConfig } from "./types";
|
||||
import { showToast } from "../../../util/toast";
|
||||
|
||||
export const supportsToggleCardFeature = (stateObj: HassEntity) => {
|
||||
const domain = computeDomain(stateObj.entity_id);
|
||||
return ["switch", "input_boolean"].includes(domain);
|
||||
return ["switch", "input_boolean", "light", "fan", "siren", "valve"].includes(
|
||||
domain
|
||||
);
|
||||
};
|
||||
|
||||
const DOMAIN_ICONS: Record<string, { on: string; off: string }> = {
|
||||
siren: {
|
||||
on: mdiVolumeHigh,
|
||||
off: mdiVolumeOff,
|
||||
},
|
||||
light: {
|
||||
on: mdiLightbulbOn,
|
||||
off: mdiLightbulbOff,
|
||||
},
|
||||
fan: {
|
||||
on: mdiFan,
|
||||
off: mdiFanOff,
|
||||
},
|
||||
};
|
||||
|
||||
@customElement("hui-toggle-card-feature")
|
||||
@ -41,67 +68,120 @@ class HuiToggleCardFeature extends LitElement implements LovelaceCardFeature {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | null {
|
||||
private _valueChanged(ev) {
|
||||
const checked = ev.target.checked as boolean;
|
||||
|
||||
if (checked) {
|
||||
this._turnOn();
|
||||
} else {
|
||||
this._turnOff();
|
||||
}
|
||||
}
|
||||
|
||||
private _turnOn() {
|
||||
this._callService(true);
|
||||
}
|
||||
|
||||
private _turnOff() {
|
||||
this._callService(false);
|
||||
}
|
||||
|
||||
private async _callService(turnOn): Promise<void> {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic("light");
|
||||
const stateDomain = computeDomain(this.stateObj.entity_id);
|
||||
const serviceDomain = stateDomain;
|
||||
const service = turnOn ? "turn_on" : "turn_off";
|
||||
|
||||
await this.hass.callService(serviceDomain, service, {
|
||||
entity_id: this.stateObj.entity_id,
|
||||
});
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (
|
||||
!this._config ||
|
||||
!this.hass ||
|
||||
!this.stateObj ||
|
||||
!supportsToggleCardFeature(this.stateObj)
|
||||
) {
|
||||
return null;
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const color = stateColorCss(this.stateObj);
|
||||
const onColor = "var(--feature-color)";
|
||||
const offColor = stateColorCss(this.stateObj, "off");
|
||||
|
||||
const options = ["off", "on"].map<ControlSelectOption>((entityState) => ({
|
||||
value: entityState,
|
||||
label: this.hass!.formatEntityState(this.stateObj!, entityState),
|
||||
path: entityState === "on" ? mdiPower : mdiPowerOff,
|
||||
}));
|
||||
const isOn = this.stateObj.state === "on";
|
||||
const isOff = this.stateObj.state === "off";
|
||||
|
||||
const domain = computeDomain(this.stateObj.entity_id);
|
||||
const onIcon = DOMAIN_ICONS[domain]?.on || mdiPower;
|
||||
const offIcon = DOMAIN_ICONS[domain]?.off || mdiPowerOff;
|
||||
|
||||
if (
|
||||
this.stateObj.attributes.assumed_state ||
|
||||
this.stateObj.state === UNKNOWN
|
||||
) {
|
||||
return html`
|
||||
<ha-control-button-group>
|
||||
<ha-control-button
|
||||
.label=${this.hass.localize("ui.card.common.turn_off")}
|
||||
@click=${this._turnOff}
|
||||
.disabled=${this.stateObj.state === UNAVAILABLE}
|
||||
class=${classMap({
|
||||
active: isOff,
|
||||
})}
|
||||
style=${styleMap({
|
||||
"--color": offColor,
|
||||
})}
|
||||
>
|
||||
<ha-svg-icon .path=${offIcon}></ha-svg-icon>
|
||||
</ha-control-button>
|
||||
<ha-control-button
|
||||
.label=${this.hass.localize("ui.card.common.turn_on")}
|
||||
@click=${this._turnOn}
|
||||
.disabled=${this.stateObj.state === UNAVAILABLE}
|
||||
class=${classMap({
|
||||
active: isOn,
|
||||
})}
|
||||
style=${styleMap({
|
||||
"--color": onColor,
|
||||
})}
|
||||
>
|
||||
<ha-svg-icon .path=${onIcon}></ha-svg-icon>
|
||||
</ha-control-button>
|
||||
</ha-control-button-group>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-control-select
|
||||
.options=${options}
|
||||
.value=${this.stateObj.state}
|
||||
@value-changed=${this._valueChanged}
|
||||
hide-label
|
||||
.ariaLabel=${this.hass.localize("ui.card.humidifier.state")}
|
||||
style=${styleMap({
|
||||
"--control-select-color": color,
|
||||
})}
|
||||
.disabled=${this.stateObj!.state === UNAVAILABLE}
|
||||
<ha-control-switch
|
||||
touch-action="none"
|
||||
.pathOn=${onIcon}
|
||||
.pathOff=${offIcon}
|
||||
.checked=${isOn}
|
||||
@change=${this._valueChanged}
|
||||
.ariaLabel=${this.hass.localize("ui.card.common.toggle")}
|
||||
.disabled=${this.stateObj.state === UNAVAILABLE}
|
||||
>
|
||||
</ha-control-select>
|
||||
</ha-control-switch>
|
||||
`;
|
||||
}
|
||||
|
||||
private async _valueChanged(ev: CustomEvent) {
|
||||
const newState = (ev.detail as any).value;
|
||||
|
||||
if (
|
||||
newState === this.stateObj!.state &&
|
||||
!this.stateObj!.attributes.assumed_state
|
||||
)
|
||||
return;
|
||||
const service = newState === "on" ? "turn_on" : "turn_off";
|
||||
const domain = computeDomain(this.stateObj!.entity_id);
|
||||
|
||||
try {
|
||||
await this.hass!.callService(domain, service, {
|
||||
entity_id: this.stateObj!.entity_id,
|
||||
});
|
||||
} catch (_err) {
|
||||
showToast(this, {
|
||||
message: this.hass!.localize("ui.notification_toast.action_failed", {
|
||||
service: domain + "." + service,
|
||||
}),
|
||||
duration: 5000,
|
||||
dismissable: true,
|
||||
});
|
||||
}
|
||||
static get styles() {
|
||||
return [
|
||||
cardFeatureStyles,
|
||||
css`
|
||||
ha-control-button.active {
|
||||
--control-button-icon-color: white;
|
||||
--control-button-background-color: var(--color);
|
||||
--control-button-background-opacity: 1;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
static styles = cardFeatureStyles;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
Loading…
x
Reference in New Issue
Block a user