Compare commits

..

20 Commits

Author SHA1 Message Date
Paul Bottein
a16f4952ab Simplify scroll lock 2025-10-24 15:44:06 +02:00
Paul Bottein
a4e2070d0f Simplify scroll lock 2025-10-24 15:37:36 +02:00
Wendelin
fef2ff6392 Merge branch 'dev' of github.com:home-assistant/frontend into bottom-sheet-swipe-close 2025-10-24 09:59:47 +02:00
Wendelin
459a0bd178 Merge branch 'add-automation-new-design' of github.com:home-assistant/frontend into bottom-sheet-swipe-close 2025-10-16 16:31:27 +02:00
Wendelin
d808c63c55 Merge branch 'dev' of github.com:home-assistant/frontend into add-automation-new-design 2025-10-16 16:29:10 +02:00
Wendelin
80135af9ec Fix bottom sheet padding 2025-10-16 15:29:27 +02:00
Wendelin
848b737a92 update target picker selector 2025-10-16 15:20:08 +02:00
Wendelin
50d4fae14a Merge branch 'add-automation-new-design' of github.com:home-assistant/frontend into bottom-sheet-swipe-close 2025-10-16 15:16:36 +02:00
Wendelin
1da3570a6f fix translations, scroll issues, RTL 2025-10-16 15:01:57 +02:00
Wendelin
6c4046c842 add swipe to close for bottom sheet 2025-10-16 14:07:41 +02:00
Wendelin
e97b04b5b9 Fix device translation 2025-10-16 10:19:28 +02:00
Wendelin
6dbfb60825 Add keybindings and blocks search separation 2025-10-16 09:44:46 +02:00
Wendelin
ba2881b0bf Add max-height 2025-10-15 17:00:06 +02:00
Wendelin
e42be13682 fix height 2025-10-15 16:53:32 +02:00
Wendelin
bf8dacb7a4 Add tabs 2025-10-15 16:50:18 +02:00
Wendelin
a23fc8fcba revert merge 2025-10-14 17:07:48 +02:00
Wendelin
0ba88246a1 Merge branch 'dev' of github.com:home-assistant/frontend into add-automation-new-design 2025-10-14 17:01:30 +02:00
Wendelin
6529b31b65 WIP new add dialog 2025-10-14 16:59:46 +02:00
Wendelin
866518477f Merge branch 'dev' of github.com:home-assistant/frontend into add-automation-new-design 2025-10-13 13:13:41 +02:00
Wendelin
f831f876de WIP new add automation element 2025-10-10 14:48:18 +02:00
16 changed files with 130 additions and 303 deletions

View File

@@ -1,6 +1,6 @@
import "@home-assistant/webawesome/dist/components/drawer/drawer";
import { css, html, LitElement, type PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators";
import { customElement, property, query, state } from "lit/decorators";
import { haStyleScrollbar } from "../resources/styles";
export const BOTTOM_SHEET_ANIMATION_DURATION_MS = 300;
@@ -14,6 +14,12 @@ export class HaBottomSheet extends LitElement {
@state() private _drawerOpen = false;
@query("#drawer") private _drawer!: HTMLElement;
private _resizeStartY = 0;
private _resizeDelta = 0;
private _handleAfterHide() {
this.open = false;
const ev = new Event("closed", {
@@ -33,19 +39,82 @@ export class HaBottomSheet extends LitElement {
render() {
return html`
<wa-drawer
id="drawer"
placement="bottom"
.open=${this._drawerOpen}
@wa-after-hide=${this._handleAfterHide}
without-header
@touchstart=${this._handleTouchStart}
>
<slot name="header"></slot>
<div class="body ha-scrollbar">
<div id="body" class="body ha-scrollbar">
<slot></slot>
</div>
</wa-drawer>
`;
}
private _handleTouchStart = (ev: TouchEvent) => {
// Check if any element inside drawer in the composed path has scrollTop > 0
for (const path of ev.composedPath()) {
const el = path as HTMLElement;
if (el === this._drawer) {
break;
}
if (el.scrollTop > 0) {
return;
}
}
this._startResizing(ev.touches[0].clientY);
};
private _startResizing(clientY: number) {
// register event listeners for drag handling
document.addEventListener("touchmove", this._handleMouseMove, {
passive: false,
});
document.addEventListener("touchend", this._endResizing);
document.addEventListener("touchcancel", this._endResizing);
this._resizeStartY = clientY;
}
private _handleMouseMove = (ev: TouchEvent) => {
this._resizeDelta = this._resizeStartY - ev.touches[0].clientY;
if (this._resizeDelta < 0) {
ev.preventDefault();
requestAnimationFrame(() => {
this.style.setProperty(
"--dialog-transform",
`translateY(${this._resizeDelta * -1}px)`
);
});
}
};
private _endResizing = () => {
this._unregisterResizeHandlers();
if (this._resizeDelta > -50) {
this.style.removeProperty("--dialog-transform");
return;
}
this._drawerOpen = false;
};
private _unregisterResizeHandlers = () => {
document.removeEventListener("touchmove", this._handleMouseMove);
document.removeEventListener("touchend", this._unregisterResizeHandlers);
document.removeEventListener("touchcancel", this._unregisterResizeHandlers);
};
disconnectedCallback() {
super.disconnectedCallback();
this._unregisterResizeHandlers();
}
static styles = [
haStyleScrollbar,
css`
@@ -59,6 +128,7 @@ export class HaBottomSheet extends LitElement {
wa-drawer::part(dialog) {
max-height: var(--ha-bottom-sheet-max-height, 90vh);
align-items: center;
transform: var(--dialog-transform);
}
wa-drawer::part(body) {
max-width: var(--ha-bottom-sheet-max-width);
@@ -90,6 +160,11 @@ export class HaBottomSheet extends LitElement {
max-width: 100%;
display: flex;
flex-direction: column;
padding: var(
--ha-bottom-sheet-padding,
0 var(--safe-area-inset-right) var(--safe-area-inset-bottom)
var(--safe-area-inset-left)
);
}
`,
];
@@ -99,4 +174,8 @@ declare global {
interface HTMLElementTagNameMap {
"ha-bottom-sheet": HaBottomSheet;
}
interface HASSDomEvents {
"bottom-sheet-lock-resize-changed": boolean;
}
}

View File

@@ -248,7 +248,7 @@ export class HaFilterDevices extends LitElement {
}
search-input-outlined {
display: block;
padding: var(--ha-space-1) var(--ha-space-2) 0;
padding: 0 8px;
}
`,
];

View File

@@ -199,7 +199,7 @@ export class HaFilterDomains extends LitElement {
}
search-input-outlined {
display: block;
padding: var(--ha-space-1) var(--ha-space-2) 0;
padding: 0 8px;
}
`,
];

View File

@@ -264,7 +264,7 @@ export class HaFilterEntities extends LitElement {
}
search-input-outlined {
display: block;
padding: var(--ha-space-1) var(--ha-space-2) 0;
padding: 0 8px;
}
`,
];

View File

@@ -217,7 +217,7 @@ export class HaFilterIntegrations extends LitElement {
}
search-input-outlined {
display: block;
padding: var(--ha-space-1) var(--ha-space-2) 0;
padding: 0 8px;
}
`,
];

View File

@@ -256,7 +256,7 @@ export class HaFilterLabels extends SubscribeMixin(LitElement) {
}
search-input-outlined {
display: block;
padding: var(--ha-space-1) var(--ha-space-2) 0;
padding: 0 8px;
}
`,
];

View File

@@ -29,7 +29,6 @@ import memoizeOne from "memoize-one";
import { fireEvent } from "../common/dom/fire_event";
import { toggleAttribute } from "../common/dom/toggle_attribute";
import { stringCompare } from "../common/string/compare";
import { computeRTL } from "../common/util/compute_rtl";
import { throttle } from "../common/util/throttle";
import { subscribeFrontendUserData } from "../data/frontend";
import type { ActionHandlerDetail } from "../data/lovelace/action_handler";
@@ -537,17 +536,11 @@ class HaSidebar extends SubscribeMixin(LitElement) {
}
private _renderUserItem(selectedPanel: string) {
const isRTL = computeRTL(this.hass);
return html`
<ha-md-list-item
href="/profile"
type="link"
class=${classMap({
user: true,
selected: selectedPanel === "profile",
rtl: isRTL,
})}
class="user ${selectedPanel === "profile" ? " selected" : ""}"
@mouseenter=${this._itemMouseEnter}
@mouseleave=${this._itemMouseLeave}
>
@@ -673,7 +666,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
tooltip.style.display = "block";
tooltip.style.position = "fixed";
tooltip.style.top = `${top}px`;
tooltip.style.left = `calc(${item.offsetLeft + item.clientWidth + 8}px + var(--safe-area-inset-left, var(--ha-space-0)))`;
tooltip.style.left = `calc(${item.offsetLeft + item.clientWidth + 8}px + var(--safe-area-inset-left, 0px))`;
}
private _hideTooltip() {
@@ -712,17 +705,13 @@ class HaSidebar extends SubscribeMixin(LitElement) {
background-color: var(--sidebar-background-color);
width: 100%;
box-sizing: border-box;
padding-bottom: calc(
14px + var(--safe-area-inset-bottom, var(--ha-space-0))
);
padding-bottom: calc(14px + var(--safe-area-inset-bottom, 0px));
}
.menu {
height: calc(
var(--header-height) + var(--safe-area-inset-top, var(--ha-space-0))
);
height: calc(var(--header-height) + var(--safe-area-inset-top, 0px));
box-sizing: border-box;
display: flex;
padding: 0 var(--ha-space-1);
padding: 0 4px;
border-bottom: 1px solid transparent;
white-space: nowrap;
font-weight: var(--ha-font-weight-normal);
@@ -737,17 +726,13 @@ class HaSidebar extends SubscribeMixin(LitElement) {
);
font-size: var(--ha-font-size-xl);
align-items: center;
padding-left: calc(
var(--ha-space-1) + var(--safe-area-inset-left, var(--ha-space-0))
);
padding-inline-start: calc(
var(--ha-space-1) + var(--safe-area-inset-left, var(--ha-space-0))
);
padding-left: calc(4px + var(--safe-area-inset-left, 0px));
padding-inline-start: calc(4px + var(--safe-area-inset-left, 0px));
padding-inline-end: initial;
padding-top: var(--safe-area-inset-top, var(--ha-space-0));
padding-top: var(--safe-area-inset-top, 0px);
}
:host([expanded]) .menu {
width: calc(256px + var(--safe-area-inset-left, var(--ha-space-0)));
width: calc(256px + var(--safe-area-inset-left, 0px));
}
:host([narrow][expanded]) .menu {
width: 100%;
@@ -763,8 +748,8 @@ class HaSidebar extends SubscribeMixin(LitElement) {
display: none;
}
:host([narrow]) .title {
margin: var(--ha-space-0);
padding: var(--ha-space-0) var(--ha-space-4);
margin: 0;
padding: 0 16px;
}
:host([expanded]) .title {
display: initial;
@@ -776,16 +761,13 @@ class HaSidebar extends SubscribeMixin(LitElement) {
ha-fade-in,
ha-md-list {
height: calc(
100% - var(--header-height) - var(
--safe-area-inset-top,
var(--ha-space-0)
) -
100% - var(--header-height) - var(--safe-area-inset-top, 0px) -
132px
);
}
ha-fade-in {
padding: var(--ha-space-1) var(--ha-space-0);
padding: 4px 0;
box-sizing: border-box;
display: flex;
justify-content: center;
@@ -795,29 +777,29 @@ class HaSidebar extends SubscribeMixin(LitElement) {
ha-md-list {
overflow-x: hidden;
background: none;
margin-left: var(--safe-area-inset-left, var(--ha-space-0));
margin-left: var(--safe-area-inset-left, 0px);
}
ha-md-list-item {
flex-shrink: 0;
box-sizing: border-box;
margin: var(--ha-space-1);
margin: 4px;
border-radius: var(--ha-border-radius-sm);
--md-list-item-one-line-container-height: var(--ha-space-10);
--md-list-item-one-line-container-height: 40px;
--md-list-item-top-space: 0;
--md-list-item-bottom-space: 0;
width: var(--ha-space-12);
width: 48px;
position: relative;
--md-list-item-label-text-color: var(--sidebar-text-color);
--md-list-item-leading-space: var(--ha-space-3);
--md-list-item-trailing-space: var(--ha-space-3);
--md-list-item-leading-icon-size: var(--ha-space-6);
--md-list-item-leading-space: 12px;
--md-list-item-trailing-space: 12px;
--md-list-item-leading-icon-size: 24px;
}
:host([expanded]) ha-md-list-item {
width: 248px;
}
:host([narrow][expanded]) ha-md-list-item {
width: calc(240px - var(--safe-area-inset-left, var(--ha-space-0)));
width: calc(240px - var(--safe-area-inset-left, 0px));
}
ha-md-list-item.selected {
@@ -841,7 +823,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
ha-icon[slot="start"],
ha-svg-icon[slot="start"] {
width: var(--ha-space-6);
width: 24px;
flex-shrink: 0;
color: var(--sidebar-icon-color);
}
@@ -874,7 +856,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
display: flex;
justify-content: center;
align-items: center;
min-width: var(--ha-space-2);
min-width: 8px;
border-radius: var(--ha-border-radius-xl);
font-weight: var(--ha-font-weight-normal);
line-height: normal;
@@ -885,26 +867,22 @@ class HaSidebar extends SubscribeMixin(LitElement) {
ha-svg-icon + .badge {
position: absolute;
top: var(--ha-space-1);
top: 4px;
left: 26px;
border-radius: var(--ha-border-radius-md);
font-size: 0.65em;
line-height: var(--ha-line-height-expanded);
padding: var(--ha-space-0) var(--ha-space-1);
padding: 0 4px;
}
ha-md-list-item.user {
--md-list-item-leading-icon-size: var(--ha-space-10);
--md-list-item-leading-space: var(--ha-space-1);
}
ha-md-list-item.user.rtl {
--md-list-item-leading-space: var(--ha-space-3);
--md-list-item-leading-icon-size: 40px;
--md-list-item-leading-space: 4px;
}
ha-user-badge {
flex-shrink: 0;
margin-right: calc(var(--ha-space-2) * -1);
margin-right: -8px;
}
.spacer {
@@ -916,7 +894,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
color: var(--sidebar-text-color);
font-size: var(--ha-font-size-m);
font-weight: var(--ha-font-weight-medium);
padding: var(--ha-space-4);
padding: 16px;
white-space: nowrap;
}
@@ -928,7 +906,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
white-space: nowrap;
color: var(--sidebar-background-color);
background-color: var(--sidebar-text-color);
padding: var(--ha-space-1);
padding: 4px;
font-weight: var(--ha-font-weight-medium);
}

View File

@@ -16,7 +16,6 @@ import memoizeOne from "memoize-one";
import { computeCssColor } from "../../common/color/compute-color";
import { hex2rgb } from "../../common/color/convert-color";
import { fireEvent } from "../../common/dom/fire_event";
import { slugify } from "../../common/string/slugify";
import {
computeDeviceName,
computeDeviceNameDisplay,
@@ -103,7 +102,7 @@ export class HaTargetPickerValueChip extends LitElement {
${this.type === "entity"
? nothing
: html`<span role="gridcell">
<ha-tooltip .for="expand-${slugify(this.itemId)}"
<ha-tooltip .for="expand-${this.itemId}"
>${this.hass.localize(
`ui.components.target-picker.expand_${this.type}_id`
)}
@@ -115,13 +114,13 @@ export class HaTargetPickerValueChip extends LitElement {
)}
.path=${mdiUnfoldMoreVertical}
hide-title
.id="expand-${slugify(this.itemId)}"
.id="expand-${this.itemId}"
.type=${this.type}
@click=${this._handleExpand}
></ha-icon-button>
</span>`}
<span role="gridcell">
<ha-tooltip .for="remove-${slugify(this.itemId)}">
<ha-tooltip .for="remove-${this.itemId}">
${this.hass.localize(
`ui.components.target-picker.remove_${this.type}_id`
)}
@@ -131,7 +130,7 @@ export class HaTargetPickerValueChip extends LitElement {
.label=${this.hass.localize("ui.components.target-picker.remove")}
.path=${mdiClose}
hide-title
.id="remove-${slugify(this.itemId)}"
.id="remove-${this.itemId}"
.type=${this.type}
@click=${this._removeItem}
></ha-icon-button>

View File

@@ -846,8 +846,7 @@ class DialogAddAutomationElement
items: true,
blank:
!this._selectedGroup && !this._filter && this._tab === "groups",
"empty-search":
!items?.length && !filteredBlockItems?.length && this._filter,
"empty-search": !items?.length && this._filter,
hidden:
this._narrow &&
!this._selectedGroup &&
@@ -856,7 +855,7 @@ class DialogAddAutomationElement
})}
@scroll=${this._onItemsScroll}
>
${filteredBlockItems
${filteredBlockItems && filteredBlockItems.length
? this._renderItemList(
this.hass.localize(`ui.panel.config.automation.editor.blocks`),
filteredBlockItems
@@ -889,7 +888,7 @@ class DialogAddAutomationElement
}
private _renderItemList(title, items?: ListItem[]) {
if (!items || !items.length) {
if (!items) {
return nothing;
}
@@ -1118,6 +1117,11 @@ class DialogAddAutomationElement
padding: 0;
}
.items ha-md-list,
.groups {
padding-bottom: max(var(--safe-area-inset-bottom), var(--ha-space-3));
}
.groups {
overflow: auto;
flex: 3;
@@ -1202,11 +1206,6 @@ class DialogAddAutomationElement
border: 1px solid var(--ha-color-border-neutral-quiet);
}
.items ha-md-list,
.groups {
padding-bottom: max(var(--safe-area-inset-bottom), var(--ha-space-3));
}
.items.blank {
justify-content: center;
}

View File

@@ -115,8 +115,8 @@ export class HaConfigLabels extends LitElement {
borderRadius: "var(--ha-border-radius-md)",
border: "1px solid var(--outline-color)",
boxSizing: "border-box",
width: "var(--ha-space-5)",
height: "var(--ha-space-5)",
width: "20px",
height: "20px",
})}
></div>`
: nothing,

View File

@@ -1,126 +0,0 @@
import { 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 "../../../components/ha-control-number-buttons";
import { isUnavailableState } from "../../../data/entity";
import {
MediaPlayerEntityFeature,
type MediaPlayerEntity,
} from "../../../data/media-player";
import type { HomeAssistant } from "../../../types";
import type { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { cardFeatureStyles } from "./common/card-feature-styles";
import type {
LovelaceCardFeatureContext,
MediaPlayerVolumeButtonsCardFeatureConfig,
} from "./types";
import { clamp } from "../../../common/number/clamp";
export const supportsMediaPlayerVolumeButtonsCardFeature = (
hass: HomeAssistant,
context: LovelaceCardFeatureContext
) => {
const stateObj = context.entity_id
? hass.states[context.entity_id]
: undefined;
if (!stateObj) return false;
const domain = computeDomain(stateObj.entity_id);
return (
domain === "media_player" &&
supportsFeature(stateObj, MediaPlayerEntityFeature.VOLUME_SET)
);
};
@customElement("hui-media-player-volume-buttons-card-feature")
class HuiMediaPlayerVolumeButtonsCardFeature
extends LitElement
implements LovelaceCardFeature
{
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public context?: LovelaceCardFeatureContext;
@state() private _config?: MediaPlayerVolumeButtonsCardFeatureConfig;
private get _stateObj() {
if (!this.hass || !this.context || !this.context.entity_id) {
return undefined;
}
return this.hass.states[this.context.entity_id] as
| MediaPlayerEntity
| undefined;
}
static getStubConfig(): MediaPlayerVolumeButtonsCardFeatureConfig {
return {
type: "media-player-volume-buttons",
step: 5,
};
}
public static async getConfigElement(): Promise<LovelaceCardFeatureEditor> {
await import(
"../editor/config-elements/hui-media-player-volume-buttons-card-feature-editor"
);
return document.createElement(
"hui-media-player-volume-buttons-card-feature-editor"
);
}
public setConfig(config: MediaPlayerVolumeButtonsCardFeatureConfig): void {
if (!config) {
throw new Error("Invalid configuration");
}
this._config = config;
}
protected render() {
if (
!this._config ||
!this.hass ||
!this.context ||
!this._stateObj ||
!supportsMediaPlayerVolumeButtonsCardFeature(this.hass, this.context)
) {
return nothing;
}
const position =
this._stateObj.attributes.volume_level != null
? Math.round(this._stateObj.attributes.volume_level * 100)
: undefined;
return html`
<ha-control-number-buttons
.disabled=${!this._stateObj || isUnavailableState(this._stateObj.state)}
.locale=${this.hass.locale}
min="0"
max="100"
.step=${this._config.step ?? 5}
.value=${position}
unit="%"
@value-changed=${this._valueChanged}
></ha-control-number-buttons>
`;
}
private _valueChanged(ev: CustomEvent) {
ev.stopPropagation();
this.hass!.callService("media_player", "volume_set", {
entity_id: this._stateObj!.entity_id,
volume_level: clamp(ev.detail.value, 0, 100) / 100,
});
}
static get styles() {
return cardFeatureStyles;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-media-player-volume-buttons-card-feature": HuiMediaPlayerVolumeButtonsCardFeature;
}
}

View File

@@ -50,11 +50,6 @@ export interface MediaPlayerVolumeSliderCardFeatureConfig {
type: "media-player-volume-slider";
}
export interface MediaPlayerVolumeButtonsCardFeatureConfig {
type: "media-player-volume-buttons";
step?: number;
}
export interface FanDirectionCardFeatureConfig {
type: "fan-direction";
}
@@ -257,7 +252,6 @@ export type LovelaceCardFeatureConfig =
| LockCommandsCardFeatureConfig
| LockOpenDoorCardFeatureConfig
| MediaPlayerPlaybackCardFeatureConfig
| MediaPlayerVolumeButtonsCardFeatureConfig
| MediaPlayerVolumeSliderCardFeatureConfig
| NumericInputCardFeatureConfig
| SelectOptionsCardFeatureConfig

View File

@@ -23,7 +23,6 @@ import "../card-features/hui-light-color-temp-card-feature";
import "../card-features/hui-lock-commands-card-feature";
import "../card-features/hui-lock-open-door-card-feature";
import "../card-features/hui-media-player-playback-card-feature";
import "../card-features/hui-media-player-volume-buttons-card-feature";
import "../card-features/hui-media-player-volume-slider-card-feature";
import "../card-features/hui-numeric-input-card-feature";
import "../card-features/hui-select-options-card-feature";
@@ -73,7 +72,6 @@ const TYPES = new Set<LovelaceCardFeatureConfig["type"]>([
"lock-commands",
"lock-open-door",
"media-player-playback",
"media-player-volume-buttons",
"media-player-volume-slider",
"numeric-input",
"select-options",

View File

@@ -48,7 +48,6 @@ import { supportsLightColorTempCardFeature } from "../../card-features/hui-light
import { supportsLockCommandsCardFeature } from "../../card-features/hui-lock-commands-card-feature";
import { supportsLockOpenDoorCardFeature } from "../../card-features/hui-lock-open-door-card-feature";
import { supportsMediaPlayerPlaybackCardFeature } from "../../card-features/hui-media-player-playback-card-feature";
import { supportsMediaPlayerVolumeButtonsCardFeature } from "../../card-features/hui-media-player-volume-buttons-card-feature";
import { supportsMediaPlayerVolumeSliderCardFeature } from "../../card-features/hui-media-player-volume-slider-card-feature";
import { supportsNumericInputCardFeature } from "../../card-features/hui-numeric-input-card-feature";
import { supportsSelectOptionsCardFeature } from "../../card-features/hui-select-options-card-feature";
@@ -103,7 +102,6 @@ const UI_FEATURE_TYPES = [
"lock-commands",
"lock-open-door",
"media-player-playback",
"media-player-volume-buttons",
"media-player-volume-slider",
"numeric-input",
"select-options",
@@ -133,7 +131,6 @@ const EDITABLES_FEATURE_TYPES = new Set<UiFeatureTypes>([
"fan-preset-modes",
"humidifier-modes",
"lawn-mower-commands",
"media-player-volume-buttons",
"numeric-input",
"select-options",
"trend-graph",
@@ -174,7 +171,6 @@ const SUPPORTS_FEATURE_TYPES: Record<
"lock-commands": supportsLockCommandsCardFeature,
"lock-open-door": supportsLockOpenDoorCardFeature,
"media-player-playback": supportsMediaPlayerPlaybackCardFeature,
"media-player-volume-buttons": supportsMediaPlayerVolumeButtonsCardFeature,
"media-player-volume-slider": supportsMediaPlayerVolumeSliderCardFeature,
"numeric-input": supportsNumericInputCardFeature,
"select-options": supportsSelectOptionsCardFeature,

View File

@@ -1,86 +0,0 @@
import { html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
import type {
LovelaceCardFeatureContext,
MediaPlayerVolumeButtonsCardFeatureConfig,
} from "../../card-features/types";
import type { LovelaceCardFeatureEditor } from "../../types";
@customElement("hui-media-player-volume-buttons-card-feature-editor")
export class HuiMediaPlayerVolumeButtonsCardFeatureEditor
extends LitElement
implements LovelaceCardFeatureEditor
{
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public context?: LovelaceCardFeatureContext;
@state() private _config?: MediaPlayerVolumeButtonsCardFeatureConfig;
public setConfig(config: MediaPlayerVolumeButtonsCardFeatureConfig): void {
this._config = config;
}
private _schema = memoizeOne(
() =>
[
{
name: "step",
selector: {
number: {
mode: "slider",
step: 1,
min: 1,
max: 100,
unit_of_measurement: "%",
},
},
},
] as const
);
protected render() {
if (!this.hass || !this._config) {
return nothing;
}
const data: MediaPlayerVolumeButtonsCardFeatureConfig = {
type: "media-player-volume-buttons",
step: this._config.step ?? 5,
};
const schema = this._schema();
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${schema}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
`;
}
private _valueChanged(ev: CustomEvent): void {
fireEvent(this, "config-changed", { config: ev.detail.value });
}
private _computeLabelCallback = (
schema: SchemaUnion<ReturnType<typeof this._schema>>
) =>
this.hass!.localize(
`ui.panel.lovelace.editor.features.types.media-player-volume-buttons.${schema.name}`
);
}
declare global {
interface HTMLElementTagNameMap {
"hui-media-player-volume-buttons-card-feature-editor": HuiMediaPlayerVolumeButtonsCardFeatureEditor;
}
}

View File

@@ -8151,10 +8151,6 @@
"media-player-playback": {
"label": "Media player playback controls"
},
"media-player-volume-buttons": {
"label": "Media player volume buttons",
"step": "Step size"
},
"media-player-volume-slider": {
"label": "Media player volume slider"
},