Automation yaml editor bottom sheet full fullscreen

This commit is contained in:
Wendelin
2025-10-01 08:53:08 +02:00
parent 2ff52c6c29
commit 3cdb8bea55
3 changed files with 58 additions and 22 deletions

View File

@@ -5,19 +5,19 @@ import type {
CompletionResult, CompletionResult,
CompletionSource, CompletionSource,
} from "@codemirror/autocomplete"; } from "@codemirror/autocomplete";
import { undo, undoDepth, redo, redoDepth } from "@codemirror/commands"; import { redo, redoDepth, undo, undoDepth } from "@codemirror/commands";
import type { Extension, TransactionSpec } from "@codemirror/state"; import type { Extension, TransactionSpec } from "@codemirror/state";
import type { EditorView, KeyBinding, ViewUpdate } from "@codemirror/view"; import type { EditorView, KeyBinding, ViewUpdate } from "@codemirror/view";
import { import {
mdiArrowExpand,
mdiArrowCollapse, mdiArrowCollapse,
mdiArrowExpand,
mdiContentCopy, mdiContentCopy,
mdiUndo,
mdiRedo, mdiRedo,
mdiUndo,
} from "@mdi/js"; } from "@mdi/js";
import type { HassEntities } from "home-assistant-js-websocket"; import type { HassEntities } from "home-assistant-js-websocket";
import type { PropertyValues } from "lit"; import type { PropertyValues } from "lit";
import { css, ReactiveElement, html, render } from "lit"; import { css, html, ReactiveElement, render } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
@@ -395,6 +395,8 @@ export class HaCodeEditor extends ReactiveElement {
// is disabled, or we have no toolbar, ensure we are not in fullscreen mode. // is disabled, or we have no toolbar, ensure we are not in fullscreen mode.
this._isFullscreen = this._isFullscreen =
fullscreen && !this.disableFullscreen && this.hasToolbar; fullscreen && !this.disableFullscreen && this.hasToolbar;
fireEvent(this, "fullscreen-changed", this._isFullscreen);
// Return whether successfully in requested state // Return whether successfully in requested state
return this._isFullscreen === fullscreen; return this._isFullscreen === fullscreen;
} }
@@ -790,6 +792,12 @@ export class HaCodeEditor extends ReactiveElement {
display: block !important; display: block !important;
} }
@media all and (max-width: 870px) {
:host(.fullscreen) {
top: 8px !important;
}
}
:host(.hasToolbar) .cm-editor { :host(.hasToolbar) .cm-editor {
padding-top: var(--code-editor-toolbar-height); padding-top: var(--code-editor-toolbar-height);
} }
@@ -834,4 +842,8 @@ declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"ha-code-editor": HaCodeEditor; "ha-code-editor": HaCodeEditor;
} }
interface HASSDomEvents {
"fullscreen-changed": boolean;
}
} }

View File

@@ -1,9 +1,12 @@
import { css, html, LitElement } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { BOTTOM_SHEET_ANIMATION_DURATION_MS } from "./ha-bottom-sheet"; import { BOTTOM_SHEET_ANIMATION_DURATION_MS } from "./ha-bottom-sheet";
const MAX_VIEWPOINT_HEIGHT = 90;
const MIN_VIEWPOINT_HEIGHT = 20;
/** /**
* A bottom sheet component that slides up from the bottom of the screen. * A bottom sheet component that slides up from the bottom of the screen.
* *
@@ -33,25 +36,32 @@ export class HaResizableBottomSheet extends LitElement {
@state() private _dialogViewportHeight?: number; @state() private _dialogViewportHeight?: number;
@property({ type: Boolean, reflect: true })
public fullscreen = false;
render() { render() {
return html`<dialog return html`<dialog
open open
@transitionend=${this._handleTransitionEnd} @transitionend=${this._handleTransitionEnd}
style=${styleMap({ style=${styleMap({
height: this._dialogViewportHeight height: this.fullscreen
? "100vh"
: this._dialogViewportHeight
? `${this._dialogViewportHeight}vh` ? `${this._dialogViewportHeight}vh`
: "auto", : "auto",
maxHeight: `${this._dialogMaxViewpointHeight}vh`, maxHeight: `${this.fullscreen ? 100 : this._dialogMaxViewpointHeight}vh`,
minHeight: `${this._dialogMinViewpointHeight}vh`, minHeight: `${this._dialogMinViewpointHeight}vh`,
})} })}
> >
<div class="handle-wrapper"> ${!this.fullscreen
? html` <div class="handle-wrapper">
<div <div
@mousedown=${this._handleMouseDown} @mousedown=${this._handleMouseDown}
@touchstart=${this._handleTouchStart} @touchstart=${this._handleTouchStart}
class="handle" class="handle"
></div> ></div>
</div> </div>`
: nothing}
<slot></slot> <slot></slot>
</dialog>`; </dialog>`;
} }
@@ -81,8 +91,8 @@ export class HaResizableBottomSheet extends LitElement {
// - set max height to 90vh, so it opens at max 70vh but can be resized to 90vh // - set max height to 90vh, so it opens at max 70vh but can be resized to 90vh
this._dialogViewportHeight = this._dialogViewportHeight =
(this._dialog.offsetHeight / window.innerHeight) * 100; (this._dialog.offsetHeight / window.innerHeight) * 100;
this._dialogMaxViewpointHeight = 90; this._dialogMaxViewpointHeight = MAX_VIEWPOINT_HEIGHT;
this._dialogMinViewpointHeight = 20; this._dialogMinViewpointHeight = MIN_VIEWPOINT_HEIGHT;
} else { } else {
// after close animation is done close dialog element and fire closed event // after close animation is done close dialog element and fire closed event
this._dialog.close(); this._dialog.close();
@@ -153,10 +163,10 @@ export class HaResizableBottomSheet extends LitElement {
// Calculate new size and clamp between 10vh and 90vh // Calculate new size and clamp between 10vh and 90vh
let newSize = this._initialSize + deltaVh; let newSize = this._initialSize + deltaVh;
newSize = Math.max(10, Math.min(90, newSize)); newSize = Math.max(10, Math.min(MAX_VIEWPOINT_HEIGHT, newSize));
// on drag down and below 20vh // on drag down and below 20vh
if (newSize < 20 && deltaY < 0) { if (newSize < MIN_VIEWPOINT_HEIGHT && deltaY < 0) {
this._endDrag(); this._endDrag();
this.closeSheet(); this.closeSheet();
return; return;

View File

@@ -41,6 +41,8 @@ export default class HaAutomationSidebar extends LitElement {
@state() private _resizing = false; @state() private _resizing = false;
@state() private _fullscreen = false;
@query("ha-resizable-bottom-sheet") @query("ha-resizable-bottom-sheet")
private _bottomSheetElement?: HaResizableBottomSheet; private _bottomSheetElement?: HaResizableBottomSheet;
@@ -68,6 +70,7 @@ export default class HaAutomationSidebar extends LitElement {
.sidebarKey=${this.sidebarKey} .sidebarKey=${this.sidebarKey}
@toggle-yaml-mode=${this._toggleYamlMode} @toggle-yaml-mode=${this._toggleYamlMode}
@close-sidebar=${this.triggerCloseSidebar} @close-sidebar=${this.triggerCloseSidebar}
@fullscreen-changed=${this._handleYamlEditorFullscreenChanged}
></ha-automation-sidebar-trigger> ></ha-automation-sidebar-trigger>
`; `;
} }
@@ -84,6 +87,7 @@ export default class HaAutomationSidebar extends LitElement {
.sidebarKey=${this.sidebarKey} .sidebarKey=${this.sidebarKey}
@toggle-yaml-mode=${this._toggleYamlMode} @toggle-yaml-mode=${this._toggleYamlMode}
@close-sidebar=${this.triggerCloseSidebar} @close-sidebar=${this.triggerCloseSidebar}
@fullscreen-changed=${this._handleYamlEditorFullscreenChanged}
></ha-automation-sidebar-condition> ></ha-automation-sidebar-condition>
`; `;
} }
@@ -100,6 +104,7 @@ export default class HaAutomationSidebar extends LitElement {
.sidebarKey=${this.sidebarKey} .sidebarKey=${this.sidebarKey}
@toggle-yaml-mode=${this._toggleYamlMode} @toggle-yaml-mode=${this._toggleYamlMode}
@close-sidebar=${this.triggerCloseSidebar} @close-sidebar=${this.triggerCloseSidebar}
@fullscreen-changed=${this._handleYamlEditorFullscreenChanged}
></ha-automation-sidebar-action> ></ha-automation-sidebar-action>
`; `;
} }
@@ -129,6 +134,7 @@ export default class HaAutomationSidebar extends LitElement {
.sidebarKey=${this.sidebarKey} .sidebarKey=${this.sidebarKey}
@toggle-yaml-mode=${this._toggleYamlMode} @toggle-yaml-mode=${this._toggleYamlMode}
@close-sidebar=${this.triggerCloseSidebar} @close-sidebar=${this.triggerCloseSidebar}
@fullscreen-changed=${this._handleYamlEditorFullscreenChanged}
></ha-automation-sidebar-script-field-selector> ></ha-automation-sidebar-script-field-selector>
`; `;
} }
@@ -145,6 +151,7 @@ export default class HaAutomationSidebar extends LitElement {
.sidebarKey=${this.sidebarKey} .sidebarKey=${this.sidebarKey}
@toggle-yaml-mode=${this._toggleYamlMode} @toggle-yaml-mode=${this._toggleYamlMode}
@close-sidebar=${this.triggerCloseSidebar} @close-sidebar=${this.triggerCloseSidebar}
@fullscreen-changed=${this._handleYamlEditorFullscreenChanged}
></ha-automation-sidebar-script-field> ></ha-automation-sidebar-script-field>
`; `;
} }
@@ -159,7 +166,10 @@ export default class HaAutomationSidebar extends LitElement {
if (this.narrow) { if (this.narrow) {
return html` return html`
<ha-resizable-bottom-sheet @bottom-sheet-closed=${this._closeSidebar}> <ha-resizable-bottom-sheet
@bottom-sheet-closed=${this._closeSidebar}
.fullscreen=${this._fullscreen}
>
${this._renderContent()} ${this._renderContent()}
</ha-resizable-bottom-sheet> </ha-resizable-bottom-sheet>
`; `;
@@ -288,6 +298,10 @@ export default class HaAutomationSidebar extends LitElement {
document.removeEventListener("touchcancel", this._endResizing); document.removeEventListener("touchcancel", this._endResizing);
} }
private _handleYamlEditorFullscreenChanged(ev: CustomEvent<boolean>) {
this._fullscreen = ev.detail;
}
static styles = css` static styles = css`
:host { :host {
z-index: 6; z-index: 6;