mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-09 10:59:50 +00:00
Automation editor: overflow changes and style fixes (#26744)
* Fix for width also for blueprint editor
* Fix overflow menus
* Fix option icons
* Fix iOS bottom sheet flickering and drag handle
* Fix mobile padding
* Fix padding in sidebar
* Fix overflow placement
* Add new a11y sort
* Remove overflow in rows
* Fix a11y select row
* Revert "Fix a11y select row"
This reverts commit 54260c4a37.
* Fix option padding on blueprint
---------
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { mdiChevronUp } from "@mdi/js";
|
||||
import type { TemplateResult } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import "./ha-icon-button";
|
||||
|
||||
@@ -16,12 +16,18 @@ export class HaAutomationRow extends LitElement {
|
||||
@property({ type: Boolean, reflect: true })
|
||||
public selected = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true, attribute: "sort-selected" })
|
||||
public sortSelected = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true })
|
||||
public disabled = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true, attribute: "building-block" })
|
||||
public buildingBlock = false;
|
||||
|
||||
@query(".row")
|
||||
private _rowElement?: HTMLDivElement;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div
|
||||
@@ -66,15 +72,40 @@ export class HaAutomationRow extends LitElement {
|
||||
if (ev.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
if (ev.key !== "Enter" && ev.key !== " ") {
|
||||
|
||||
if (
|
||||
ev.key !== "Enter" &&
|
||||
ev.key !== " " &&
|
||||
!(
|
||||
(this.sortSelected || ev.altKey) &&
|
||||
(ev.key === "ArrowUp" || ev.key === "ArrowDown")
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (ev.key === "ArrowUp" || ev.key === "ArrowDown") {
|
||||
if (ev.key === "ArrowUp") {
|
||||
fireEvent(this, "move-up");
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "move-down");
|
||||
return;
|
||||
}
|
||||
if (this.sortSelected && (ev.key === "Enter" || ev.key === " ")) {
|
||||
fireEvent(this, "stop-sort-selection");
|
||||
return;
|
||||
}
|
||||
|
||||
this.click();
|
||||
}
|
||||
|
||||
public focus() {
|
||||
requestAnimationFrame(() => this._rowElement?.focus());
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
@@ -134,6 +165,11 @@ export class HaAutomationRow extends LitElement {
|
||||
overflow-wrap: anywhere;
|
||||
margin: 0 12px;
|
||||
}
|
||||
:host([sort-selected]) .row {
|
||||
box-shadow:
|
||||
0px 0px 8px 4px rgba(var(--rgb-accent-color), 0.8),
|
||||
inset 0px 2px 8px 4px rgba(var(--rgb-accent-color), 0.4);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -144,5 +180,6 @@ declare global {
|
||||
|
||||
interface HASSDomEvents {
|
||||
"toggle-collapsed": undefined;
|
||||
"stop-sort-selection": undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ export class HaBottomSheet extends LitElement {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 7;
|
||||
padding-bottom: 76px;
|
||||
}
|
||||
.handle-wrapper .handle::after {
|
||||
content: "";
|
||||
|
||||
@@ -16,9 +16,23 @@ export class HaMdButtonMenu extends LitElement {
|
||||
|
||||
@property() public positioning?: "fixed" | "absolute" | "popover";
|
||||
|
||||
@property({ attribute: "anchor-corner" }) public anchorCorner:
|
||||
| "start-start"
|
||||
| "start-end"
|
||||
| "end-start"
|
||||
| "end-end" = "end-start";
|
||||
|
||||
@property({ attribute: "menu-corner" }) public menuCorner:
|
||||
| "start-start"
|
||||
| "start-end"
|
||||
| "end-start"
|
||||
| "end-end" = "start-start";
|
||||
|
||||
@property({ type: Boolean, attribute: "has-overflow" }) public hasOverflow =
|
||||
false;
|
||||
|
||||
@property({ type: Boolean }) public quick = false;
|
||||
|
||||
@query("ha-md-menu", true) private _menu!: HaMdMenu;
|
||||
|
||||
public get items() {
|
||||
@@ -39,8 +53,11 @@ export class HaMdButtonMenu extends LitElement {
|
||||
<slot name="trigger" @slotchange=${this._setTriggerAria}></slot>
|
||||
</div>
|
||||
<ha-md-menu
|
||||
.quick=${this.quick}
|
||||
.positioning=${this.positioning}
|
||||
.hasOverflow=${this.hasOverflow}
|
||||
.anchorCorner=${this.anchorCorner}
|
||||
.menuCorner=${this.menuCorner}
|
||||
@opening=${this._handleOpening}
|
||||
@closing=${this._handleClosing}
|
||||
>
|
||||
|
||||
@@ -53,6 +53,7 @@ export default class HaAutomationActionEditor extends LitElement {
|
||||
this.disabled || (this.action.enabled === false && !this.yamlMode),
|
||||
yaml: yamlMode,
|
||||
indent: this.indent,
|
||||
card: !this.inSidebar,
|
||||
})}
|
||||
>
|
||||
${yamlMode
|
||||
|
||||
@@ -26,6 +26,7 @@ import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
||||
import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter";
|
||||
import { handleStructError } from "../../../../common/structs/handle-errors";
|
||||
import "../../../../components/ha-automation-row";
|
||||
import type { HaAutomationRow } from "../../../../components/ha-automation-row";
|
||||
import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-expansion-panel";
|
||||
import "../../../../components/ha-icon-button";
|
||||
@@ -153,6 +154,9 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
@property({ type: Boolean, attribute: "sidebar" })
|
||||
public optionsInSidebar = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "sort-selected" })
|
||||
public sortSelected = false;
|
||||
|
||||
@storage({
|
||||
key: "automationClipboard",
|
||||
state: false,
|
||||
@@ -186,6 +190,9 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
@query("ha-automation-action-editor")
|
||||
private _actionEditor?: HaAutomationActionEditor;
|
||||
|
||||
@query("ha-automation-row")
|
||||
private _automationRowElement?: HaAutomationRow;
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(changedProperties);
|
||||
|
||||
@@ -254,13 +261,16 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
<ha-svg-icon .path=${mdiAlertCircleCheck}></ha-svg-icon>
|
||||
</ha-tooltip>`
|
||||
: nothing}
|
||||
|
||||
<ha-md-button-menu
|
||||
${!this.optionsInSidebar
|
||||
? html`<ha-md-button-menu
|
||||
quick
|
||||
slot="icons"
|
||||
@click=${preventDefaultStopPropagation}
|
||||
@keydown=${stopPropagation}
|
||||
@closed=${stopPropagation}
|
||||
positioning="fixed"
|
||||
anchor-corner="end-end"
|
||||
menu-corner="start-end"
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
@@ -268,8 +278,7 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`<ha-md-menu-item .clickAction=${this._runAction}>
|
||||
<ha-md-menu-item .clickAction=${this._runAction}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.run"
|
||||
)}
|
||||
@@ -316,8 +325,7 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
"ui.panel.config.automation.editor.triggers.cut"
|
||||
)}
|
||||
<ha-svg-icon slot="start" .path=${mdiContentCut}></ha-svg-icon>
|
||||
</ha-md-menu-item>`
|
||||
: nothing}
|
||||
</ha-md-menu-item>
|
||||
|
||||
<ha-md-menu-item
|
||||
.clickAction=${this._moveUp}
|
||||
@@ -331,22 +339,20 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
.clickAction=${this._moveDown}
|
||||
.disabled=${this.disabled || !!this.last}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.automation.editor.move_down")}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.move_down"
|
||||
)}
|
||||
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
||||
></ha-md-menu-item>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`<ha-md-menu-item
|
||||
<ha-md-menu-item
|
||||
.clickAction=${this._toggleYamlMode}
|
||||
.disabled=${!this._uiModeAvailable || !!this._warnings}
|
||||
>
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="start"
|
||||
.path=${mdiPlaylistEdit}
|
||||
></ha-svg-icon>
|
||||
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
|
||||
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
||||
@@ -382,10 +388,9 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
slot="start"
|
||||
.path=${mdiDelete}
|
||||
></ha-svg-icon>
|
||||
</ha-md-menu-item>`
|
||||
</ha-md-menu-item>
|
||||
</ha-md-button-menu>`
|
||||
: nothing}
|
||||
</ha-md-button-menu>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`${this._warnings
|
||||
? html`<ha-automation-editor-warning
|
||||
@@ -447,6 +452,7 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
...ACTION_BUILDING_BLOCKS,
|
||||
...ACTION_COMBINED_BLOCKS,
|
||||
].includes(blockType!)}
|
||||
.sortSelected=${this.sortSelected}
|
||||
>${this._renderRow()}</ha-automation-row
|
||||
>`
|
||||
: html`
|
||||
@@ -697,10 +703,12 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
this._collapsed = false;
|
||||
|
||||
if (this.narrow) {
|
||||
requestAnimationFrame(() => {
|
||||
this.scrollIntoView({
|
||||
block: "start",
|
||||
behavior: "smooth",
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,6 +759,10 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this._automationRowElement?.focus();
|
||||
}
|
||||
|
||||
static styles = rowStyles;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ export default class HaAutomationAction extends LitElement {
|
||||
|
||||
@state() private _showReorder = false;
|
||||
|
||||
@state() private _rowSortSelected?: number;
|
||||
|
||||
@state()
|
||||
@storage({
|
||||
key: "automationClipboard",
|
||||
@@ -94,7 +96,7 @@ export default class HaAutomationAction extends LitElement {
|
||||
@item-removed=${this._actionRemoved}
|
||||
@item-cloned=${this._actionCloned}
|
||||
>
|
||||
<div class="rows">
|
||||
<div class="rows ${!this.optionsInSidebar ? "no-sidebar" : ""}">
|
||||
${repeat(
|
||||
this.actions,
|
||||
(action) => this._getKey(action),
|
||||
@@ -115,10 +117,20 @@ export default class HaAutomationAction extends LitElement {
|
||||
.hass=${this.hass}
|
||||
?highlight=${this.highlightedActions?.includes(action)}
|
||||
.optionsInSidebar=${this.optionsInSidebar}
|
||||
.sortSelected=${this._rowSortSelected === idx}
|
||||
@stop-sort-selection=${this._stopSortSelection}
|
||||
>
|
||||
${this._showReorder && !this.disabled
|
||||
? html`
|
||||
<div class="handle" slot="icons">
|
||||
<div
|
||||
tabindex="0"
|
||||
class="handle ${this._rowSortSelected === idx
|
||||
? "active"
|
||||
: ""}"
|
||||
slot="icons"
|
||||
@keydown=${this._handleDragKeydown}
|
||||
.index=${idx}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiDrag}></ha-svg-icon>
|
||||
</div>
|
||||
`
|
||||
@@ -264,18 +276,30 @@ export default class HaAutomationAction extends LitElement {
|
||||
return this._actionKeys.get(action)!;
|
||||
}
|
||||
|
||||
private _moveUp(ev) {
|
||||
private async _moveUp(ev) {
|
||||
ev.stopPropagation();
|
||||
const index = (ev.target as any).index;
|
||||
if (!(ev.target as HaAutomationActionRow).first) {
|
||||
const newIndex = index - 1;
|
||||
this._move(index, newIndex);
|
||||
if (this._rowSortSelected === index) {
|
||||
this._rowSortSelected = newIndex;
|
||||
}
|
||||
ev.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private _moveDown(ev) {
|
||||
private async _moveDown(ev) {
|
||||
ev.stopPropagation();
|
||||
const index = (ev.target as any).index;
|
||||
if (!(ev.target as HaAutomationActionRow).last) {
|
||||
const newIndex = index + 1;
|
||||
this._move(index, newIndex);
|
||||
if (this._rowSortSelected === index) {
|
||||
this._rowSortSelected = newIndex;
|
||||
}
|
||||
ev.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private _move(oldIndex: number, newIndex: number) {
|
||||
@@ -371,6 +395,20 @@ export default class HaAutomationAction extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _handleDragKeydown(ev: KeyboardEvent) {
|
||||
if (ev.key === "Enter" || ev.key === " ") {
|
||||
ev.stopPropagation();
|
||||
this._rowSortSelected =
|
||||
this._rowSortSelected === undefined
|
||||
? (ev.target as any).index
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private _stopSortSelection() {
|
||||
this._rowSortSelected = undefined;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
automationRowsStyles,
|
||||
css`
|
||||
|
||||
@@ -28,6 +28,8 @@ export default class HaAutomationConditionEditor extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "sidebar" }) public inSidebar = false;
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public selected = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "supported" }) public uiSupported =
|
||||
@@ -55,6 +57,7 @@ export default class HaAutomationConditionEditor extends LitElement {
|
||||
(this.condition.enabled === false && !this.yamlMode),
|
||||
yaml: yamlMode,
|
||||
indent: this.indent,
|
||||
card: !this.inSidebar,
|
||||
})}
|
||||
>
|
||||
${yamlMode
|
||||
|
||||
@@ -26,6 +26,7 @@ import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
||||
import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter";
|
||||
import { handleStructError } from "../../../../common/structs/handle-errors";
|
||||
import "../../../../components/ha-automation-row";
|
||||
import type { HaAutomationRow } from "../../../../components/ha-automation-row";
|
||||
import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-expansion-panel";
|
||||
import "../../../../components/ha-icon-button";
|
||||
@@ -115,6 +116,9 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "sort-selected" })
|
||||
public sortSelected = false;
|
||||
|
||||
@state() private _collapsed = true;
|
||||
|
||||
@state() private _warnings?: string[];
|
||||
@@ -145,6 +149,9 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
@query("ha-automation-condition-editor")
|
||||
public conditionEditor?: HaAutomationConditionEditor;
|
||||
|
||||
@query("ha-automation-row")
|
||||
private _automationRowElement?: HaAutomationRow;
|
||||
|
||||
private _renderRow() {
|
||||
return html`
|
||||
<ha-svg-icon
|
||||
@@ -160,12 +167,16 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
|
||||
<slot name="icons" slot="icons"></slot>
|
||||
|
||||
<ha-md-button-menu
|
||||
${!this.optionsInSidebar
|
||||
? html`<ha-md-button-menu
|
||||
quick
|
||||
slot="icons"
|
||||
@click=${preventDefaultStopPropagation}
|
||||
@keydown=${stopPropagation}
|
||||
@closed=${stopPropagation}
|
||||
positioning="fixed"
|
||||
anchor-corner="end-end"
|
||||
menu-corner="start-end"
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
@@ -174,8 +185,6 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
>
|
||||
</ha-icon-button>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`
|
||||
<ha-md-menu-item .clickAction=${this._testCondition}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.conditions.test"
|
||||
@@ -226,8 +235,6 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
)}
|
||||
<ha-svg-icon slot="start" .path=${mdiContentCut}></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
`
|
||||
: nothing}
|
||||
|
||||
<ha-md-menu-item
|
||||
.clickAction=${this._moveUp}
|
||||
@@ -241,12 +248,13 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
.clickAction=${this._moveDown}
|
||||
.disabled=${this.disabled || this.last}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.automation.editor.move_down")}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.move_down"
|
||||
)}
|
||||
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
||||
></ha-md-menu-item>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`<ha-md-menu-item
|
||||
<ha-md-menu-item
|
||||
.clickAction=${this._toggleYamlMode}
|
||||
.disabled=${this._uiSupported(this.condition.condition) ||
|
||||
!!this._warnings}
|
||||
@@ -254,10 +262,7 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="start"
|
||||
.path=${mdiPlaylistEdit}
|
||||
></ha-svg-icon>
|
||||
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
|
||||
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
||||
@@ -293,10 +298,9 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
slot="start"
|
||||
.path=${mdiDelete}
|
||||
></ha-svg-icon>
|
||||
</ha-md-menu-item>`
|
||||
</ha-md-menu-item>
|
||||
</ha-md-button-menu>`
|
||||
: nothing}
|
||||
</ha-md-button-menu>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`${this._warnings
|
||||
? html`<ha-automation-editor-warning
|
||||
@@ -356,6 +360,7 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
.buildingBlock=${CONDITION_BUILDING_BLOCKS.includes(
|
||||
this.condition.condition
|
||||
)}
|
||||
.sortSelected=${this.sortSelected}
|
||||
>${this._renderRow()}</ha-automation-row
|
||||
>`
|
||||
: html`
|
||||
@@ -668,10 +673,12 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
this._collapsed = false;
|
||||
|
||||
if (this.narrow) {
|
||||
requestAnimationFrame(() => {
|
||||
this.scrollIntoView({
|
||||
block: "start",
|
||||
behavior: "smooth",
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -688,6 +695,10 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this._automationRowElement?.focus();
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
rowStyles,
|
||||
|
||||
@@ -46,6 +46,8 @@ export default class HaAutomationCondition extends LitElement {
|
||||
|
||||
@state() private _showReorder = false;
|
||||
|
||||
@state() private _rowSortSelected?: number;
|
||||
|
||||
@state()
|
||||
@storage({
|
||||
key: "automationClipboard",
|
||||
@@ -171,7 +173,7 @@ export default class HaAutomationCondition extends LitElement {
|
||||
@item-removed=${this._conditionRemoved}
|
||||
@item-cloned=${this._conditionCloned}
|
||||
>
|
||||
<div class="rows">
|
||||
<div class="rows ${!this.optionsInSidebar ? "no-sidebar" : ""}">
|
||||
${repeat(
|
||||
this.conditions.filter((c) => typeof c === "object"),
|
||||
(condition) => this._getKey(condition),
|
||||
@@ -193,10 +195,20 @@ export default class HaAutomationCondition extends LitElement {
|
||||
.hass=${this.hass}
|
||||
?highlight=${this.highlightedConditions?.includes(cond)}
|
||||
.optionsInSidebar=${this.optionsInSidebar}
|
||||
.sortSelected=${this._rowSortSelected === idx}
|
||||
@stop-sort-selection=${this._stopSortSelection}
|
||||
>
|
||||
${this._showReorder && !this.disabled
|
||||
? html`
|
||||
<div class="handle" slot="icons">
|
||||
<div
|
||||
tabindex="0"
|
||||
class="handle ${this._rowSortSelected === idx
|
||||
? "active"
|
||||
: ""}"
|
||||
slot="icons"
|
||||
@keydown=${this._handleDragKeydown}
|
||||
.index=${idx}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiDrag}></ha-svg-icon>
|
||||
</div>
|
||||
`
|
||||
@@ -285,15 +297,27 @@ export default class HaAutomationCondition extends LitElement {
|
||||
private _moveUp(ev) {
|
||||
ev.stopPropagation();
|
||||
const index = (ev.target as any).index;
|
||||
if (!(ev.target as HaAutomationConditionRow).first) {
|
||||
const newIndex = index - 1;
|
||||
this._move(index, newIndex);
|
||||
if (this._rowSortSelected === index) {
|
||||
this._rowSortSelected = newIndex;
|
||||
}
|
||||
ev.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private _moveDown(ev) {
|
||||
ev.stopPropagation();
|
||||
const index = (ev.target as any).index;
|
||||
if (!(ev.target as HaAutomationConditionRow).last) {
|
||||
const newIndex = index + 1;
|
||||
this._move(index, newIndex);
|
||||
if (this._rowSortSelected === index) {
|
||||
this._rowSortSelected = newIndex;
|
||||
}
|
||||
ev.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private _move(oldIndex: number, newIndex: number) {
|
||||
@@ -390,6 +414,20 @@ export default class HaAutomationCondition extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _handleDragKeydown(ev: KeyboardEvent) {
|
||||
if (ev.key === "Enter" || ev.key === " ") {
|
||||
ev.stopPropagation();
|
||||
this._rowSortSelected =
|
||||
this._rowSortSelected === undefined
|
||||
? (ev.target as any).index
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private _stopSortSelection() {
|
||||
this._rowSortSelected = undefined;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
automationRowsStyles,
|
||||
css`
|
||||
|
||||
@@ -17,6 +17,7 @@ import { preventDefaultStopPropagation } from "../../../../common/dom/prevent_de
|
||||
import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
||||
import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter";
|
||||
import "../../../../components/ha-automation-row";
|
||||
import type { HaAutomationRow } from "../../../../components/ha-automation-row";
|
||||
import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-expansion-panel";
|
||||
import "../../../../components/ha-icon-button";
|
||||
@@ -63,6 +64,9 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
@property({ type: Boolean, attribute: "sidebar" })
|
||||
public optionsInSidebar = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "sort-selected" })
|
||||
public sortSelected = false;
|
||||
|
||||
@state() private _expanded = false;
|
||||
|
||||
@state() private _selected = false;
|
||||
@@ -79,6 +83,9 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
@query("ha-automation-action")
|
||||
private _actionElement?: HaAutomationAction;
|
||||
|
||||
@query("ha-automation-row")
|
||||
private _automationRowElement?: HaAutomationRow;
|
||||
|
||||
private _expandedChanged(ev) {
|
||||
if (ev.currentTarget.id !== "option") {
|
||||
return;
|
||||
@@ -123,14 +130,17 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
|
||||
<slot name="icons" slot="icons"></slot>
|
||||
|
||||
${this.option
|
||||
${this.option && !this.optionsInSidebar
|
||||
? html`
|
||||
<ha-md-button-menu
|
||||
quick
|
||||
slot="icons"
|
||||
@click=${preventDefaultStopPropagation}
|
||||
@closed=${stopPropagation}
|
||||
@keydown=${stopPropagation}
|
||||
positioning="fixed"
|
||||
anchor-corner="end-end"
|
||||
menu-corner="start-end"
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
@@ -138,8 +148,6 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`
|
||||
<ha-md-menu-item
|
||||
@click=${this._renameOption}
|
||||
.disabled=${this.disabled}
|
||||
@@ -147,10 +155,7 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.rename"
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiRenameBox}
|
||||
></ha-svg-icon>
|
||||
<ha-svg-icon slot="start" .path=${mdiRenameBox}></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
|
||||
<ha-md-menu-item
|
||||
@@ -161,12 +166,10 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
"ui.panel.config.automation.editor.actions.duplicate"
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
slot="start"
|
||||
.path=${mdiContentDuplicate}
|
||||
></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
`
|
||||
: nothing}
|
||||
|
||||
<ha-md-menu-item
|
||||
@click=${this._moveUp}
|
||||
@@ -175,7 +178,7 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.move_up"
|
||||
)}
|
||||
<ha-svg-icon slot="graphic" .path=${mdiArrowUp}></ha-svg-icon>
|
||||
<ha-svg-icon slot="start" .path=${mdiArrowUp}></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
|
||||
<ha-md-menu-item
|
||||
@@ -185,11 +188,10 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.move_down"
|
||||
)}
|
||||
<ha-svg-icon slot="graphic" .path=${mdiArrowDown}></ha-svg-icon>
|
||||
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`<ha-md-menu-item
|
||||
<ha-md-menu-item
|
||||
@click=${this._removeOption}
|
||||
class="warning"
|
||||
.disabled=${this.disabled}
|
||||
@@ -199,11 +201,10 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
)}
|
||||
<ha-svg-icon
|
||||
class="warning"
|
||||
slot="graphic"
|
||||
slot="start"
|
||||
.path=${mdiDelete}
|
||||
></ha-svg-icon>
|
||||
</ha-md-menu-item>`
|
||||
: nothing}
|
||||
</ha-md-menu-item>
|
||||
</ha-md-button-menu>
|
||||
`
|
||||
: nothing}
|
||||
@@ -215,6 +216,7 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
return html`<div
|
||||
class=${classMap({
|
||||
"card-content": true,
|
||||
card: !this.optionsInSidebar,
|
||||
indent: this.optionsInSidebar,
|
||||
selected: this._selected,
|
||||
hidden: this.optionsInSidebar && this._collapsed,
|
||||
@@ -271,6 +273,7 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
.selected=${this._selected}
|
||||
@click=${this._toggleSidebar}
|
||||
@toggle-collapsed=${this._toggleCollapse}
|
||||
.sortSelected=${this.sortSelected}
|
||||
>${this._renderRow()}</ha-automation-row
|
||||
>`
|
||||
: html`
|
||||
@@ -398,10 +401,12 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
this._collapsed = false;
|
||||
|
||||
if (this.narrow) {
|
||||
requestAnimationFrame(() => {
|
||||
this.scrollIntoView({
|
||||
block: "start",
|
||||
behavior: "smooth",
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,6 +447,10 @@ export default class HaAutomationOptionRow extends LitElement {
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this._automationRowElement?.focus();
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
rowStyles,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { mdiDrag, mdiPlus } from "@mdi/js";
|
||||
import deepClone from "deep-clone-simple";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { LitElement, html, nothing } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, queryAll, state } from "lit/decorators";
|
||||
import { repeat } from "lit/directives/repeat";
|
||||
import { storage } from "../../../../common/decorators/storage";
|
||||
@@ -37,6 +37,8 @@ export default class HaAutomationOption extends LitElement {
|
||||
|
||||
@state() private _showReorder = false;
|
||||
|
||||
@state() private _rowSortSelected?: number;
|
||||
|
||||
@state()
|
||||
@storage({
|
||||
key: "automationClipboard",
|
||||
@@ -83,7 +85,7 @@ export default class HaAutomationOption extends LitElement {
|
||||
@item-removed=${this._optionRemoved}
|
||||
@item-cloned=${this._optionCloned}
|
||||
>
|
||||
<div class="rows">
|
||||
<div class="rows ${!this.optionsInSidebar ? "no-sidebar" : ""}">
|
||||
${repeat(
|
||||
this.options,
|
||||
(option) => this._getKey(option),
|
||||
@@ -102,10 +104,20 @@ export default class HaAutomationOption extends LitElement {
|
||||
@value-changed=${this._optionChanged}
|
||||
.hass=${this.hass}
|
||||
.optionsInSidebar=${this.optionsInSidebar}
|
||||
.sortSelected=${this._rowSortSelected === idx}
|
||||
@stop-sort-selection=${this._stopSortSelection}
|
||||
>
|
||||
${this._showReorder && !this.disabled
|
||||
? html`
|
||||
<div class="handle" slot="icons">
|
||||
<div
|
||||
tabindex="0"
|
||||
class="handle ${this._rowSortSelected === idx
|
||||
? "active"
|
||||
: ""}"
|
||||
slot="icons"
|
||||
@keydown=${this._handleDragKeydown}
|
||||
.index=${idx}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiDrag}></ha-svg-icon>
|
||||
</div>
|
||||
`
|
||||
@@ -207,15 +219,27 @@ export default class HaAutomationOption extends LitElement {
|
||||
private _moveUp(ev) {
|
||||
ev.stopPropagation();
|
||||
const index = (ev.target as any).index;
|
||||
if (!(ev.target as HaAutomationOptionRow).first) {
|
||||
const newIndex = index - 1;
|
||||
this._move(index, newIndex);
|
||||
if (this._rowSortSelected === index) {
|
||||
this._rowSortSelected = newIndex;
|
||||
}
|
||||
ev.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private _moveDown(ev) {
|
||||
ev.stopPropagation();
|
||||
const index = (ev.target as any).index;
|
||||
if (!(ev.target as HaAutomationOptionRow).last) {
|
||||
const newIndex = index + 1;
|
||||
this._move(index, newIndex);
|
||||
if (this._rowSortSelected === index) {
|
||||
this._rowSortSelected = newIndex;
|
||||
}
|
||||
ev.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private _move(oldIndex: number, newIndex: number) {
|
||||
@@ -304,7 +328,28 @@ export default class HaAutomationOption extends LitElement {
|
||||
fireEvent(this, "show-default-actions");
|
||||
};
|
||||
|
||||
static styles = automationRowsStyles;
|
||||
private _handleDragKeydown(ev: KeyboardEvent) {
|
||||
if (ev.key === "Enter" || ev.key === " ") {
|
||||
ev.stopPropagation();
|
||||
this._rowSortSelected =
|
||||
this._rowSortSelected === undefined
|
||||
? (ev.target as any).index
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private _stopSortSelection() {
|
||||
this._rowSortSelected = undefined;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
automationRowsStyles,
|
||||
css`
|
||||
:host([root]) .rows {
|
||||
padding-right: 8px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@@ -67,10 +67,13 @@ export default class HaAutomationSidebarCard extends LitElement {
|
||||
<slot slot="subtitle" name="subtitle"></slot>
|
||||
<slot name="overflow-menu" slot="actionItems">
|
||||
<ha-md-button-menu
|
||||
quick
|
||||
@click=${this._openOverflowMenu}
|
||||
@keydown=${stopPropagation}
|
||||
@closed=${stopPropagation}
|
||||
.positioning=${this.narrow ? "absolute" : "fixed"}
|
||||
anchor-corner="end-end"
|
||||
menu-corner="start-end"
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
|
||||
@@ -182,6 +182,7 @@ export default class HaAutomationSidebarCondition extends LitElement {
|
||||
@value-changed=${this._valueChangedSidebar}
|
||||
.disabled=${this.disabled}
|
||||
@ui-mode-not-available=${this._handleUiModeNotAvailable}
|
||||
sidebar
|
||||
></ha-automation-condition-editor> `}
|
||||
</ha-automation-sidebar-card>`;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ export default class HaAutomationSidebarOption extends LitElement {
|
||||
"ui.panel.config.automation.editor.actions.duplicate"
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
slot="start"
|
||||
.path=${mdiContentDuplicate}
|
||||
></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
|
||||
@@ -193,6 +193,7 @@ export default class HaAutomationSidebarTrigger extends LitElement {
|
||||
.yamlMode=${this.yamlMode}
|
||||
.disabled=${this.disabled}
|
||||
@ui-mode-not-available=${this._handleUiModeNotAvailable}
|
||||
sidebar
|
||||
></ha-automation-trigger-editor>
|
||||
</ha-automation-sidebar-card>
|
||||
`;
|
||||
|
||||
@@ -54,7 +54,7 @@ export const editorStyles = css`
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
.card-content.card {
|
||||
padding: 16px;
|
||||
}
|
||||
.card-content.yaml {
|
||||
@@ -69,7 +69,7 @@ export const indentStyle = css`
|
||||
.selector-row,
|
||||
:host([indent]) ha-form {
|
||||
margin-left: 12px;
|
||||
padding: 12px 24px 16px 16px;
|
||||
padding: 12px 20px 16px 16px;
|
||||
border-left: 2px solid var(--ha-color-border-neutral-quiet);
|
||||
border-bottom: 2px solid var(--ha-color-border-neutral-quiet);
|
||||
border-radius: 0;
|
||||
@@ -168,7 +168,6 @@ export const manualEditorStyles = css`
|
||||
@media all and (max-width: 870px) {
|
||||
.split-view {
|
||||
gap: 0;
|
||||
margin-right: -8px;
|
||||
}
|
||||
.sidebar {
|
||||
height: 0;
|
||||
@@ -197,6 +196,9 @@ export const automationRowsStyles = css`
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.rows.no-sidebar {
|
||||
margin-right: 0;
|
||||
}
|
||||
.sortable-ghost {
|
||||
background: none;
|
||||
border-radius: var(--ha-card-border-radius, var(--ha-border-radius-lg));
|
||||
@@ -209,9 +211,19 @@ export const automationRowsStyles = css`
|
||||
scroll-margin-top: 48px;
|
||||
}
|
||||
.handle {
|
||||
padding: 12px;
|
||||
margin: 4px;
|
||||
padding: 8px;
|
||||
cursor: move; /* fallback if grab cursor is unsupported */
|
||||
cursor: grab;
|
||||
border-radius: var(--ha-border-radius-pill);
|
||||
}
|
||||
.handle:focus {
|
||||
outline: var(--wa-focus-ring);
|
||||
background: var(--ha-color-fill-neutral-quiet-resting);
|
||||
}
|
||||
.handle.active {
|
||||
outline: var(--wa-focus-ring);
|
||||
background: var(--ha-color-fill-neutral-normal-active);
|
||||
}
|
||||
.handle ha-svg-icon {
|
||||
pointer-events: none;
|
||||
|
||||
@@ -29,6 +29,8 @@ export default class HaAutomationTriggerEditor extends LitElement {
|
||||
|
||||
@property({ type: Boolean, attribute: "show-id" }) public showId = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "sidebar" }) public inSidebar = false;
|
||||
|
||||
@query("ha-yaml-editor") public yamlEditor?: HaYamlEditor;
|
||||
|
||||
protected render() {
|
||||
@@ -47,6 +49,7 @@ export default class HaAutomationTriggerEditor extends LitElement {
|
||||
this.trigger.enabled === false &&
|
||||
!this.yamlMode),
|
||||
yaml: yamlMode,
|
||||
card: !this.inSidebar,
|
||||
})}
|
||||
>
|
||||
${yamlMode
|
||||
|
||||
@@ -28,6 +28,7 @@ import { handleStructError } from "../../../../common/structs/handle-errors";
|
||||
import { debounce } from "../../../../common/util/debounce";
|
||||
import "../../../../components/ha-alert";
|
||||
import "../../../../components/ha-automation-row";
|
||||
import type { HaAutomationRow } from "../../../../components/ha-automation-row";
|
||||
import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-expansion-panel";
|
||||
import "../../../../components/ha-icon-button";
|
||||
@@ -115,6 +116,9 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
@property({ type: Boolean, attribute: "sidebar" })
|
||||
public optionsInSidebar = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "sort-selected" })
|
||||
public sortSelected = false;
|
||||
|
||||
@state() private _yamlMode = false;
|
||||
|
||||
@state() private _triggered?: Record<string, unknown>;
|
||||
@@ -132,6 +136,9 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
@query("ha-automation-trigger-editor")
|
||||
public triggerEditor?: HaAutomationTriggerEditor;
|
||||
|
||||
@query("ha-automation-row")
|
||||
private _automationRowElement?: HaAutomationRow;
|
||||
|
||||
@storage({
|
||||
key: "automationClipboard",
|
||||
state: false,
|
||||
@@ -165,21 +172,23 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
|
||||
<slot name="icons" slot="icons"></slot>
|
||||
|
||||
<ha-md-button-menu
|
||||
${!this.optionsInSidebar
|
||||
? html`<ha-md-button-menu
|
||||
quick
|
||||
slot="icons"
|
||||
@click=${preventDefaultStopPropagation}
|
||||
@keydown=${stopPropagation}
|
||||
@closed=${stopPropagation}
|
||||
positioning="fixed"
|
||||
anchor-corner="end-end"
|
||||
menu-corner="start-end"
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass.localize("ui.common.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`<ha-md-menu-item
|
||||
<ha-md-menu-item
|
||||
.clickAction=${this._renameTrigger}
|
||||
.disabled=${this.disabled || type === "list"}
|
||||
>
|
||||
@@ -232,8 +241,7 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
"ui.panel.config.automation.editor.triggers.cut"
|
||||
)}
|
||||
<ha-svg-icon slot="start" .path=${mdiContentCut}></ha-svg-icon>
|
||||
</ha-md-menu-item>`
|
||||
: nothing}
|
||||
</ha-md-menu-item>
|
||||
|
||||
<ha-md-menu-item
|
||||
.clickAction=${this._moveUp}
|
||||
@@ -247,12 +255,12 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
.clickAction=${this._moveDown}
|
||||
.disabled=${this.disabled || this.last}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.automation.editor.move_down")}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.move_down"
|
||||
)}
|
||||
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
|
||||
></ha-md-menu-item>
|
||||
|
||||
${!this.optionsInSidebar
|
||||
? html`
|
||||
<ha-md-menu-item
|
||||
.clickAction=${this._toggleYamlMode}
|
||||
.disabled=${!supported || !!this._warnings}
|
||||
@@ -260,10 +268,7 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.automation.editor.edit_${!yamlMode ? "yaml" : "ui"}`
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="start"
|
||||
.path=${mdiPlaylistEdit}
|
||||
></ha-svg-icon>
|
||||
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
|
||||
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
|
||||
@@ -301,9 +306,8 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
.path=${mdiDelete}
|
||||
></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
`
|
||||
</ha-md-button-menu>`
|
||||
: nothing}
|
||||
</ha-md-button-menu>
|
||||
${!this.optionsInSidebar
|
||||
? html`${this._warnings
|
||||
? html`<ha-automation-editor-warning
|
||||
@@ -345,6 +349,7 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
this.trigger.enabled === false}
|
||||
@click=${this._toggleSidebar}
|
||||
.selected=${this._selected}
|
||||
.sortSelected=${this.sortSelected}
|
||||
>${this._selected
|
||||
? "selected"
|
||||
: nothing}${this._renderRow()}</ha-automation-row
|
||||
@@ -500,10 +505,12 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
this._selected = true;
|
||||
|
||||
if (this.narrow) {
|
||||
requestAnimationFrame(() => {
|
||||
this.scrollIntoView({
|
||||
block: "start",
|
||||
behavior: "smooth",
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,6 +677,10 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this._automationRowElement?.focus();
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
rowStyles,
|
||||
|
||||
@@ -47,6 +47,8 @@ export default class HaAutomationTrigger extends LitElement {
|
||||
|
||||
@state() private _showReorder = false;
|
||||
|
||||
@state() private _rowSortSelected?: number;
|
||||
|
||||
@state()
|
||||
@storage({
|
||||
key: "automationClipboard",
|
||||
@@ -90,7 +92,7 @@ export default class HaAutomationTrigger extends LitElement {
|
||||
@item-removed=${this._triggerRemoved}
|
||||
@item-cloned=${this._triggerCloned}
|
||||
>
|
||||
<div class="rows">
|
||||
<div class="rows ${!this.optionsInSidebar ? "no-sidebar" : ""}">
|
||||
${repeat(
|
||||
this.triggers,
|
||||
(trigger) => this._getKey(trigger),
|
||||
@@ -110,10 +112,20 @@ export default class HaAutomationTrigger extends LitElement {
|
||||
.narrow=${this.narrow}
|
||||
?highlight=${this.highlightedTriggers?.includes(trg)}
|
||||
.optionsInSidebar=${this.optionsInSidebar}
|
||||
.sortSelected=${this._rowSortSelected === idx}
|
||||
@stop-sort-selection=${this._stopSortSelection}
|
||||
>
|
||||
${this._showReorder && !this.disabled
|
||||
? html`
|
||||
<div class="handle" slot="icons">
|
||||
<div
|
||||
tabindex="0"
|
||||
class="handle ${this._rowSortSelected === idx
|
||||
? "active"
|
||||
: ""}"
|
||||
slot="icons"
|
||||
@keydown=${this._handleDragKeydown}
|
||||
.index=${idx}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiDrag}></ha-svg-icon>
|
||||
</div>
|
||||
`
|
||||
@@ -226,15 +238,27 @@ export default class HaAutomationTrigger extends LitElement {
|
||||
private _moveUp(ev) {
|
||||
ev.stopPropagation();
|
||||
const index = (ev.target as any).index;
|
||||
if (!(ev.target as HaAutomationTriggerRow).first) {
|
||||
const newIndex = index - 1;
|
||||
this._move(index, newIndex);
|
||||
if (this._rowSortSelected === index) {
|
||||
this._rowSortSelected = newIndex;
|
||||
}
|
||||
ev.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private _moveDown(ev) {
|
||||
ev.stopPropagation();
|
||||
const index = (ev.target as any).index;
|
||||
if (!(ev.target as HaAutomationTriggerRow).last) {
|
||||
const newIndex = index + 1;
|
||||
this._move(index, newIndex);
|
||||
if (this._rowSortSelected === index) {
|
||||
this._rowSortSelected = newIndex;
|
||||
}
|
||||
ev.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private _move(oldIndex: number, newIndex: number) {
|
||||
@@ -330,6 +354,20 @@ export default class HaAutomationTrigger extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _handleDragKeydown(ev: KeyboardEvent) {
|
||||
if (ev.key === "Enter" || ev.key === " ") {
|
||||
ev.stopPropagation();
|
||||
this._rowSortSelected =
|
||||
this._rowSortSelected === undefined
|
||||
? (ev.target as any).index
|
||||
: undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private _stopSortSelection() {
|
||||
this._rowSortSelected = undefined;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
automationRowsStyles,
|
||||
css`
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { mdiDelete } from "@mdi/js";
|
||||
import type { CSSResultGroup } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { preventDefaultStopPropagation } from "../../../common/dom/prevent_default_stop_propagation";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
import type { LocalizeKeys } from "../../../common/translations/localize";
|
||||
import "../../../components/ha-automation-row";
|
||||
import "../../../components/ha-card";
|
||||
@@ -61,6 +64,29 @@ export default class HaScriptFieldRow extends LitElement {
|
||||
<h3 slot="header">${this.key}</h3>
|
||||
|
||||
<slot name="icons" slot="icons"></slot>
|
||||
|
||||
<ha-md-button-menu
|
||||
quick
|
||||
slot="icons"
|
||||
@click=${preventDefaultStopPropagation}
|
||||
@keydown=${stopPropagation}
|
||||
@closed=${stopPropagation}
|
||||
positioning="fixed"
|
||||
anchor-corner="end-end"
|
||||
menu-corner="start-end"
|
||||
>
|
||||
<ha-md-menu-item
|
||||
slot="menu-items"
|
||||
.clickAction=${this._onDelete}
|
||||
.disabled=${this.disabled}
|
||||
class="warning"
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.delete"
|
||||
)}
|
||||
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
|
||||
</ha-md-menu-item>
|
||||
</ha-md-button-menu>
|
||||
</ha-automation-row>
|
||||
</ha-card>
|
||||
<div
|
||||
@@ -221,10 +247,12 @@ export default class HaScriptFieldRow extends LitElement {
|
||||
} satisfies ScriptFieldSidebarConfig);
|
||||
|
||||
if (this.narrow) {
|
||||
requestAnimationFrame(() => {
|
||||
this.scrollIntoView({
|
||||
block: "start",
|
||||
behavior: "smooth",
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user