automation editor: resizable sidebar (#27025)
parent
912d710ae4
commit
034afd1375
|
@ -1154,6 +1154,12 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
|
|||
return [
|
||||
haStyle,
|
||||
css`
|
||||
:host {
|
||||
--ha-automation-editor-max-width: var(
|
||||
--ha-automation-editor-width,
|
||||
1540px
|
||||
);
|
||||
}
|
||||
ha-fade-in {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -1175,7 +1181,7 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
|
|||
}
|
||||
|
||||
manual-automation-editor {
|
||||
max-width: 1540px;
|
||||
max-width: var(--ha-automation-editor-max-width);
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import "../../../components/ha-resizable-bottom-sheet";
|
||||
import type { HaResizableBottomSheet } from "../../../components/ha-resizable-bottom-sheet";
|
||||
import {
|
||||
|
@ -37,9 +39,18 @@ export default class HaAutomationSidebar extends LitElement {
|
|||
|
||||
@state() private _yamlMode = false;
|
||||
|
||||
@state() private _resizing = false;
|
||||
|
||||
@query("ha-resizable-bottom-sheet")
|
||||
private _bottomSheetElement?: HaResizableBottomSheet;
|
||||
|
||||
private _resizeStartX = 0;
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this._unregisterResizeHandlers();
|
||||
}
|
||||
|
||||
private _renderContent() {
|
||||
// get config type
|
||||
const type = this._getType();
|
||||
|
@ -154,7 +165,16 @@ export default class HaAutomationSidebar extends LitElement {
|
|||
`;
|
||||
}
|
||||
|
||||
return this._renderContent();
|
||||
return html`
|
||||
<div
|
||||
class="handle ${this._resizing ? "resizing" : ""}"
|
||||
@mousedown=${this._handleMouseDown}
|
||||
@touchstart=${this._handleMouseDown}
|
||||
>
|
||||
${this._resizing ? html`<div class="indicator"></div>` : nothing}
|
||||
</div>
|
||||
${this._renderContent()}
|
||||
`;
|
||||
}
|
||||
|
||||
private _getType() {
|
||||
|
@ -207,6 +227,67 @@ export default class HaAutomationSidebar extends LitElement {
|
|||
(this.config as ActionSidebarConfig)?.toggleYamlMode();
|
||||
};
|
||||
|
||||
private _handleMouseDown = (ev: MouseEvent | TouchEvent) => {
|
||||
// Prevent the browser from interpreting this as a scroll/PTR gesture.
|
||||
ev.preventDefault();
|
||||
this._startResizing(
|
||||
(ev as TouchEvent).touches?.length
|
||||
? (ev as TouchEvent).touches[0].clientX
|
||||
: (ev as MouseEvent).clientX
|
||||
);
|
||||
};
|
||||
|
||||
private _startResizing(clientX: number) {
|
||||
// register event listeners for drag handling
|
||||
document.addEventListener("mousemove", this._handleMouseMove);
|
||||
document.addEventListener("mouseup", this._endResizing);
|
||||
document.addEventListener("touchmove", this._handleMouseMove, {
|
||||
passive: false,
|
||||
});
|
||||
document.addEventListener("touchend", this._endResizing);
|
||||
document.addEventListener("touchcancel", this._endResizing);
|
||||
|
||||
this._resizing = true;
|
||||
this._resizeStartX = clientX;
|
||||
}
|
||||
|
||||
private _handleMouseMove = (ev: MouseEvent | TouchEvent) => {
|
||||
this._updateSize(
|
||||
(ev as TouchEvent).touches?.length
|
||||
? (ev as TouchEvent).touches[0].clientX
|
||||
: (ev as MouseEvent).clientX
|
||||
);
|
||||
};
|
||||
|
||||
private _updateSize(clientX: number) {
|
||||
let delta = this._resizeStartX - clientX;
|
||||
|
||||
if (computeRTL(this.hass)) {
|
||||
delta = -delta;
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
fireEvent(this, "sidebar-resized", {
|
||||
deltaInPx: delta,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private _endResizing = () => {
|
||||
this._unregisterResizeHandlers();
|
||||
this._resizing = false;
|
||||
document.body.style.removeProperty("cursor");
|
||||
fireEvent(this, "sidebar-resizing-stopped");
|
||||
};
|
||||
|
||||
private _unregisterResizeHandlers() {
|
||||
document.removeEventListener("mousemove", this._handleMouseMove);
|
||||
document.removeEventListener("mouseup", this._endResizing);
|
||||
document.removeEventListener("touchmove", this._handleMouseMove);
|
||||
document.removeEventListener("touchend", this._endResizing);
|
||||
document.removeEventListener("touchcancel", this._endResizing);
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
z-index: 6;
|
||||
|
@ -231,6 +312,28 @@ export default class HaAutomationSidebar extends LitElement {
|
|||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.handle {
|
||||
position: absolute;
|
||||
margin-inline-start: -11px;
|
||||
height: calc(100% - (2 * var(--ha-card-border-radius)));
|
||||
width: 24px;
|
||||
z-index: 7;
|
||||
cursor: ew-resize;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: var(--ha-card-border-radius) 0;
|
||||
}
|
||||
.handle.resizing {
|
||||
cursor: grabbing;
|
||||
}
|
||||
.handle .indicator {
|
||||
background-color: var(--primary-color);
|
||||
height: 100%;
|
||||
width: 4px;
|
||||
border-radius: var(--ha-border-radius-pill);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -244,5 +347,9 @@ declare global {
|
|||
"yaml-changed": {
|
||||
value: unknown;
|
||||
};
|
||||
"sidebar-resized": {
|
||||
deltaInPx: number;
|
||||
};
|
||||
"sidebar-resizing-stopped": undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
union,
|
||||
} from "superstruct";
|
||||
import { ensureArray } from "../../../common/array/ensure-array";
|
||||
import { storage } from "../../../common/decorators/storage";
|
||||
import { canOverrideAlphanumericInput } from "../../../common/dom/can-override-input";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { constructUrlCurrentPath } from "../../../common/url/construct-url";
|
||||
|
@ -77,6 +78,8 @@ const automationConfigStruct = union([
|
|||
assign(baseConfigStruct, object({ actions: array(any()) })),
|
||||
]);
|
||||
|
||||
export const SIDEBAR_DEFAULT_WIDTH = 500;
|
||||
|
||||
@customElement("manual-automation-editor")
|
||||
export class HaManualAutomationEditor extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
@ -101,6 +104,13 @@ export class HaManualAutomationEditor extends LitElement {
|
|||
|
||||
@state() private _sidebarKey?: string;
|
||||
|
||||
@storage({
|
||||
key: "automation-sidebar-width",
|
||||
state: false,
|
||||
subscribe: false,
|
||||
})
|
||||
private _sidebarWidthPx = SIDEBAR_DEFAULT_WIDTH;
|
||||
|
||||
@query("ha-automation-sidebar") private _sidebarElement?: HaAutomationSidebar;
|
||||
|
||||
@queryAll("ha-automation-action, ha-automation-condition")
|
||||
|
@ -110,6 +120,8 @@ export class HaManualAutomationEditor extends LitElement {
|
|||
|
||||
private _previousConfig?: ManualAutomationConfig;
|
||||
|
||||
private _prevSidebarWidthPx?: number;
|
||||
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
window.addEventListener("paste", this._handlePaste);
|
||||
|
@ -303,9 +315,11 @@ export class HaManualAutomationEditor extends LitElement {
|
|||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.config=${this._sidebarConfig}
|
||||
@value-changed=${this._sidebarConfigChanged}
|
||||
.disabled=${this.disabled}
|
||||
.sidebarKey=${this._sidebarKey}
|
||||
@value-changed=${this._sidebarConfigChanged}
|
||||
@sidebar-resized=${this._resizeSidebar}
|
||||
@sidebar-resizing-stopped=${this._stopResizeSidebar}
|
||||
></ha-automation-sidebar>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -314,6 +328,12 @@ export class HaManualAutomationEditor extends LitElement {
|
|||
|
||||
protected firstUpdated(changedProps: PropertyValues): void {
|
||||
super.firstUpdated(changedProps);
|
||||
|
||||
this.style.setProperty(
|
||||
"--sidebar-dynamic-width",
|
||||
`${this._sidebarWidthPx}px`
|
||||
);
|
||||
|
||||
const expanded = extractSearchParam("expanded");
|
||||
if (expanded === "1") {
|
||||
this._clearParam("expanded");
|
||||
|
@ -642,6 +662,31 @@ export class HaManualAutomationEditor extends LitElement {
|
|||
}
|
||||
}
|
||||
|
||||
private _resizeSidebar(ev) {
|
||||
ev.stopPropagation();
|
||||
const delta = ev.detail.deltaInPx as number;
|
||||
|
||||
// set initial resize width to add / reduce delta from it
|
||||
if (!this._prevSidebarWidthPx) {
|
||||
this._prevSidebarWidthPx =
|
||||
this._sidebarElement?.clientWidth || SIDEBAR_DEFAULT_WIDTH;
|
||||
}
|
||||
|
||||
const widthPx = delta + this._prevSidebarWidthPx;
|
||||
|
||||
this._sidebarWidthPx = widthPx;
|
||||
|
||||
this.style.setProperty(
|
||||
"--sidebar-dynamic-width",
|
||||
`${this._sidebarWidthPx}px`
|
||||
);
|
||||
}
|
||||
|
||||
private _stopResizeSidebar(ev) {
|
||||
ev.stopPropagation();
|
||||
this._prevSidebarWidthPx = undefined;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
saveFabStyles,
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { css } from "lit";
|
||||
|
||||
export const SIDEBAR_MIN_WIDTH = 375;
|
||||
export const CONTENT_MIN_WIDTH = 350;
|
||||
|
||||
export const rowStyles = css`
|
||||
ha-icon-button {
|
||||
--mdc-theme-text-primary-on-background: var(--primary-text-color);
|
||||
|
@ -109,7 +112,12 @@ export const manualEditorStyles = css`
|
|||
}
|
||||
|
||||
.has-sidebar {
|
||||
--sidebar-width: min(35vw, 500px);
|
||||
--sidebar-width: min(
|
||||
max(var(--sidebar-dynamic-width), ${SIDEBAR_MIN_WIDTH}px),
|
||||
100vw - ${CONTENT_MIN_WIDTH}px - var(--mdc-drawer-width, 0px),
|
||||
var(--ha-automation-editor-max-width) -
|
||||
${CONTENT_MIN_WIDTH}px - var(--mdc-drawer-width, 0px)
|
||||
);
|
||||
--sidebar-gap: 16px;
|
||||
}
|
||||
|
||||
|
|
|
@ -1062,6 +1062,12 @@ export class HaScriptEditor extends SubscribeMixin(
|
|||
return [
|
||||
haStyle,
|
||||
css`
|
||||
:host {
|
||||
--ha-automation-editor-max-width: var(
|
||||
--ha-automation-editor-width,
|
||||
1540px
|
||||
);
|
||||
}
|
||||
.yaml-mode {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
@ -1114,7 +1120,7 @@ export class HaScriptEditor extends SubscribeMixin(
|
|||
}
|
||||
|
||||
manual-script-editor {
|
||||
max-width: 1540px;
|
||||
max-width: var(--ha-automation-editor-max-width);
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
string,
|
||||
} from "superstruct";
|
||||
import { ensureArray } from "../../../common/array/ensure-array";
|
||||
import { storage } from "../../../common/decorators/storage";
|
||||
import { canOverrideAlphanumericInput } from "../../../common/dom/can-override-input";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { constructUrlCurrentPath } from "../../../common/url/construct-url";
|
||||
|
@ -47,6 +48,7 @@ import "../automation/action/ha-automation-action";
|
|||
import type HaAutomationAction from "../automation/action/ha-automation-action";
|
||||
import "../automation/ha-automation-sidebar";
|
||||
import type HaAutomationSidebar from "../automation/ha-automation-sidebar";
|
||||
import { SIDEBAR_DEFAULT_WIDTH } from "../automation/manual-automation-editor";
|
||||
import { showPasteReplaceDialog } from "../automation/paste-replace-dialog/show-dialog-paste-replace";
|
||||
import { manualEditorStyles, saveFabStyles } from "../automation/styles";
|
||||
import "./ha-script-fields";
|
||||
|
@ -84,6 +86,13 @@ export class HaManualScriptEditor extends LitElement {
|
|||
|
||||
@state() private _sidebarKey?: string;
|
||||
|
||||
@storage({
|
||||
key: "automation-sidebar-width",
|
||||
state: false,
|
||||
subscribe: false,
|
||||
})
|
||||
private _sidebarWidthPx = SIDEBAR_DEFAULT_WIDTH;
|
||||
|
||||
@query("ha-script-fields")
|
||||
private _scriptFields?: HaScriptFields;
|
||||
|
||||
|
@ -98,6 +107,8 @@ export class HaManualScriptEditor extends LitElement {
|
|||
|
||||
private _openFields = false;
|
||||
|
||||
private _prevSidebarWidthPx?: number;
|
||||
|
||||
public addFields() {
|
||||
this._openFields = true;
|
||||
fireEvent(this, "value-changed", {
|
||||
|
@ -252,8 +263,10 @@ export class HaManualScriptEditor extends LitElement {
|
|||
.isWide=${this.isWide}
|
||||
.hass=${this.hass}
|
||||
.config=${this._sidebarConfig}
|
||||
@value-changed=${this._sidebarConfigChanged}
|
||||
.disabled=${this.disabled}
|
||||
@value-changed=${this._sidebarConfigChanged}
|
||||
@sidebar-resized=${this._resizeSidebar}
|
||||
@sidebar-resizing-stopped=${this._stopResizeSidebar}
|
||||
></ha-automation-sidebar>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -262,6 +275,12 @@ export class HaManualScriptEditor extends LitElement {
|
|||
|
||||
protected firstUpdated(changedProps: PropertyValues): void {
|
||||
super.firstUpdated(changedProps);
|
||||
|
||||
this.style.setProperty(
|
||||
"--sidebar-dynamic-width",
|
||||
`${this._sidebarWidthPx}px`
|
||||
);
|
||||
|
||||
const expanded = extractSearchParam("expanded");
|
||||
if (expanded === "1") {
|
||||
this._clearParam("expanded");
|
||||
|
@ -557,6 +576,31 @@ export class HaManualScriptEditor extends LitElement {
|
|||
}
|
||||
}
|
||||
|
||||
private _resizeSidebar(ev) {
|
||||
ev.stopPropagation();
|
||||
const delta = ev.detail.deltaInPx as number;
|
||||
|
||||
// set initial resize width to add / reduce delta from it
|
||||
if (!this._prevSidebarWidthPx) {
|
||||
this._prevSidebarWidthPx =
|
||||
this._sidebarElement?.clientWidth || SIDEBAR_DEFAULT_WIDTH;
|
||||
}
|
||||
|
||||
const widthPx = delta + this._prevSidebarWidthPx;
|
||||
|
||||
this._sidebarWidthPx = widthPx;
|
||||
|
||||
this.style.setProperty(
|
||||
"--sidebar-dynamic-width",
|
||||
`${this._sidebarWidthPx}px`
|
||||
);
|
||||
}
|
||||
|
||||
private _stopResizeSidebar(ev) {
|
||||
ev.stopPropagation();
|
||||
this._prevSidebarWidthPx = undefined;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
saveFabStyles,
|
||||
|
|
Loading…
Reference in New Issue