mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Cover position tile feature (#16110)
* wip * css + transtations * Update types.ts rollback changes done by VS Code * fix * Inverted slider --------- Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
This commit is contained in:
parent
6e27fbe10f
commit
705b6aeb4b
@ -43,6 +43,9 @@ export class HaControlSlider extends LitElement {
|
|||||||
@property({ type: Boolean, attribute: "show-handle" })
|
@property({ type: Boolean, attribute: "show-handle" })
|
||||||
public showHandle = false;
|
public showHandle = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "inverted" })
|
||||||
|
public inverted = false;
|
||||||
|
|
||||||
@property({ type: Number })
|
@property({ type: Number })
|
||||||
public value?: number;
|
public value?: number;
|
||||||
|
|
||||||
@ -61,11 +64,16 @@ export class HaControlSlider extends LitElement {
|
|||||||
public pressed = false;
|
public pressed = false;
|
||||||
|
|
||||||
valueToPercentage(value: number) {
|
valueToPercentage(value: number) {
|
||||||
return (this.boundedValue(value) - this.min) / (this.max - this.min);
|
const percentage =
|
||||||
|
(this.boundedValue(value) - this.min) / (this.max - this.min);
|
||||||
|
return this.inverted ? 1 - percentage : percentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
percentageToValue(value: number) {
|
percentageToValue(percentage: number) {
|
||||||
return (this.max - this.min) * value + this.min;
|
return (
|
||||||
|
(this.max - this.min) * (this.inverted ? 1 - percentage : percentage) +
|
||||||
|
this.min
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
steppedValue(value: number) {
|
steppedValue(value: number) {
|
||||||
|
@ -50,7 +50,7 @@ export class HaMoreInfoCoverPosition extends LitElement {
|
|||||||
this.hass.localize,
|
this.hass.localize,
|
||||||
this.stateObj,
|
this.stateObj,
|
||||||
this.hass.entities,
|
this.hass.entities,
|
||||||
"position"
|
"current_position"
|
||||||
)}
|
)}
|
||||||
style=${styleMap({
|
style=${styleMap({
|
||||||
"--control-slider-color": color,
|
"--control-slider-color": color,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import "../tile-features/hui-alarm-modes-tile-feature";
|
import "../tile-features/hui-alarm-modes-tile-feature";
|
||||||
import "../tile-features/hui-climate-hvac-modes-tile-feature";
|
import "../tile-features/hui-climate-hvac-modes-tile-feature";
|
||||||
import "../tile-features/hui-cover-open-close-tile-feature";
|
import "../tile-features/hui-cover-open-close-tile-feature";
|
||||||
|
import "../tile-features/hui-cover-position-tile-feature";
|
||||||
import "../tile-features/hui-cover-tilt-tile-feature";
|
import "../tile-features/hui-cover-tilt-tile-feature";
|
||||||
import "../tile-features/hui-fan-speed-tile-feature";
|
import "../tile-features/hui-fan-speed-tile-feature";
|
||||||
import "../tile-features/hui-light-brightness-tile-feature";
|
import "../tile-features/hui-light-brightness-tile-feature";
|
||||||
@ -15,6 +16,7 @@ import {
|
|||||||
|
|
||||||
const TYPES: Set<LovelaceTileFeatureConfig["type"]> = new Set([
|
const TYPES: Set<LovelaceTileFeatureConfig["type"]> = new Set([
|
||||||
"cover-open-close",
|
"cover-open-close",
|
||||||
|
"cover-position",
|
||||||
"cover-tilt",
|
"cover-tilt",
|
||||||
"light-brightness",
|
"light-brightness",
|
||||||
"light-color-temp",
|
"light-color-temp",
|
||||||
|
@ -28,6 +28,7 @@ import { getTileFeatureElementClass } from "../../create-element/create-tile-fea
|
|||||||
import { supportsAlarmModesTileFeature } from "../../tile-features/hui-alarm-modes-tile-feature";
|
import { supportsAlarmModesTileFeature } from "../../tile-features/hui-alarm-modes-tile-feature";
|
||||||
import { supportsClimateHvacModesTileFeature } from "../../tile-features/hui-climate-hvac-modes-tile-feature";
|
import { supportsClimateHvacModesTileFeature } from "../../tile-features/hui-climate-hvac-modes-tile-feature";
|
||||||
import { supportsCoverOpenCloseTileFeature } from "../../tile-features/hui-cover-open-close-tile-feature";
|
import { supportsCoverOpenCloseTileFeature } from "../../tile-features/hui-cover-open-close-tile-feature";
|
||||||
|
import { supportsCoverPositionTileFeature } from "../../tile-features/hui-cover-position-tile-feature";
|
||||||
import { supportsCoverTiltTileFeature } from "../../tile-features/hui-cover-tilt-tile-feature";
|
import { supportsCoverTiltTileFeature } from "../../tile-features/hui-cover-tilt-tile-feature";
|
||||||
import { supportsFanSpeedTileFeature } from "../../tile-features/hui-fan-speed-tile-feature";
|
import { supportsFanSpeedTileFeature } from "../../tile-features/hui-fan-speed-tile-feature";
|
||||||
import { supportsLightBrightnessTileFeature } from "../../tile-features/hui-light-brightness-tile-feature";
|
import { supportsLightBrightnessTileFeature } from "../../tile-features/hui-light-brightness-tile-feature";
|
||||||
@ -41,6 +42,7 @@ type SupportsFeature = (stateObj: HassEntity) => boolean;
|
|||||||
|
|
||||||
const FEATURE_TYPES: FeatureType[] = [
|
const FEATURE_TYPES: FeatureType[] = [
|
||||||
"cover-open-close",
|
"cover-open-close",
|
||||||
|
"cover-position",
|
||||||
"cover-tilt",
|
"cover-tilt",
|
||||||
"light-brightness",
|
"light-brightness",
|
||||||
"light-color-temp",
|
"light-color-temp",
|
||||||
@ -61,6 +63,7 @@ const EDITABLES_FEATURE_TYPES = new Set<FeatureType>([
|
|||||||
const SUPPORTS_FEATURE_TYPES: Record<FeatureType, SupportsFeature | undefined> =
|
const SUPPORTS_FEATURE_TYPES: Record<FeatureType, SupportsFeature | undefined> =
|
||||||
{
|
{
|
||||||
"cover-open-close": supportsCoverOpenCloseTileFeature,
|
"cover-open-close": supportsCoverOpenCloseTileFeature,
|
||||||
|
"cover-position": supportsCoverPositionTileFeature,
|
||||||
"cover-tilt": supportsCoverTiltTileFeature,
|
"cover-tilt": supportsCoverTiltTileFeature,
|
||||||
"light-brightness": supportsLightBrightnessTileFeature,
|
"light-brightness": supportsLightBrightnessTileFeature,
|
||||||
"light-color-temp": supportsLightColorTempTileFeature,
|
"light-color-temp": supportsLightColorTempTileFeature,
|
||||||
|
@ -0,0 +1,114 @@
|
|||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
|
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||||
|
import { CoverEntityFeature } from "../../../data/cover";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { LovelaceTileFeature } from "../types";
|
||||||
|
import { CoverPositionTileFeatureConfig } from "./types";
|
||||||
|
import { stateActive } from "../../../common/entity/state_active";
|
||||||
|
import { computeAttributeNameDisplay } from "../../../common/entity/compute_attribute_display";
|
||||||
|
import { UNAVAILABLE } from "../../../data/entity";
|
||||||
|
|
||||||
|
export const supportsCoverPositionTileFeature = (stateObj: HassEntity) => {
|
||||||
|
const domain = computeDomain(stateObj.entity_id);
|
||||||
|
return (
|
||||||
|
domain === "cover" &&
|
||||||
|
supportsFeature(stateObj, CoverEntityFeature.SET_POSITION)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
@customElement("hui-cover-position-tile-feature")
|
||||||
|
class HuiCoverPositionTileFeature
|
||||||
|
extends LitElement
|
||||||
|
implements LovelaceTileFeature
|
||||||
|
{
|
||||||
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public stateObj?: HassEntity;
|
||||||
|
|
||||||
|
@state() private _config?: CoverPositionTileFeatureConfig;
|
||||||
|
|
||||||
|
static getStubConfig(): CoverPositionTileFeatureConfig {
|
||||||
|
return {
|
||||||
|
type: "cover-position",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public setConfig(config: CoverPositionTileFeatureConfig): void {
|
||||||
|
if (!config) {
|
||||||
|
throw new Error("Invalid configuration");
|
||||||
|
}
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (
|
||||||
|
!this._config ||
|
||||||
|
!this.hass ||
|
||||||
|
!this.stateObj ||
|
||||||
|
!supportsCoverPositionTileFeature(this.stateObj)
|
||||||
|
) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
const percentage = stateActive(this.stateObj)
|
||||||
|
? this.stateObj.attributes.current_position ?? 0
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
const value = Math.max(Math.round(percentage), 0);
|
||||||
|
|
||||||
|
return html` <div class="container">
|
||||||
|
<ha-control-slider
|
||||||
|
.value=${value}
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
step="1"
|
||||||
|
inverted
|
||||||
|
show-handle
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
.ariaLabel=${computeAttributeNameDisplay(
|
||||||
|
this.hass.localize,
|
||||||
|
this.stateObj,
|
||||||
|
this.hass.entities,
|
||||||
|
"current_position"
|
||||||
|
)}
|
||||||
|
.disabled=${this.stateObj!.state === UNAVAILABLE}
|
||||||
|
></ha-control-slider>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev: CustomEvent) {
|
||||||
|
const value = (ev.detail as any).value;
|
||||||
|
if (isNaN(value)) return;
|
||||||
|
|
||||||
|
this.hass!.callService("cover", "set_cover_position", {
|
||||||
|
entity_id: this.stateObj!.entity_id,
|
||||||
|
position: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-slider {
|
||||||
|
/* Force inactive state to be colored for the slider */
|
||||||
|
--control-slider-color: var(--tile-color);
|
||||||
|
--control-slider-background: var(--tile-color);
|
||||||
|
--control-slider-background-opacity: 0.2;
|
||||||
|
--control-slider-thickness: 40px;
|
||||||
|
--control-slider-border-radius: 10px;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
padding: 0 12px 12px 12px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-cover-position-tile-feature": HuiCoverPositionTileFeature;
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,10 @@ export interface CoverOpenCloseTileFeatureConfig {
|
|||||||
type: "cover-open-close";
|
type: "cover-open-close";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CoverPositionTileFeatureConfig {
|
||||||
|
type: "cover-position";
|
||||||
|
}
|
||||||
|
|
||||||
export interface CoverTiltTileFeatureConfig {
|
export interface CoverTiltTileFeatureConfig {
|
||||||
type: "cover-tilt";
|
type: "cover-tilt";
|
||||||
}
|
}
|
||||||
@ -54,6 +58,7 @@ export interface VacuumCommandsTileFeatureConfig {
|
|||||||
|
|
||||||
export type LovelaceTileFeatureConfig =
|
export type LovelaceTileFeatureConfig =
|
||||||
| CoverOpenCloseTileFeatureConfig
|
| CoverOpenCloseTileFeatureConfig
|
||||||
|
| CoverPositionTileFeatureConfig
|
||||||
| CoverTiltTileFeatureConfig
|
| CoverTiltTileFeatureConfig
|
||||||
| LightBrightnessTileFeatureConfig
|
| LightBrightnessTileFeatureConfig
|
||||||
| LightColorTempTileFeatureConfig
|
| LightColorTempTileFeatureConfig
|
||||||
|
@ -4967,6 +4967,9 @@
|
|||||||
"cover-open-close": {
|
"cover-open-close": {
|
||||||
"label": "Cover open/close"
|
"label": "Cover open/close"
|
||||||
},
|
},
|
||||||
|
"cover-position": {
|
||||||
|
"label": "Cover position"
|
||||||
|
},
|
||||||
"cover-tilt": {
|
"cover-tilt": {
|
||||||
"label": "Cover tilt"
|
"label": "Cover tilt"
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user