Rename tile extras to tile features (#14483)

This commit is contained in:
Paul Bottein 2022-11-30 18:35:13 +01:00 committed by GitHub
parent 92d022747b
commit d4cda0c106
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 332 additions and 318 deletions

View File

@ -29,10 +29,14 @@ import { actionHandler } from "../common/directives/action-handler-directive";
import { findEntities } from "../common/find-entities"; import { findEntities } from "../common/find-entities";
import { handleAction } from "../common/handle-action"; import { handleAction } from "../common/handle-action";
import "../components/hui-timestamp-display"; import "../components/hui-timestamp-display";
import { createTileExtraElement } from "../create-element/create-tile-extra-element"; import { createTileFeatureElement } from "../create-element/create-tile-feature-element";
import { supportsTileExtra } from "../tile-extra/tile-extras"; import { supportsTileFeature } from "../tile-features/tile-features";
import { LovelaceTileExtraConfig } from "../tile-extra/types"; import { LovelaceTileFeatureConfig } from "../tile-features/types";
import { LovelaceCard, LovelaceCardEditor, LovelaceTileExtra } from "../types"; import {
LovelaceCard,
LovelaceCardEditor,
LovelaceTileFeature,
} from "../types";
import { HuiErrorCard } from "./hui-error-card"; import { HuiErrorCard } from "./hui-error-card";
import { computeTileBadge } from "./tile/badges/tile-badge"; import { computeTileBadge } from "./tile/badges/tile-badge";
import { ThermostatCardConfig, TileCardConfig } from "./types"; import { ThermostatCardConfig, TileCardConfig } from "./types";
@ -242,8 +246,8 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
: undefined; : undefined;
const badge = computeTileBadge(stateObj, this.hass); const badge = computeTileBadge(stateObj, this.hass);
const supportedExtras = this._config.extras?.filter((extra) => const supportedFeatures = this._config.features?.filter((feature) =>
supportsTileExtra(stateObj, extra.type) supportsTileFeature(stateObj, feature.type)
); );
return html` return html`
@ -292,11 +296,11 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
.actionHandler=${actionHandler()} .actionHandler=${actionHandler()}
></ha-tile-info> ></ha-tile-info>
</div> </div>
${supportedExtras?.length ${supportedFeatures?.length
? html` ? html`
<div class="extras"> <div class="features">
${supportedExtras.map((extraConf) => ${supportedFeatures.map((featureConf) =>
this.renderExtra(extraConf, stateObj) this.renderFeature(featureConf, stateObj)
)} )}
</div> </div>
` `
@ -305,33 +309,33 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
`; `;
} }
private _extrasElements = new WeakMap< private _featuresElements = new WeakMap<
LovelaceTileExtraConfig, LovelaceTileFeatureConfig,
LovelaceTileExtra | HuiErrorCard LovelaceTileFeature | HuiErrorCard
>(); >();
private _getExtraElement(extra: LovelaceTileExtraConfig) { private _getFeatureElement(feature: LovelaceTileFeatureConfig) {
if (!this._extrasElements.has(extra)) { if (!this._featuresElements.has(feature)) {
const element = createTileExtraElement(extra); const element = createTileFeatureElement(feature);
this._extrasElements.set(extra, element); this._featuresElements.set(feature, element);
return element; return element;
} }
return this._extrasElements.get(extra)!; return this._featuresElements.get(feature)!;
} }
private renderExtra( private renderFeature(
extraConf: LovelaceTileExtraConfig, featureConf: LovelaceTileFeatureConfig,
stateObj: HassEntity stateObj: HassEntity
): TemplateResult { ): TemplateResult {
const element = this._getExtraElement(extraConf); const element = this._getFeatureElement(featureConf);
if (this.hass) { if (this.hass) {
element.hass = this.hass; element.hass = this.hass;
(element as LovelaceTileExtra).stateObj = stateObj; (element as LovelaceTileFeature).stateObj = stateObj;
} }
return html`<div class="extra">${element}</div>`; return html`<div class="feature">${element}</div>`;
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {

View File

@ -11,7 +11,7 @@ import {
} from "../entity-rows/types"; } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types"; import { LovelaceHeaderFooterConfig } from "../header-footer/types";
import { HaDurationData } from "../../../components/ha-duration-input"; import { HaDurationData } from "../../../components/ha-duration-input";
import { LovelaceTileExtraConfig } from "../tile-extra/types"; import { LovelaceTileFeatureConfig } from "../tile-features/types";
export interface AlarmPanelCardConfig extends LovelaceCardConfig { export interface AlarmPanelCardConfig extends LovelaceCardConfig {
entity: string; entity: string;
@ -502,5 +502,5 @@ export interface TileCardConfig extends LovelaceCardConfig {
show_entity_picture?: string; show_entity_picture?: string;
tap_action?: ActionConfig; tap_action?: ActionConfig;
icon_tap_action?: ActionConfig; icon_tap_action?: ActionConfig;
extras?: LovelaceTileExtraConfig[]; features?: LovelaceTileFeatureConfig[];
} }

View File

@ -11,7 +11,7 @@ import type { ErrorCardConfig } from "../cards/types";
import { LovelaceElement, LovelaceElementConfig } from "../elements/types"; import { LovelaceElement, LovelaceElementConfig } from "../elements/types";
import { LovelaceRow, LovelaceRowConfig } from "../entity-rows/types"; import { LovelaceRow, LovelaceRowConfig } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types"; import { LovelaceHeaderFooterConfig } from "../header-footer/types";
import { LovelaceTileExtraConfig } from "../tile-extra/types"; import { LovelaceTileFeatureConfig } from "../tile-features/types";
import { import {
LovelaceBadge, LovelaceBadge,
LovelaceCard, LovelaceCard,
@ -19,8 +19,8 @@ import {
LovelaceHeaderFooter, LovelaceHeaderFooter,
LovelaceHeaderFooterConstructor, LovelaceHeaderFooterConstructor,
LovelaceRowConstructor, LovelaceRowConstructor,
LovelaceTileExtra, LovelaceTileFeature,
LovelaceTileExtraConstructor, LovelaceTileFeatureConstructor,
} from "../types"; } from "../types";
const TIMEOUT = 2000; const TIMEOUT = 2000;
@ -56,10 +56,10 @@ interface CreateElementConfigTypes {
element: LovelaceViewElement; element: LovelaceViewElement;
constructor: unknown; constructor: unknown;
}; };
"tile-extra": { "tile-feature": {
config: LovelaceTileExtraConfig; config: LovelaceTileFeatureConfig;
element: LovelaceTileExtra; element: LovelaceTileFeature;
constructor: LovelaceTileExtraConstructor; constructor: LovelaceTileFeatureConstructor;
}; };
} }

View File

@ -1,22 +0,0 @@
import { LovelaceTileExtraConfig } from "../tile-extra/types";
import {
createLovelaceElement,
getLovelaceElementClass,
} from "./create-element-base";
import "../tile-extra/hui-cover-open-close-tile-extra";
import "../tile-extra/hui-cover-tilt-tile-extra";
import "../tile-extra/hui-light-brightness-tile-extra";
import "../tile-extra/hui-vacuum-commands-tile-extra";
const TYPES: Set<LovelaceTileExtraConfig["type"]> = new Set([
"cover-open-close",
"cover-tilt",
"light-brightness",
"vacuum-commands",
]);
export const createTileExtraElement = (config: LovelaceTileExtraConfig) =>
createLovelaceElement("tile-extra", config, TYPES);
export const getTileExtraElementClass = (type: string) =>
getLovelaceElementClass(type, "tile-extra", TYPES);

View File

@ -0,0 +1,22 @@
import { LovelaceTileFeatureConfig } from "../tile-features/types";
import {
createLovelaceElement,
getLovelaceElementClass,
} from "./create-element-base";
import "../tile-features/hui-cover-open-close-tile-feature";
import "../tile-features/hui-cover-tilt-tile-feature";
import "../tile-features/hui-light-brightness-tile-feature";
import "../tile-features/hui-vacuum-commands-tile-feature";
const TYPES: Set<LovelaceTileFeatureConfig["type"]> = new Set([
"cover-open-close",
"cover-tilt",
"light-brightness",
"vacuum-commands",
]);
export const createTileFeatureElement = (config: LovelaceTileFeatureConfig) =>
createLovelaceElement("tile-feature", config, TYPES);
export const getTileFeatureElementClass = (type: string) =>
getLovelaceElementClass(type, "tile-feature", TYPES);

View File

@ -21,16 +21,16 @@ import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { TileCardConfig } from "../../cards/types"; import type { TileCardConfig } from "../../cards/types";
import { import {
LovelaceTileExtraConfig, LovelaceTileFeatureConfig,
LovelaceTileExtraContext, LovelaceTileFeatureContext,
} from "../../tile-extra/types"; } from "../../tile-features/types";
import type { LovelaceCardEditor } from "../../types"; import type { LovelaceCardEditor } from "../../types";
import "../hui-sub-element-editor"; import "../hui-sub-element-editor";
import { actionConfigStruct } from "../structs/action-struct"; import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { EditSubElementEvent, SubElementEditorConfig } from "../types"; import { EditSubElementEvent, SubElementEditorConfig } from "../types";
import { configElementStyle } from "./config-elements-style"; import { configElementStyle } from "./config-elements-style";
import "./hui-tile-card-extras-editor"; import "./hui-tile-card-features-editor";
const cardConfigStruct = assign( const cardConfigStruct = assign(
baseLovelaceCardConfig, baseLovelaceCardConfig,
@ -42,7 +42,7 @@ const cardConfigStruct = assign(
show_entity_picture: optional(boolean()), show_entity_picture: optional(boolean()),
tap_action: optional(actionConfigStruct), tap_action: optional(actionConfigStruct),
icon_tap_action: optional(actionConfigStruct), icon_tap_action: optional(actionConfigStruct),
extras: optional(array(any())), features: optional(array(any())),
}) })
); );
@ -133,7 +133,7 @@ export class HuiTileCardEditor
); );
private _context = memoizeOne( private _context = memoizeOne(
(entity_id?: string): LovelaceTileExtraContext => ({ entity_id }) (entity_id?: string): LovelaceTileFeatureContext => ({ entity_id })
); );
protected render(): TemplateResult { protected render(): TemplateResult {
@ -172,13 +172,13 @@ export class HuiTileCardEditor
.computeLabel=${this._computeLabelCallback} .computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></ha-form> ></ha-form>
<hui-tile-card-extras-editor <hui-tile-card-features-editor
.hass=${this.hass} .hass=${this.hass}
.stateObj=${stateObj} .stateObj=${stateObj}
.extras=${this._config!.extras ?? []} .features=${this._config!.features ?? []}
@extras-changed=${this._extrasChanged} @features-changed=${this._featuresChanged}
@edit-detail-element=${this._editDetailElement} @edit-detail-element=${this._editDetailElement}
></hui-tile-card-extras-editor> ></hui-tile-card-features-editor>
`; `;
} }
@ -189,26 +189,26 @@ export class HuiTileCardEditor
} }
const config: TileCardConfig = { const config: TileCardConfig = {
extras: this._config.extras, features: this._config.features,
...ev.detail.value, ...ev.detail.value,
}; };
fireEvent(this, "config-changed", { config }); fireEvent(this, "config-changed", { config });
} }
private _extrasChanged(ev: CustomEvent) { private _featuresChanged(ev: CustomEvent) {
ev.stopPropagation(); ev.stopPropagation();
if (!this._config || !this.hass) { if (!this._config || !this.hass) {
return; return;
} }
const extras = ev.detail.extras as LovelaceTileExtraConfig[]; const features = ev.detail.features as LovelaceTileFeatureConfig[];
const config: TileCardConfig = { const config: TileCardConfig = {
...this._config, ...this._config,
extras, features,
}; };
if (extras.length === 0) { if (features.length === 0) {
delete config.extras; delete config.features;
} }
fireEvent(this, "config-changed", { config }); fireEvent(this, "config-changed", { config });
@ -222,18 +222,18 @@ export class HuiTileCardEditor
const value = ev.detail.config; const value = ev.detail.config;
const newConfigExtras = this._config!.extras const newConfigFeatures = this._config!.features
? [...this._config!.extras] ? [...this._config!.features]
: []; : [];
if (!value) { if (!value) {
newConfigExtras.splice(this._subElementEditorConfig!.index!, 1); newConfigFeatures.splice(this._subElementEditorConfig!.index!, 1);
this._goBack(); this._goBack();
} else { } else {
newConfigExtras[this._subElementEditorConfig!.index!] = value; newConfigFeatures[this._subElementEditorConfig!.index!] = value;
} }
this._config = { ...this._config!, extras: newConfigExtras }; this._config = { ...this._config!, features: newConfigFeatures };
this._subElementEditorConfig = { this._subElementEditorConfig = {
...this._subElementEditorConfig!, ...this._subElementEditorConfig!,

View File

@ -22,14 +22,14 @@ import {
SortableInstance, SortableInstance,
} from "../../../../resources/sortable.ondemand"; } from "../../../../resources/sortable.ondemand";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
import { getTileExtraElementClass } from "../../create-element/create-tile-extra-element"; import { getTileFeatureElementClass } from "../../create-element/create-tile-feature-element";
import { import {
isTileExtraEditable, isTileFeatureEditable,
supportsTileExtra, supportsTileFeature,
} from "../../tile-extra/tile-extras"; } from "../../tile-features/tile-features";
import { LovelaceTileExtraConfig } from "../../tile-extra/types"; import { LovelaceTileFeatureConfig } from "../../tile-features/types";
const EXTRAS_TYPE: LovelaceTileExtraConfig["type"][] = [ const FEATURES_TYPE: LovelaceTileFeatureConfig["type"][] = [
"cover-open-close", "cover-open-close",
"cover-tilt", "cover-tilt",
"light-brightness", "light-brightness",
@ -38,24 +38,24 @@ const EXTRAS_TYPE: LovelaceTileExtraConfig["type"][] = [
declare global { declare global {
interface HASSDomEvents { interface HASSDomEvents {
"extras-changed": { "features-changed": {
extras: LovelaceTileExtraConfig[]; features: LovelaceTileFeatureConfig[];
}; };
} }
} }
@customElement("hui-tile-card-extras-editor") @customElement("hui-tile-card-features-editor")
export class HuiTileCardExtrasEditor extends LitElement { export class HuiTileCardFeaturesEditor extends LitElement {
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: HassEntity; @property({ attribute: false }) public stateObj?: HassEntity;
@property({ attribute: false }) @property({ attribute: false })
public extras?: LovelaceTileExtraConfig[]; public features?: LovelaceTileFeatureConfig[];
@property() public label?: string; @property() public label?: string;
private _extraKeys = new WeakMap<LovelaceTileExtraConfig, string>(); private _featuresKeys = new WeakMap<LovelaceTileFeatureConfig, string>();
private _sortable?: SortableInstance; private _sortable?: SortableInstance;
@ -63,24 +63,24 @@ export class HuiTileCardExtrasEditor extends LitElement {
this._destroySortable(); this._destroySortable();
} }
private _getKey(extra: LovelaceTileExtraConfig) { private _getKey(feature: LovelaceTileFeatureConfig) {
if (!this._extraKeys.has(extra)) { if (!this._featuresKeys.has(feature)) {
this._extraKeys.set(extra, Math.random().toString()); this._featuresKeys.set(feature, Math.random().toString());
} }
return this._extraKeys.get(extra)!; return this._featuresKeys.get(feature)!;
} }
private get _supportedExtraTypes() { private get _supportedFeatureTypes() {
if (!this.stateObj) return []; if (!this.stateObj) return [];
return EXTRAS_TYPE.filter((type) => return FEATURES_TYPE.filter((type) =>
supportsTileExtra(this.stateObj!, type) supportsTileFeature(this.stateObj!, type)
); );
} }
protected render(): TemplateResult { protected render(): TemplateResult {
if (!this.extras || !this.hass) { if (!this.features || !this.hass) {
return html``; return html``;
} }
@ -89,93 +89,94 @@ export class HuiTileCardExtrasEditor extends LitElement {
<h3 slot="header"> <h3 slot="header">
<ha-svg-icon .path=${mdiListBox}></ha-svg-icon> <ha-svg-icon .path=${mdiListBox}></ha-svg-icon>
${this.hass!.localize( ${this.hass!.localize(
"ui.panel.lovelace.editor.card.tile.extras.name" "ui.panel.lovelace.editor.card.tile.features.name"
)} )}
</h3> </h3>
<div class="content"> <div class="content">
${this._supportedExtraTypes.length === 0 && this.extras.length === 0 ${this._supportedFeatureTypes.length === 0 &&
this.features.length === 0
? html` ? html`
<ha-alert type="info"> <ha-alert type="info">
${this.hass!.localize( ${this.hass!.localize(
"ui.panel.lovelace.editor.card.tile.extras.no_compatible_available" "ui.panel.lovelace.editor.card.tile.features.no_compatible_available"
)} )}
</ha-alert> </ha-alert>
` `
: null} : null}
<div class="extras"> <div class="features">
${repeat( ${repeat(
this.extras, this.features,
(extraConf) => this._getKey(extraConf), (featureConf) => this._getKey(featureConf),
(extraConf, index) => html` (featureConf, index) => html`
<div class="extra"> <div class="feature">
<div class="handle"> <div class="handle">
<ha-svg-icon .path=${mdiDrag}></ha-svg-icon> <ha-svg-icon .path=${mdiDrag}></ha-svg-icon>
</div> </div>
<div class="extra-content"> <div class="feature-content">
<div> <div>
<span> <span>
${this.hass!.localize( ${this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.extras.types.${extraConf.type}.label` `ui.panel.lovelace.editor.card.tile.features.types.${featureConf.type}.label`
)} )}
</span> </span>
${this.stateObj && ${this.stateObj &&
!supportsTileExtra(this.stateObj, extraConf.type) !supportsTileFeature(this.stateObj, featureConf.type)
? html`<span class="secondary"> ? html`<span class="secondary">
${this.hass!.localize( ${this.hass!.localize(
"ui.panel.lovelace.editor.card.tile.extras.not_compatible" "ui.panel.lovelace.editor.card.tile.features.not_compatible"
)} )}
</span>` </span>`
: null} : null}
</div> </div>
</div> </div>
${isTileExtraEditable(extraConf.type) ${isTileFeatureEditable(featureConf.type)
? html`<ha-icon-button ? html`<ha-icon-button
.label=${this.hass!.localize( .label=${this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.extras.edit` `ui.panel.lovelace.editor.card.tile.features.edit`
)} )}
.path=${mdiPencil} .path=${mdiPencil}
class="edit-icon" class="edit-icon"
.index=${index} .index=${index}
@click=${this._editExtra} @click=${this._editFeature}
></ha-icon-button>` ></ha-icon-button>`
: null} : null}
<ha-icon-button <ha-icon-button
.label=${this.hass!.localize( .label=${this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.extras.remove` `ui.panel.lovelace.editor.card.tile.features.remove`
)} )}
.path=${mdiDelete} .path=${mdiDelete}
class="remove-icon" class="remove-icon"
.index=${index} .index=${index}
@click=${this._removeExtra} @click=${this._removeFeature}
></ha-icon-button> ></ha-icon-button>
</div> </div>
` `
)} )}
</div> </div>
${this._supportedExtraTypes.length > 0 ${this._supportedFeatureTypes.length > 0
? html` ? html`
<ha-button-menu <ha-button-menu
fixed fixed
@action=${this._addExtra} @action=${this._addFeature}
@closed=${stopPropagation} @closed=${stopPropagation}
> >
<mwc-button <mwc-button
slot="trigger" slot="trigger"
outlined outlined
.label=${this.hass!.localize( .label=${this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.extras.add` `ui.panel.lovelace.editor.card.tile.features.add`
)} )}
> >
<ha-svg-icon .path=${mdiPlus} slot="icon"></ha-svg-icon> <ha-svg-icon .path=${mdiPlus} slot="icon"></ha-svg-icon>
</mwc-button> </mwc-button>
${this._supportedExtraTypes.map( ${this._supportedFeatureTypes.map(
(extraType) => html`<mwc-list-item .value=${extraType}> (featureType) => html`<mwc-list-item .value=${featureType}>
<ha-svg-icon <ha-svg-icon
slot="graphic" slot="graphic"
.path=${mdiWindowShutter} .path=${mdiWindowShutter}
></ha-svg-icon> ></ha-svg-icon>
${this.hass!.localize( ${this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.extras.types.${extraType}.label` `ui.panel.lovelace.editor.card.tile.features.types.${featureType}.label`
)} )}
</mwc-list-item>` </mwc-list-item>`
)} )}
@ -193,24 +194,27 @@ export class HuiTileCardExtrasEditor extends LitElement {
private async _createSortable() { private async _createSortable() {
const Sortable = await loadSortable(); const Sortable = await loadSortable();
this._sortable = new Sortable(this.shadowRoot!.querySelector(".extras")!, { this._sortable = new Sortable(
animation: 150, this.shadowRoot!.querySelector(".features")!,
fallbackClass: "sortable-fallback", {
handle: ".handle", animation: 150,
onChoose: (evt: SortableEvent) => { fallbackClass: "sortable-fallback",
(evt.item as any).placeholder = handle: ".handle",
document.createComment("sort-placeholder"); onChoose: (evt: SortableEvent) => {
evt.item.after((evt.item as any).placeholder); (evt.item as any).placeholder =
}, document.createComment("sort-placeholder");
onEnd: (evt: SortableEvent) => { evt.item.after((evt.item as any).placeholder);
// put back in original location },
if ((evt.item as any).placeholder) { onEnd: (evt: SortableEvent) => {
(evt.item as any).placeholder.replaceWith(evt.item); // put back in original location
delete (evt.item as any).placeholder; if ((evt.item as any).placeholder) {
} (evt.item as any).placeholder.replaceWith(evt.item);
this._rowMoved(evt); delete (evt.item as any).placeholder;
}, }
}); this._rowMoved(evt);
},
}
);
} }
private _destroySortable() { private _destroySortable() {
@ -218,22 +222,22 @@ export class HuiTileCardExtrasEditor extends LitElement {
this._sortable = undefined; this._sortable = undefined;
} }
private async _addExtra(ev: CustomEvent): Promise<void> { private async _addFeature(ev: CustomEvent): Promise<void> {
const index = ev.detail.index as number; const index = ev.detail.index as number;
if (index == null) return; if (index == null) return;
const value = this._supportedExtraTypes[index]; const value = this._supportedFeatureTypes[index];
const elClass = await getTileExtraElementClass(value); const elClass = await getTileFeatureElementClass(value);
let newExtra: LovelaceTileExtraConfig; let newFeature: LovelaceTileFeatureConfig;
if (elClass && elClass.getStubConfig) { if (elClass && elClass.getStubConfig) {
newExtra = await elClass.getStubConfig(this.hass!, this.stateObj); newFeature = await elClass.getStubConfig(this.hass!, this.stateObj);
} else { } else {
newExtra = { type: value } as LovelaceTileExtraConfig; newFeature = { type: value } as LovelaceTileFeatureConfig;
} }
const newConfigExtra = this.extras!.concat(newExtra); const newConfigFeature = this.features!.concat(newFeature);
fireEvent(this, "extras-changed", { extras: newConfigExtra }); fireEvent(this, "features-changed", { features: newConfigFeature });
} }
private _rowMoved(ev: SortableEvent): void { private _rowMoved(ev: SortableEvent): void {
@ -241,29 +245,29 @@ export class HuiTileCardExtrasEditor extends LitElement {
return; return;
} }
const newExtras = this.extras!.concat(); const newFeatures = this.features!.concat();
newExtras.splice(ev.newIndex!, 0, newExtras.splice(ev.oldIndex!, 1)[0]); newFeatures.splice(ev.newIndex!, 0, newFeatures.splice(ev.oldIndex!, 1)[0]);
fireEvent(this, "extras-changed", { extras: newExtras }); fireEvent(this, "features-changed", { features: newFeatures });
} }
private _removeExtra(ev: CustomEvent): void { private _removeFeature(ev: CustomEvent): void {
const index = (ev.currentTarget as any).index; const index = (ev.currentTarget as any).index;
const newExtras = this.extras!.concat(); const newfeatures = this.features!.concat();
newExtras.splice(index, 1); newfeatures.splice(index, 1);
fireEvent(this, "extras-changed", { extras: newExtras }); fireEvent(this, "features-changed", { features: newfeatures });
} }
private _editExtra(ev: CustomEvent): void { private _editFeature(ev: CustomEvent): void {
const index = (ev.currentTarget as any).index; const index = (ev.currentTarget as any).index;
fireEvent(this, "edit-detail-element", { fireEvent(this, "edit-detail-element", {
subElementConfig: { subElementConfig: {
index, index,
type: "tile-extra", type: "tile-feature",
elementConfig: this.extras![index], elementConfig: this.features![index],
}, },
}); });
} }
@ -296,22 +300,22 @@ export class HuiTileCardExtrasEditor extends LitElement {
ha-button-menu { ha-button-menu {
margin-top: 8px; margin-top: 8px;
} }
.extra { .feature {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.extra .handle { .feature .handle {
padding-right: 8px; padding-right: 8px;
cursor: move; cursor: move;
padding-inline-end: 8px; padding-inline-end: 8px;
padding-inline-start: initial; padding-inline-start: initial;
direction: var(--direction); direction: var(--direction);
} }
.extra .handle > * { .feature .handle > * {
pointer-events: none; pointer-events: none;
} }
.extra-content { .feature-content {
height: 60px; height: 60px;
font-size: 16px; font-size: 16px;
display: flex; display: flex;
@ -320,7 +324,7 @@ export class HuiTileCardExtrasEditor extends LitElement {
flex-grow: 1; flex-grow: 1;
} }
.extra-content div { .feature-content div {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
@ -342,6 +346,6 @@ export class HuiTileCardExtrasEditor extends LitElement {
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"hui-tile-card-extras-editor": HuiTileCardExtrasEditor; "hui-tile-card-features-editor": HuiTileCardFeaturesEditor;
} }
} }

View File

@ -6,26 +6,26 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import type { LocalizeFunc } from "../../../../common/translations/localize"; import type { LocalizeFunc } from "../../../../common/translations/localize";
import type { SchemaUnion } from "../../../../components/ha-form/types"; import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import { supportsVacuumCommand } from "../../tile-extra/hui-vacuum-commands-tile-extra"; import { supportsVacuumCommand } from "../../tile-features/hui-vacuum-commands-tile-feature";
import { import {
LovelaceTileExtraContext, LovelaceTileFeatureContext,
VacuumCommandsTileExtraConfig, VacuumCommandsTileFeatureConfig,
VACUUM_COMMANDS, VACUUM_COMMANDS,
} from "../../tile-extra/types"; } from "../../tile-features/types";
import type { LovelaceTileExtraEditor } from "../../types"; import type { LovelaceTileFeatureEditor } from "../../types";
@customElement("hui-vacuum-commands-tile-extra-editor") @customElement("hui-vacuum-commands-tile-feature-editor")
export class HuiVacuumCommandsTileExtraEditor export class HuiVacuumCommandsTileFeatureEditor
extends LitElement extends LitElement
implements LovelaceTileExtraEditor implements LovelaceTileFeatureEditor
{ {
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public context?: LovelaceTileExtraContext; @property({ attribute: false }) public context?: LovelaceTileFeatureContext;
@state() private _config?: VacuumCommandsTileExtraConfig; @state() private _config?: VacuumCommandsTileFeatureConfig;
public setConfig(config: VacuumCommandsTileExtraConfig): void { public setConfig(config: VacuumCommandsTileFeatureConfig): void {
this._config = config; this._config = config;
} }
@ -43,7 +43,7 @@ export class HuiVacuumCommandsTileExtraEditor
).map((command) => ({ ).map((command) => ({
value: command, value: command,
label: `${localize( label: `${localize(
`ui.panel.lovelace.editor.card.tile.extras.types.vacuum-commands.commands_list.${command}` `ui.panel.lovelace.editor.card.tile.features.types.vacuum-commands.commands_list.${command}`
)}`, )}`,
})), })),
}, },
@ -84,7 +84,7 @@ export class HuiVacuumCommandsTileExtraEditor
switch (schema.name) { switch (schema.name) {
case "commands": case "commands":
return this.hass!.localize( return this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.extras.types.vacuum-commands.${schema.name}` `ui.panel.lovelace.editor.card.tile.features.types.vacuum-commands.${schema.name}`
); );
default: default:
return this.hass!.localize( return this.hass!.localize(
@ -96,6 +96,6 @@ export class HuiVacuumCommandsTileExtraEditor
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"hui-vacuum-commands-tile-extra-editor": HuiVacuumCommandsTileExtraEditor; "hui-vacuum-commands-tile-feature-editor": HuiVacuumCommandsTileFeatureEditor;
} }
} }

View File

@ -27,14 +27,14 @@ import type { LovelaceGenericElementEditor } from "../types";
import "./config-elements/hui-generic-entity-row-editor"; import "./config-elements/hui-generic-entity-row-editor";
import { GUISupportError } from "./gui-support-error"; import { GUISupportError } from "./gui-support-error";
import { EditSubElementEvent, GUIModeChangedEvent } from "./types"; import { EditSubElementEvent, GUIModeChangedEvent } from "./types";
import { LovelaceTileExtraConfig } from "../tile-extra/types"; import { LovelaceTileFeatureConfig } from "../tile-features/types";
export interface ConfigChangedEvent { export interface ConfigChangedEvent {
config: config:
| LovelaceCardConfig | LovelaceCardConfig
| LovelaceRowConfig | LovelaceRowConfig
| LovelaceHeaderFooterConfig | LovelaceHeaderFooterConfig
| LovelaceTileExtraConfig; | LovelaceTileFeatureConfig;
error?: string; error?: string;
guiModeAvailable?: boolean; guiModeAvailable?: boolean;
} }
@ -53,7 +53,7 @@ export interface UIConfigChangedEvent extends Event {
| LovelaceCardConfig | LovelaceCardConfig
| LovelaceRowConfig | LovelaceRowConfig
| LovelaceHeaderFooterConfig | LovelaceHeaderFooterConfig
| LovelaceTileExtraConfig; | LovelaceTileFeatureConfig;
}; };
} }

View File

@ -10,7 +10,7 @@ import type { LovelaceHeaderFooterConfig } from "../header-footer/types";
import "./entity-row-editor/hui-row-element-editor"; import "./entity-row-editor/hui-row-element-editor";
import "./header-footer-editor/hui-header-footer-element-editor"; import "./header-footer-editor/hui-header-footer-element-editor";
import type { HuiElementEditor } from "./hui-element-editor"; import type { HuiElementEditor } from "./hui-element-editor";
import "./tile-extra/hui-tile-extra-element-editor"; import "./tile-feature-editor/hui-tile-feature-element-editor";
import type { GUIModeChangedEvent, SubElementEditorConfig } from "./types"; import type { GUIModeChangedEvent, SubElementEditorConfig } from "./types";
declare global { declare global {
@ -84,16 +84,16 @@ export class HuiSubElementEditor extends LitElement {
@GUImode-changed=${this._handleGUIModeChanged} @GUImode-changed=${this._handleGUIModeChanged}
></hui-headerfooter-element-editor> ></hui-headerfooter-element-editor>
` `
: this.config.type === "tile-extra" : this.config.type === "tile-feature"
? html` ? html`
<hui-tile-extra-element-editor <hui-tile-feature-element-editor
class="editor" class="editor"
.hass=${this.hass} .hass=${this.hass}
.value=${this.config.elementConfig} .value=${this.config.elementConfig}
.context=${this.context} .context=${this.context}
@config-changed=${this._handleConfigChanged} @config-changed=${this._handleConfigChanged}
@GUImode-changed=${this._handleGUIModeChanged} @GUImode-changed=${this._handleGUIModeChanged}
></hui-tile-extra-element-editor> ></hui-tile-feature-element-editor>
` `
: ""} : ""}
`; `;

View File

@ -1,33 +0,0 @@
import { customElement } from "lit/decorators";
import { getTileExtraElementClass } from "../../create-element/create-tile-extra-element";
import {
LovelaceTileExtraConfig,
LovelaceTileExtraContext,
} from "../../tile-extra/types";
import type { LovelaceTileExtraEditor } from "../../types";
import { HuiElementEditor } from "../hui-element-editor";
@customElement("hui-tile-extra-element-editor")
export class HuiTileExtraElementEditor extends HuiElementEditor<
LovelaceTileExtraConfig,
LovelaceTileExtraContext
> {
protected async getConfigElement(): Promise<
LovelaceTileExtraEditor | undefined
> {
const elClass = await getTileExtraElementClass(this.configElementType!);
// Check if a GUI editor exists
if (elClass && elClass.getConfigElement) {
return elClass.getConfigElement();
}
return undefined;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-tile-extra-element-editor": HuiTileExtraElementEditor;
}
}

View File

@ -0,0 +1,33 @@
import { customElement } from "lit/decorators";
import { getTileFeatureElementClass } from "../../create-element/create-tile-feature-element";
import {
LovelaceTileFeatureConfig,
LovelaceTileFeatureContext,
} from "../../tile-features/types";
import type { LovelaceTileFeatureEditor } from "../../types";
import { HuiElementEditor } from "../hui-element-editor";
@customElement("hui-tile-feature-element-editor")
export class HuiTileFeatureElementEditor extends HuiElementEditor<
LovelaceTileFeatureConfig,
LovelaceTileFeatureContext
> {
protected async getConfigElement(): Promise<
LovelaceTileFeatureEditor | undefined
> {
const elClass = await getTileFeatureElementClass(this.configElementType!);
// Check if a GUI editor exists
if (elClass && elClass.getConfigElement) {
return elClass.getConfigElement();
}
return undefined;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-tile-feature-element-editor": HuiTileFeatureElementEditor;
}
}

View File

@ -6,7 +6,7 @@ import {
} from "../../../data/lovelace"; } from "../../../data/lovelace";
import { EntityConfig, LovelaceRowConfig } from "../entity-rows/types"; import { EntityConfig, LovelaceRowConfig } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types"; import { LovelaceHeaderFooterConfig } from "../header-footer/types";
import { LovelaceTileExtraConfig } from "../tile-extra/types"; import { LovelaceTileFeatureConfig } from "../tile-features/types";
export interface YamlChangedEvent extends Event { export interface YamlChangedEvent extends Event {
detail: { detail: {
@ -78,8 +78,8 @@ export interface SubElementEditorConfig {
elementConfig?: elementConfig?:
| LovelaceRowConfig | LovelaceRowConfig
| LovelaceHeaderFooterConfig | LovelaceHeaderFooterConfig
| LovelaceTileExtraConfig; | LovelaceTileFeatureConfig;
type: "header" | "footer" | "row" | "tile-extra"; type: "header" | "footer" | "row" | "tile-feature";
} }
export interface EditSubElementEvent { export interface EditSubElementEvent {

View File

@ -1,36 +0,0 @@
export interface CoverOpenCloseTileExtraConfig {
type: "cover-open-close";
}
export interface CoverTiltTileExtraConfig {
type: "cover-tilt";
}
export interface LightBrightnessTileExtraConfig {
type: "light-brightness";
}
export const VACUUM_COMMANDS = [
"start_pause",
"stop",
"clean_spot",
"locate",
"return_home",
] as const;
export type VacuumCommand = typeof VACUUM_COMMANDS[number];
export interface VacuumCommandsTileExtraConfig {
type: "vacuum-commands";
commands?: VacuumCommand[];
}
export type LovelaceTileExtraConfig =
| CoverOpenCloseTileExtraConfig
| CoverTiltTileExtraConfig
| LightBrightnessTileExtraConfig
| VacuumCommandsTileExtraConfig;
export type LovelaceTileExtraContext = {
entity_id?: string;
};

View File

@ -15,27 +15,27 @@ import {
CoverEntityFeature, CoverEntityFeature,
} from "../../../data/cover"; } from "../../../data/cover";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceTileExtra } from "../types"; import { LovelaceTileFeature } from "../types";
import { CoverOpenCloseTileExtraConfig } from "./types"; import { CoverOpenCloseTileFeatureConfig } from "./types";
@customElement("hui-cover-open-close-tile-extra") @customElement("hui-cover-open-close-tile-feature")
class HuiCoverOpenCloseTileExtra class HuiCoverOpenCloseTileFeature
extends LitElement extends LitElement
implements LovelaceTileExtra implements LovelaceTileFeature
{ {
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: HassEntity; @property({ attribute: false }) public stateObj?: HassEntity;
@state() private _config?: CoverOpenCloseTileExtraConfig; @state() private _config?: CoverOpenCloseTileFeatureConfig;
static getStubConfig(): CoverOpenCloseTileExtraConfig { static getStubConfig(): CoverOpenCloseTileFeatureConfig {
return { return {
type: "cover-open-close", type: "cover-open-close",
}; };
} }
public setConfig(config: CoverOpenCloseTileExtraConfig): void { public setConfig(config: CoverOpenCloseTileFeatureConfig): void {
if (!config) { if (!config) {
throw new Error("Invalid configuration"); throw new Error("Invalid configuration");
} }
@ -138,6 +138,6 @@ class HuiCoverOpenCloseTileExtra
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"hui-cover-open-close-tile-extra": HuiCoverOpenCloseTileExtra; "hui-cover-open-close-tile-feature": HuiCoverOpenCloseTileFeature;
} }
} }

View File

@ -11,24 +11,27 @@ import {
CoverEntityFeature, CoverEntityFeature,
} from "../../../data/cover"; } from "../../../data/cover";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceTileExtra } from "../types"; import { LovelaceTileFeature } from "../types";
import { CoverTiltTileExtraConfig } from "./types"; import { CoverTiltTileFeatureConfig } from "./types";
@customElement("hui-cover-tilt-tile-extra") @customElement("hui-cover-tilt-tile-feature")
class HuiCoverTiltTileExtra extends LitElement implements LovelaceTileExtra { class HuiCoverTiltTileFeature
extends LitElement
implements LovelaceTileFeature
{
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: HassEntity; @property({ attribute: false }) public stateObj?: HassEntity;
@state() private _config?: CoverTiltTileExtraConfig; @state() private _config?: CoverTiltTileFeatureConfig;
static getStubConfig(): CoverTiltTileExtraConfig { static getStubConfig(): CoverTiltTileFeatureConfig {
return { return {
type: "cover-tilt", type: "cover-tilt",
}; };
} }
public setConfig(config: CoverTiltTileExtraConfig): void { public setConfig(config: CoverTiltTileFeatureConfig): void {
if (!config) { if (!config) {
throw new Error("Invalid configuration"); throw new Error("Invalid configuration");
} }
@ -127,6 +130,6 @@ class HuiCoverTiltTileExtra extends LitElement implements LovelaceTileExtra {
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"hui-cover-tilt-tile-extra": HuiCoverTiltTileExtra; "hui-cover-tilt-tile-feature": HuiCoverTiltTileFeature;
} }
} }

View File

@ -4,27 +4,27 @@ import { customElement, property, state } from "lit/decorators";
import "../../../components/tile/ha-tile-slider"; import "../../../components/tile/ha-tile-slider";
import { UNAVAILABLE } from "../../../data/entity"; import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceTileExtra } from "../types"; import { LovelaceTileFeature } from "../types";
import { LightBrightnessTileExtraConfig } from "./types"; import { LightBrightnessTileFeatureConfig } from "./types";
@customElement("hui-light-brightness-tile-extra") @customElement("hui-light-brightness-tile-feature")
class HuiLightBrightnessTileExtra class HuiLightBrightnessTileFeature
extends LitElement extends LitElement
implements LovelaceTileExtra implements LovelaceTileFeature
{ {
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: HassEntity; @property({ attribute: false }) public stateObj?: HassEntity;
@state() private _config?: LightBrightnessTileExtraConfig; @state() private _config?: LightBrightnessTileFeatureConfig;
static getStubConfig(): LightBrightnessTileExtraConfig { static getStubConfig(): LightBrightnessTileFeatureConfig {
return { return {
type: "light-brightness", type: "light-brightness",
}; };
} }
public setConfig(config: LightBrightnessTileExtraConfig): void { public setConfig(config: LightBrightnessTileFeatureConfig): void {
if (!config) { if (!config) {
throw new Error("Invalid configuration"); throw new Error("Invalid configuration");
} }
@ -84,6 +84,6 @@ class HuiLightBrightnessTileExtra
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"hui-light-brightness-tile-extra": HuiLightBrightnessTileExtra; "hui-light-brightness-tile-feature": HuiLightBrightnessTileFeature;
} }
} }

View File

@ -22,10 +22,10 @@ import {
VacuumEntityFeature, VacuumEntityFeature,
} from "../../../data/vacuum"; } from "../../../data/vacuum";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceTileExtra, LovelaceTileExtraEditor } from "../types"; import { LovelaceTileFeature, LovelaceTileFeatureEditor } from "../types";
import { import {
VacuumCommand, VacuumCommand,
VacuumCommandsTileExtraConfig, VacuumCommandsTileFeatureConfig,
VACUUM_COMMANDS, VACUUM_COMMANDS,
} from "./types"; } from "./types";
@ -112,21 +112,21 @@ export const VACUUM_COMMANDS_BUTTONS: Record<
}), }),
}; };
@customElement("hui-vacuum-commands-tile-extra") @customElement("hui-vacuum-commands-tile-feature")
class HuiVacuumCommandTileExtra class HuiVacuumCommandTileFeature
extends LitElement extends LitElement
implements LovelaceTileExtra implements LovelaceTileFeature
{ {
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: HassEntity; @property({ attribute: false }) public stateObj?: HassEntity;
@state() private _config?: VacuumCommandsTileExtraConfig; @state() private _config?: VacuumCommandsTileFeatureConfig;
static getStubConfig( static getStubConfig(
_, _,
stateObj?: HassEntity stateObj?: HassEntity
): VacuumCommandsTileExtraConfig { ): VacuumCommandsTileFeatureConfig {
return { return {
type: "vacuum-commands", type: "vacuum-commands",
commands: stateObj commands: stateObj
@ -137,14 +137,14 @@ class HuiVacuumCommandTileExtra
}; };
} }
public static async getConfigElement(): Promise<LovelaceTileExtraEditor> { public static async getConfigElement(): Promise<LovelaceTileFeatureEditor> {
await import( await import(
"../editor/config-elements/hui-vacuum-commands-tile-extra-editor" "../editor/config-elements/hui-vacuum-commands-tile-feature-editor"
); );
return document.createElement("hui-vacuum-commands-tile-extra-editor"); return document.createElement("hui-vacuum-commands-tile-feature-editor");
} }
public setConfig(config: VacuumCommandsTileExtraConfig): void { public setConfig(config: VacuumCommandsTileFeatureConfig): void {
if (!config) { if (!config) {
throw new Error("Invalid configuration"); throw new Error("Invalid configuration");
} }
@ -215,6 +215,6 @@ class HuiVacuumCommandTileExtra
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"hui-vacuum-commands-tile-extra": HuiVacuumCommandTileExtra; "hui-vacuum-commands-tile-feature": HuiVacuumCommandTileFeature;
} }
} }

View File

@ -3,13 +3,13 @@ import { computeDomain } from "../../../common/entity/compute_domain";
import { supportsFeature } from "../../../common/entity/supports-feature"; import { supportsFeature } from "../../../common/entity/supports-feature";
import { CoverEntityFeature } from "../../../data/cover"; import { CoverEntityFeature } from "../../../data/cover";
import { lightSupportsBrightness } from "../../../data/light"; import { lightSupportsBrightness } from "../../../data/light";
import { supportsVacuumCommand } from "./hui-vacuum-commands-tile-extra"; import { supportsVacuumCommand } from "./hui-vacuum-commands-tile-feature";
import { LovelaceTileExtraConfig, VACUUM_COMMANDS } from "./types"; import { LovelaceTileFeatureConfig, VACUUM_COMMANDS } from "./types";
type TileExtraType = LovelaceTileExtraConfig["type"]; type TileFeatureType = LovelaceTileFeatureConfig["type"];
export type SupportsTileExtra = (stateObj: HassEntity) => boolean; export type SupportsTileFeature = (stateObj: HassEntity) => boolean;
const TILE_EXTRAS_SUPPORT: Record<TileExtraType, SupportsTileExtra> = { const TILE_FEATURES_SUPPORT: Record<TileFeatureType, SupportsTileFeature> = {
"cover-open-close": (stateObj) => "cover-open-close": (stateObj) =>
computeDomain(stateObj.entity_id) === "cover" && computeDomain(stateObj.entity_id) === "cover" &&
(supportsFeature(stateObj, CoverEntityFeature.OPEN) || (supportsFeature(stateObj, CoverEntityFeature.OPEN) ||
@ -26,17 +26,19 @@ const TILE_EXTRAS_SUPPORT: Record<TileExtraType, SupportsTileExtra> = {
VACUUM_COMMANDS.some((c) => supportsVacuumCommand(stateObj, c)), VACUUM_COMMANDS.some((c) => supportsVacuumCommand(stateObj, c)),
}; };
const TILE_EXTRAS_EDITABLE: Set<TileExtraType> = new Set(["vacuum-commands"]); const TILE_FEATURE_EDITABLE: Set<TileFeatureType> = new Set([
"vacuum-commands",
]);
export const supportsTileExtra = ( export const supportsTileFeature = (
stateObj: HassEntity, stateObj: HassEntity,
extra: TileExtraType feature: TileFeatureType
): boolean => { ): boolean => {
const supportFunction = TILE_EXTRAS_SUPPORT[extra] as const supportFunction = TILE_FEATURES_SUPPORT[feature] as
| SupportsTileExtra | SupportsTileFeature
| undefined; | undefined;
return !supportFunction || supportFunction(stateObj); return !supportFunction || supportFunction(stateObj);
}; };
export const isTileExtraEditable = (extra: TileExtraType): boolean => export const isTileFeatureEditable = (feature: TileFeatureType): boolean =>
TILE_EXTRAS_EDITABLE.has(extra); TILE_FEATURE_EDITABLE.has(feature);

View File

@ -0,0 +1,36 @@
export interface CoverOpenCloseTileFeatureConfig {
type: "cover-open-close";
}
export interface CoverTiltTileFeatureConfig {
type: "cover-tilt";
}
export interface LightBrightnessTileFeatureConfig {
type: "light-brightness";
}
export const VACUUM_COMMANDS = [
"start_pause",
"stop",
"clean_spot",
"locate",
"return_home",
] as const;
export type VacuumCommand = typeof VACUUM_COMMANDS[number];
export interface VacuumCommandsTileFeatureConfig {
type: "vacuum-commands";
commands?: VacuumCommand[];
}
export type LovelaceTileFeatureConfig =
| CoverOpenCloseTileFeatureConfig
| CoverTiltTileFeatureConfig
| LightBrightnessTileFeatureConfig
| VacuumCommandsTileFeatureConfig;
export type LovelaceTileFeatureContext = {
entity_id?: string;
};

View File

@ -8,7 +8,7 @@ import { FrontendLocaleData } from "../../data/translation";
import { Constructor, HomeAssistant } from "../../types"; import { Constructor, HomeAssistant } from "../../types";
import { LovelaceRow, LovelaceRowConfig } from "./entity-rows/types"; import { LovelaceRow, LovelaceRowConfig } from "./entity-rows/types";
import { LovelaceHeaderFooterConfig } from "./header-footer/types"; import { LovelaceHeaderFooterConfig } from "./header-footer/types";
import { LovelaceTileExtraConfig } from "./tile-extra/types"; import { LovelaceTileFeatureConfig } from "./tile-features/types";
declare global { declare global {
// eslint-disable-next-line // eslint-disable-next-line
@ -96,21 +96,22 @@ export interface LovelaceGenericElementEditor<C = any> extends HTMLElement {
focusYamlEditor?: () => void; focusYamlEditor?: () => void;
} }
export interface LovelaceTileExtra extends HTMLElement { export interface LovelaceTileFeature extends HTMLElement {
hass?: HomeAssistant; hass?: HomeAssistant;
stateObj?: HassEntity; stateObj?: HassEntity;
setConfig(config: LovelaceTileExtraConfig); setConfig(config: LovelaceTileFeatureConfig);
} }
export interface LovelaceTileExtraConstructor export interface LovelaceTileFeatureConstructor
extends Constructor<LovelaceTileExtra> { extends Constructor<LovelaceTileFeature> {
getConfigElement?: () => LovelaceTileExtraEditor; getConfigElement?: () => LovelaceTileFeatureEditor;
getStubConfig?: ( getStubConfig?: (
hass: HomeAssistant, hass: HomeAssistant,
stateObj?: HassEntity stateObj?: HassEntity
) => LovelaceTileExtraConfig; ) => LovelaceTileFeatureConfig;
} }
export interface LovelaceTileExtraEditor extends LovelaceGenericElementEditor { export interface LovelaceTileFeatureEditor
setConfig(config: LovelaceTileExtraConfig): void; extends LovelaceGenericElementEditor {
setConfig(config: LovelaceTileFeatureConfig): void;
} }

View File

@ -4224,13 +4224,13 @@
"appearance": "Appearance", "appearance": "Appearance",
"default_color": "Default color (state)", "default_color": "Default color (state)",
"show_entity_picture": "Show entity picture", "show_entity_picture": "Show entity picture",
"extras": { "features": {
"name": "Extras", "name": "Features",
"not_compatible": "Not compatible", "not_compatible": "Not compatible",
"no_compatible_available": "No compatible extras available for this entity", "no_compatible_available": "No compatible features available for this entity",
"add": "Add extra", "add": "Add feature",
"edit": "Edit extra", "edit": "Edit feature",
"remove": "Remove extra", "remove": "Remove feature",
"types": { "types": {
"cover-open-close": { "cover-open-close": {
"label": "Cover open/close" "label": "Cover open/close"