170 lines
5.1 KiB
TypeScript
170 lines
5.1 KiB
TypeScript
import { css, CSSResultGroup, html, LitElement } from "lit";
|
|
import { customElement, property, state } from "lit/decorators";
|
|
import { styleMap } from "lit/directives/style-map";
|
|
import { computeAttributeNameDisplay } from "../../common/entity/compute_attribute_display";
|
|
import { stateActive } from "../../common/entity/state_active";
|
|
import { stateColorCss } from "../../common/entity/state_color";
|
|
import "../../components/ha-control-select";
|
|
import type { ControlSelectOption } from "../../components/ha-control-select";
|
|
import "../../components/ha-control-slider";
|
|
import { UNAVAILABLE } from "../../data/entity";
|
|
import { DOMAIN_ATTRIBUTES_UNITS } from "../../data/entity_attributes";
|
|
import {
|
|
computeFanSpeedCount,
|
|
computeFanSpeedIcon,
|
|
FAN_SPEED_COUNT_MAX_FOR_BUTTONS,
|
|
FAN_SPEEDS,
|
|
FanEntity,
|
|
fanPercentageToSpeed,
|
|
FanSpeed,
|
|
fanSpeedToPercentage,
|
|
} from "../../data/fan";
|
|
import { HomeAssistant } from "../../types";
|
|
|
|
@customElement("ha-state-control-fan-speed")
|
|
export class HaStateControlFanSpeed extends LitElement {
|
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
|
|
@property({ attribute: false }) public stateObj!: FanEntity;
|
|
|
|
@state() sliderValue?: number;
|
|
|
|
@state() speedValue?: FanSpeed;
|
|
|
|
protected updated(changedProp: Map<string | number | symbol, unknown>): void {
|
|
if (changedProp.has("stateObj")) {
|
|
const percentage = stateActive(this.stateObj)
|
|
? this.stateObj.attributes.percentage ?? 0
|
|
: 0;
|
|
this.sliderValue = Math.max(Math.round(percentage), 0);
|
|
this.speedValue = fanPercentageToSpeed(this.stateObj, percentage);
|
|
}
|
|
}
|
|
|
|
private _speedValueChanged(ev: CustomEvent) {
|
|
const speed = (ev.detail as any).value as FanSpeed;
|
|
|
|
this.speedValue = speed;
|
|
|
|
const percentage = fanSpeedToPercentage(this.stateObj, speed);
|
|
|
|
this.hass.callService("fan", "set_percentage", {
|
|
entity_id: this.stateObj!.entity_id,
|
|
percentage: percentage,
|
|
});
|
|
}
|
|
|
|
private _valueChanged(ev: CustomEvent) {
|
|
const value = (ev.detail as any).value;
|
|
if (isNaN(value)) return;
|
|
|
|
this.sliderValue = value;
|
|
|
|
this.hass.callService("fan", "set_percentage", {
|
|
entity_id: this.stateObj!.entity_id,
|
|
percentage: value,
|
|
});
|
|
}
|
|
|
|
private _localizeSpeed(speed: FanSpeed) {
|
|
if (speed === "on" || speed === "off") {
|
|
return this.hass.formatEntityState(this.stateObj, speed);
|
|
}
|
|
return this.hass.localize(`ui.card.fan.speed.${speed}`) || speed;
|
|
}
|
|
|
|
protected render() {
|
|
const color = stateColorCss(this.stateObj);
|
|
|
|
const speedCount = computeFanSpeedCount(this.stateObj);
|
|
|
|
if (speedCount <= FAN_SPEED_COUNT_MAX_FOR_BUTTONS) {
|
|
const options = FAN_SPEEDS[speedCount]!.map<ControlSelectOption>(
|
|
(speed) => ({
|
|
value: speed,
|
|
label: this._localizeSpeed(speed),
|
|
path: computeFanSpeedIcon(this.stateObj, speed),
|
|
})
|
|
).reverse();
|
|
|
|
return html`
|
|
<ha-control-select
|
|
vertical
|
|
.options=${options}
|
|
.value=${this.speedValue}
|
|
@value-changed=${this._speedValueChanged}
|
|
.ariaLabel=${computeAttributeNameDisplay(
|
|
this.hass.localize,
|
|
this.stateObj,
|
|
this.hass.entities,
|
|
"percentage"
|
|
)}
|
|
style=${styleMap({
|
|
"--control-select-color": color,
|
|
"--control-select-background": color,
|
|
})}
|
|
.disabled=${this.stateObj.state === UNAVAILABLE}
|
|
>
|
|
</ha-control-select>
|
|
`;
|
|
}
|
|
|
|
return html`
|
|
<ha-control-slider
|
|
vertical
|
|
min="0"
|
|
max="100"
|
|
.value=${this.sliderValue}
|
|
.step=${this.stateObj.attributes.percentage_step ?? 1}
|
|
@value-changed=${this._valueChanged}
|
|
.ariaLabel=${computeAttributeNameDisplay(
|
|
this.hass.localize,
|
|
this.stateObj,
|
|
this.hass.entities,
|
|
"percentage"
|
|
)}
|
|
style=${styleMap({
|
|
"--control-slider-color": color,
|
|
"--control-slider-background": color,
|
|
})}
|
|
.disabled=${this.stateObj.state === UNAVAILABLE}
|
|
.unit=${DOMAIN_ATTRIBUTES_UNITS.fan.percentage}
|
|
.locale=${this.hass.locale}
|
|
>
|
|
</ha-control-slider>
|
|
`;
|
|
}
|
|
|
|
static get styles(): CSSResultGroup {
|
|
return css`
|
|
ha-control-slider {
|
|
height: 45vh;
|
|
max-height: 320px;
|
|
min-height: 200px;
|
|
--control-slider-thickness: 130px;
|
|
--control-slider-border-radius: 48px;
|
|
--control-slider-color: var(--primary-color);
|
|
--control-slider-background: var(--disabled-color);
|
|
--control-slider-background-opacity: 0.2;
|
|
--control-slider-tooltip-font-size: 20px;
|
|
}
|
|
ha-control-select {
|
|
height: 45vh;
|
|
max-height: 320px;
|
|
min-height: 200px;
|
|
--control-select-thickness: 130px;
|
|
--control-select-border-radius: 48px;
|
|
--control-select-color: var(--primary-color);
|
|
--control-select-background: var(--disabled-color);
|
|
--control-select-background-opacity: 0.2;
|
|
}
|
|
`;
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"ha-state-control-fan-speed": HaStateControlFanSpeed;
|
|
}
|
|
}
|