diff --git a/gallery/src/demos/demo-more-info-cover.ts b/gallery/src/demos/demo-more-info-cover.ts
new file mode 100644
index 0000000000..f715d5fc9c
--- /dev/null
+++ b/gallery/src/demos/demo-more-info-cover.ts
@@ -0,0 +1,164 @@
+import { html, LitElement, PropertyValues, TemplateResult } from "lit";
+import { customElement, property, query } from "lit/decorators";
+import "../../../src/components/ha-card";
+import {
+ SUPPORT_OPEN,
+ SUPPORT_STOP,
+ SUPPORT_CLOSE,
+ SUPPORT_SET_POSITION,
+ SUPPORT_OPEN_TILT,
+ SUPPORT_STOP_TILT,
+ SUPPORT_CLOSE_TILT,
+ SUPPORT_SET_TILT_POSITION,
+} from "../../../src/data/cover";
+import "../../../src/dialogs/more-info/more-info-content";
+import { getEntity } from "../../../src/fake_data/entity";
+import {
+ MockHomeAssistant,
+ provideHass,
+} from "../../../src/fake_data/provide_hass";
+import "../components/demo-more-infos";
+
+const ENTITIES = [
+ getEntity("cover", "position_buttons", "on", {
+ friendly_name: "Position Buttons",
+ supported_features: SUPPORT_OPEN + SUPPORT_STOP + SUPPORT_CLOSE,
+ }),
+ getEntity("cover", "position_slider_half", "on", {
+ friendly_name: "Position Half-Open",
+ supported_features:
+ SUPPORT_OPEN + SUPPORT_STOP + SUPPORT_CLOSE + SUPPORT_SET_POSITION,
+ current_position: 50,
+ }),
+ getEntity("cover", "position_slider_open", "on", {
+ friendly_name: "Position Open",
+ supported_features:
+ SUPPORT_OPEN + SUPPORT_STOP + SUPPORT_CLOSE + SUPPORT_SET_POSITION,
+ current_position: 100,
+ }),
+ getEntity("cover", "position_slider_closed", "on", {
+ friendly_name: "Position Closed",
+ supported_features:
+ SUPPORT_OPEN + SUPPORT_STOP + SUPPORT_CLOSE + SUPPORT_SET_POSITION,
+ current_position: 0,
+ }),
+ getEntity("cover", "tilt_buttons", "on", {
+ friendly_name: "Tilt Buttons",
+ supported_features:
+ SUPPORT_OPEN_TILT + SUPPORT_STOP_TILT + SUPPORT_CLOSE_TILT,
+ }),
+ getEntity("cover", "tilt_slider_half", "on", {
+ friendly_name: "Tilt Half-Open",
+ supported_features:
+ SUPPORT_OPEN_TILT +
+ SUPPORT_STOP_TILT +
+ SUPPORT_CLOSE_TILT +
+ SUPPORT_SET_TILT_POSITION,
+ current_tilt_position: 50,
+ }),
+ getEntity("cover", "tilt_slider_open", "on", {
+ friendly_name: "Tilt Open",
+ supported_features:
+ SUPPORT_OPEN_TILT +
+ SUPPORT_STOP_TILT +
+ SUPPORT_CLOSE_TILT +
+ SUPPORT_SET_TILT_POSITION,
+ current_tilt_position: 100,
+ }),
+ getEntity("cover", "tilt_slider_closed", "on", {
+ friendly_name: "Tilt Closed",
+ supported_features:
+ SUPPORT_OPEN_TILT +
+ SUPPORT_STOP_TILT +
+ SUPPORT_CLOSE_TILT +
+ SUPPORT_SET_TILT_POSITION,
+ current_tilt_position: 0,
+ }),
+ getEntity("cover", "position_slider_tilt_slider", "on", {
+ friendly_name: "Both Sliders",
+ supported_features:
+ SUPPORT_OPEN +
+ SUPPORT_STOP +
+ SUPPORT_CLOSE +
+ SUPPORT_SET_POSITION +
+ SUPPORT_OPEN_TILT +
+ SUPPORT_STOP_TILT +
+ SUPPORT_CLOSE_TILT +
+ SUPPORT_SET_TILT_POSITION,
+ current_position: 30,
+ current_tilt_position: 70,
+ }),
+ getEntity("cover", "position_tilt_slider", "on", {
+ friendly_name: "Position & Tilt Slider",
+ supported_features:
+ SUPPORT_OPEN +
+ SUPPORT_STOP +
+ SUPPORT_CLOSE +
+ SUPPORT_OPEN_TILT +
+ SUPPORT_STOP_TILT +
+ SUPPORT_CLOSE_TILT +
+ SUPPORT_SET_TILT_POSITION,
+ current_tilt_position: 70,
+ }),
+ getEntity("cover", "position_slider_tilt", "on", {
+ friendly_name: "Position Slider & Tilt",
+ supported_features:
+ SUPPORT_OPEN +
+ SUPPORT_STOP +
+ SUPPORT_CLOSE +
+ SUPPORT_SET_POSITION +
+ SUPPORT_OPEN_TILT +
+ SUPPORT_STOP_TILT +
+ SUPPORT_CLOSE_TILT,
+ current_position: 30,
+ }),
+ getEntity("cover", "position_slider_only_tilt_slider", "on", {
+ friendly_name: "Position Slider Only & Tilt Buttons",
+ supported_features:
+ SUPPORT_SET_POSITION +
+ SUPPORT_OPEN_TILT +
+ SUPPORT_STOP_TILT +
+ SUPPORT_CLOSE_TILT,
+ current_position: 30,
+ }),
+ getEntity("cover", "position_slider_only_tilt", "on", {
+ friendly_name: "Position Slider Only & Tilt",
+ supported_features:
+ SUPPORT_SET_POSITION +
+ SUPPORT_OPEN_TILT +
+ SUPPORT_STOP_TILT +
+ SUPPORT_CLOSE_TILT +
+ SUPPORT_SET_TILT_POSITION,
+ current_position: 30,
+ current_tilt_position: 70,
+ }),
+];
+
+@customElement("demo-more-info-cover")
+class DemoMoreInfoCover extends LitElement {
+ @property() public hass!: MockHomeAssistant;
+
+ @query("demo-more-infos") private _demoRoot!: HTMLElement;
+
+ protected render(): TemplateResult {
+ return html`
+ ent.entityId)}
+ >
+ `;
+ }
+
+ protected firstUpdated(changedProperties: PropertyValues) {
+ super.firstUpdated(changedProperties);
+ const hass = provideHass(this._demoRoot);
+ hass.updateTranslations(null, "en");
+ hass.addEntities(ENTITIES);
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "demo-more-info-cover": DemoMoreInfoCover;
+ }
+}
diff --git a/src/components/ha-cover-controls.ts b/src/components/ha-cover-controls.ts
index 85be8bf786..9f28b010d9 100644
--- a/src/components/ha-cover-controls.ts
+++ b/src/components/ha-cover-controls.ts
@@ -1,39 +1,30 @@
import { mdiStop } from "@mdi/js";
-import type { HassEntity } from "home-assistant-js-websocket";
-import {
- css,
- CSSResultGroup,
- html,
- LitElement,
- PropertyValues,
- TemplateResult,
-} from "lit";
-import { customElement, property, state } from "lit/decorators";
+import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
+import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { computeCloseIcon, computeOpenIcon } from "../common/entity/cover_icon";
+import {
+ CoverEntity,
+ isClosing,
+ isFullyClosed,
+ isFullyOpen,
+ isOpening,
+ supportsClose,
+ supportsOpen,
+ supportsStop,
+} from "../data/cover";
import { UNAVAILABLE } from "../data/entity";
import type { HomeAssistant } from "../types";
-import CoverEntity from "../util/cover-model";
import "./ha-icon-button";
@customElement("ha-cover-controls")
class HaCoverControls extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
- @property({ attribute: false }) public stateObj!: HassEntity;
-
- @state() private _entityObj?: CoverEntity;
-
- public willUpdate(changedProperties: PropertyValues): void {
- super.willUpdate(changedProperties);
-
- if (changedProperties.has("stateObj")) {
- this._entityObj = new CoverEntity(this.hass, this.stateObj);
- }
- }
+ @property({ attribute: false }) public stateObj!: CoverEntity;
protected render(): TemplateResult {
- if (!this._entityObj) {
+ if (!this.stateObj) {
return html``;
}
@@ -41,7 +32,7 @@ class HaCoverControls extends LitElement {
+ supportsFeature(stateObj, SUPPORT_OPEN);
+
+export const supportsClose = (stateObj) =>
+ supportsFeature(stateObj, SUPPORT_CLOSE);
+
+export const supportsSetPosition = (stateObj) =>
+ supportsFeature(stateObj, SUPPORT_SET_POSITION);
+
+export const supportsStop = (stateObj) =>
+ supportsFeature(stateObj, SUPPORT_STOP);
+
+export const supportsOpenTilt = (stateObj) =>
+ supportsFeature(stateObj, SUPPORT_OPEN_TILT);
+
+export const supportsCloseTilt = (stateObj) =>
+ supportsFeature(stateObj, SUPPORT_CLOSE_TILT);
+
+export const supportsStopTilt = (stateObj) =>
+ supportsFeature(stateObj, SUPPORT_STOP_TILT);
+
+export const supportsSetTiltPosition = (stateObj) =>
+ supportsFeature(stateObj, SUPPORT_SET_TILT_POSITION);
+
+export function isFullyOpen(stateObj: CoverEntity) {
+ if (stateObj.attributes.current_position !== undefined) {
+ return stateObj.attributes.current_position === 100;
+ }
+ return stateObj.state === "open";
+}
+
+export function isFullyClosed(stateObj: CoverEntity) {
+ if (stateObj.attributes.current_position !== undefined) {
+ return stateObj.attributes.current_position === 0;
+ }
+ return stateObj.state === "closed";
+}
+
+export function isFullyOpenTilt(stateObj: CoverEntity) {
+ return stateObj.attributes.current_tilt_position === 100;
+}
+
+export function isFullyClosedTilt(stateObj: CoverEntity) {
+ return stateObj.attributes.current_tilt_position === 0;
+}
+
+export function isOpening(stateObj: CoverEntity) {
+ return stateObj.state === "opening";
+}
+
+export function isClosing(stateObj: CoverEntity) {
+ return stateObj.state === "closing";
+}
+
+export function isTiltOnly(stateObj: CoverEntity) {
+ const supportsCover =
+ supportsOpen(stateObj) || supportsClose(stateObj) || supportsStop(stateObj);
+ const supportsTilt =
+ supportsOpenTilt(stateObj) ||
+ supportsCloseTilt(stateObj) ||
+ supportsStopTilt(stateObj);
+ return supportsTilt && !supportsCover;
+}
+
+interface CoverEntityAttributes extends HassEntityAttributeBase {
+ current_position: number;
+ current_tilt_position: number;
+}
+
+export interface CoverEntity extends HassEntityBase {
+ attributes: CoverEntityAttributes;
+}
diff --git a/src/dialogs/more-info/controls/more-info-cover.js b/src/dialogs/more-info/controls/more-info-cover.js
deleted file mode 100644
index 6431959047..0000000000
--- a/src/dialogs/more-info/controls/more-info-cover.js
+++ /dev/null
@@ -1,124 +0,0 @@
-import "@polymer/iron-flex-layout/iron-flex-layout-classes";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-/* eslint-plugin-disable lit */
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-import { attributeClassNames } from "../../../common/entity/attribute_class_names";
-import { featureClassNames } from "../../../common/entity/feature_class_names";
-import "../../../components/ha-cover-tilt-controls";
-import "../../../components/ha-labeled-slider";
-import LocalizeMixin from "../../../mixins/localize-mixin";
-import CoverEntity from "../../../util/cover-model";
-
-const FEATURE_CLASS_NAMES = {
- 4: "has-set_position",
- 128: "has-set_tilt_position",
-};
-class MoreInfoCover extends LocalizeMixin(PolymerElement) {
- static get template() {
- return html`
-
-
-
-
- `;
- }
-
- static get properties() {
- return {
- hass: Object,
- stateObj: {
- type: Object,
- observer: "stateObjChanged",
- },
- entityObj: {
- type: Object,
- computed: "computeEntityObj(hass, stateObj)",
- },
- coverPositionSliderValue: Number,
- coverTiltPositionSliderValue: Number,
- };
- }
-
- computeEntityObj(hass, stateObj) {
- return new CoverEntity(hass, stateObj);
- }
-
- stateObjChanged(newVal) {
- if (newVal) {
- this.setProperties({
- coverPositionSliderValue: newVal.attributes.current_position,
- coverTiltPositionSliderValue: newVal.attributes.current_tilt_position,
- });
- }
- }
-
- computeClassNames(stateObj) {
- const classes = [
- attributeClassNames(stateObj, [
- "current_position",
- "current_tilt_position",
- ]),
- featureClassNames(stateObj, FEATURE_CLASS_NAMES),
- ];
- return classes.join(" ");
- }
-
- coverPositionSliderChanged(ev) {
- this.entityObj.setCoverPosition(ev.target.value);
- }
-
- coverTiltPositionSliderChanged(ev) {
- this.entityObj.setCoverTiltPosition(ev.target.value);
- }
-}
-
-customElements.define("more-info-cover", MoreInfoCover);
diff --git a/src/dialogs/more-info/controls/more-info-cover.ts b/src/dialogs/more-info/controls/more-info-cover.ts
new file mode 100644
index 0000000000..61faf09af2
--- /dev/null
+++ b/src/dialogs/more-info/controls/more-info-cover.ts
@@ -0,0 +1,140 @@
+import { css, CSSResult, html, LitElement, TemplateResult } from "lit";
+import { customElement, property } from "lit/decorators";
+import { attributeClassNames } from "../../../common/entity/attribute_class_names";
+import { featureClassNames } from "../../../common/entity/feature_class_names";
+import "../../../components/ha-attributes";
+import "../../../components/ha-cover-tilt-controls";
+import "../../../components/ha-labeled-slider";
+import {
+ CoverEntity,
+ FEATURE_CLASS_NAMES,
+ isTiltOnly,
+ supportsSetPosition,
+ supportsSetTiltPosition,
+} from "../../../data/cover";
+import { HomeAssistant } from "../../../types";
+
+@customElement("more-info-cover")
+class MoreInfoCover extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false }) public stateObj!: CoverEntity;
+
+ protected render(): TemplateResult {
+ if (!this.stateObj) {
+ return html``;
+ }
+
+ const _isTiltOnly = isTiltOnly(this.stateObj);
+
+ return html`
+
+
+
+
+
+
+ ${supportsSetTiltPosition(this.stateObj)
+ ? // Either render the labeled slider and put the tilt buttons into its slot
+ // or (if tilt position is not supported and therefore no slider is shown)
+ // render a title
(same style as for a labeled slider) and directly put
+ // the tilt controls on the more-info.
+ html`
+ ${!_isTiltOnly
+ ? html` `
+ : html``}
+ `
+ : !_isTiltOnly
+ ? html`
+
+ ${this.hass.localize("ui.card.cover.tilt_position")}
+
+
+ `
+ : html``}
+
+
+
+ `;
+ }
+
+ private _computeClassNames(stateObj) {
+ const classes = [
+ attributeClassNames(stateObj, [
+ "current_position",
+ "current_tilt_position",
+ ]),
+ featureClassNames(stateObj, FEATURE_CLASS_NAMES),
+ ];
+ return classes.join(" ");
+ }
+
+ private _coverPositionSliderChanged(ev) {
+ this.hass.callService("cover", "set_cover_position", {
+ entity_id: this.stateObj.entity_id,
+ position: ev.target.value,
+ });
+ }
+
+ private _coverTiltPositionSliderChanged(ev) {
+ this.hass.callService("cover", "set_cover_tilt_position", {
+ entity_id: this.stateObj.entity_id,
+ tilt_position: ev.target.value,
+ });
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ .current_position,
+ .tilt {
+ max-height: 0px;
+ overflow: hidden;
+ }
+
+ .has-set_position .current_position,
+ .has-current_position .current_position,
+ .has-open_tilt .tilt,
+ .has-close_tilt .tilt,
+ .has-stop_tilt .tilt,
+ .has-set_tilt_position .tilt,
+ .has-current_tilt_position .tilt {
+ max-height: 208px;
+ }
+
+ /* from ha-labeled-slider for consistent look */
+ .title {
+ margin: 5px 0 8px;
+ color: var(--primary-text-color);
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "more-info-cover": MoreInfoCover;
+ }
+}
diff --git a/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts b/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts
index 5503eac028..b42d0dc64d 100644
--- a/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts
+++ b/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts
@@ -9,8 +9,8 @@ import {
import { customElement, property, state } from "lit/decorators";
import "../../../components/ha-cover-controls";
import "../../../components/ha-cover-tilt-controls";
+import { CoverEntity, isTiltOnly } from "../../../data/cover";
import { HomeAssistant } from "../../../types";
-import { isTiltOnly } from "../../../util/cover-model";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
@@ -38,7 +38,7 @@ class HuiCoverEntityRow extends LitElement implements LovelaceRow {
return html``;
}
- const stateObj = this.hass.states[this._config.entity];
+ const stateObj = this.hass.states[this._config.entity] as CoverEntity;
if (!stateObj) {
return html`
diff --git a/src/state-summary/state-card-cover.js b/src/state-summary/state-card-cover.js
deleted file mode 100644
index e2e6b54277..0000000000
--- a/src/state-summary/state-card-cover.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import "@polymer/iron-flex-layout/iron-flex-layout-classes";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-/* eslint-plugin-disable lit */
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-import "../components/entity/state-info";
-import "../components/ha-cover-controls";
-import "../components/ha-cover-tilt-controls";
-import CoverEntity from "../util/cover-model";
-
-class StateCardCover extends PolymerElement {
- static get template() {
- return html`
-
-
-
-
- ${this.stateInfoTemplate}
-
-
-
-
-
- `;
- }
-
- static get stateInfoTemplate() {
- return html`
-
- `;
- }
-
- static get properties() {
- return {
- hass: Object,
- stateObj: Object,
- inDialog: {
- type: Boolean,
- value: false,
- },
- entityObj: {
- type: Object,
- computed: "computeEntityObj(hass, stateObj)",
- },
- };
- }
-
- computeEntityObj(hass, stateObj) {
- const entity = new CoverEntity(hass, stateObj);
- return entity;
- }
-}
-customElements.define("state-card-cover", StateCardCover);
diff --git a/src/state-summary/state-card-cover.ts b/src/state-summary/state-card-cover.ts
new file mode 100644
index 0000000000..9134ff9257
--- /dev/null
+++ b/src/state-summary/state-card-cover.ts
@@ -0,0 +1,56 @@
+import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
+import { customElement, property } from "lit/decorators";
+import "../components/entity/state-info";
+import "../components/ha-cover-controls";
+import "../components/ha-cover-tilt-controls";
+import { CoverEntity, isTiltOnly } from "../data/cover";
+import { haStyle } from "../resources/styles";
+import { HomeAssistant } from "../types";
+
+@customElement("state-card-cover")
+class StateCardCover extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false }) public stateObj!: CoverEntity;
+
+ @property({ type: Boolean }) public inDialog = false;
+
+ protected render(): TemplateResult {
+ return html`
+
+
+
+
+
+ `;
+ }
+
+ static get styles(): CSSResultGroup {
+ return [
+ haStyle,
+ css`
+ :host {
+ line-height: 1.5;
+ }
+ `,
+ ];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "state-card-cover": StateCardCover;
+ }
+}
diff --git a/src/util/cover-model.js b/src/util/cover-model.js
deleted file mode 100644
index eae1007cf8..0000000000
--- a/src/util/cover-model.js
+++ /dev/null
@@ -1,149 +0,0 @@
-import { supportsFeature } from "../common/entity/supports-feature";
-
-/* eslint-enable no-bitwise */
-export default class CoverEntity {
- constructor(hass, stateObj) {
- this.hass = hass;
- this.stateObj = stateObj;
- this._attr = stateObj.attributes;
- this._feat = this._attr.supported_features;
- }
-
- get isFullyOpen() {
- if (this._attr.current_position !== undefined) {
- return this._attr.current_position === 100;
- }
- return this.stateObj.state === "open";
- }
-
- get isFullyClosed() {
- if (this._attr.current_position !== undefined) {
- return this._attr.current_position === 0;
- }
- return this.stateObj.state === "closed";
- }
-
- get isFullyOpenTilt() {
- return this._attr.current_tilt_position === 100;
- }
-
- get isFullyClosedTilt() {
- return this._attr.current_tilt_position === 0;
- }
-
- get isOpening() {
- return this.stateObj.state === "opening";
- }
-
- get isClosing() {
- return this.stateObj.state === "closing";
- }
-
- get supportsOpen() {
- return supportsFeature(this.stateObj, 1);
- }
-
- get supportsClose() {
- return supportsFeature(this.stateObj, 2);
- }
-
- get supportsSetPosition() {
- return supportsFeature(this.stateObj, 4);
- }
-
- get supportsStop() {
- return supportsFeature(this.stateObj, 8);
- }
-
- get supportsOpenTilt() {
- return supportsFeature(this.stateObj, 16);
- }
-
- get supportsCloseTilt() {
- return supportsFeature(this.stateObj, 32);
- }
-
- get supportsStopTilt() {
- return supportsFeature(this.stateObj, 64);
- }
-
- get supportsSetTiltPosition() {
- return supportsFeature(this.stateObj, 128);
- }
-
- get isTiltOnly() {
- const supportsCover =
- this.supportsOpen || this.supportsClose || this.supportsStop;
- const supportsTilt =
- this.supportsOpenTilt || this.supportsCloseTilt || this.supportsStopTilt;
- return supportsTilt && !supportsCover;
- }
-
- openCover() {
- this.callService("open_cover");
- }
-
- closeCover() {
- this.callService("close_cover");
- }
-
- stopCover() {
- this.callService("stop_cover");
- }
-
- openCoverTilt() {
- this.callService("open_cover_tilt");
- }
-
- closeCoverTilt() {
- this.callService("close_cover_tilt");
- }
-
- stopCoverTilt() {
- this.callService("stop_cover_tilt");
- }
-
- setCoverPosition(position) {
- this.callService("set_cover_position", { position });
- }
-
- setCoverTiltPosition(tiltPosition) {
- this.callService("set_cover_tilt_position", {
- tilt_position: tiltPosition,
- });
- }
-
- // helper method
-
- callService(service, data = {}) {
- data.entity_id = this.stateObj.entity_id;
- this.hass.callService("cover", service, data);
- }
-}
-
-export const supportsOpen = (stateObj) => supportsFeature(stateObj, 1);
-
-export const supportsClose = (stateObj) => supportsFeature(stateObj, 2);
-
-export const supportsSetPosition = (stateObj) => supportsFeature(stateObj, 4);
-
-export const supportsStop = (stateObj) => supportsFeature(stateObj, 8);
-
-export const supportsOpenTilt = (stateObj) => supportsFeature(stateObj, 16);
-
-export const supportsCloseTilt = (stateObj) => supportsFeature(stateObj, 32);
-
-export const supportsStopTilt = (stateObj) => supportsFeature(stateObj, 64);
-
-export const supportsSetTiltPosition = (stateObj) =>
- supportsFeature(stateObj, 128);
-
-export function isTiltOnly(stateObj) {
- const supportsCover =
- supportsOpen(stateObj) || supportsClose(stateObj) || supportsStop(stateObj);
- const supportsTilt =
- supportsOpenTilt(stateObj) ||
- supportsCloseTilt(stateObj) ||
- supportsStopTilt(stateObj);
- return supportsTilt && !supportsCover;
-}