diff --git a/src/panels/lovelace/components/hui-yaml-editor.ts b/src/components/ha-yaml-editor.ts similarity index 75% rename from src/panels/lovelace/components/hui-yaml-editor.ts rename to src/components/ha-yaml-editor.ts index 99b2fec3fb..11190cbfef 100644 --- a/src/panels/lovelace/components/hui-yaml-editor.ts +++ b/src/components/ha-yaml-editor.ts @@ -3,9 +3,7 @@ import CodeMirror from "codemirror"; import "codemirror/mode/yaml/yaml"; // @ts-ignore import codeMirrorCSS from "codemirror/lib/codemirror.css"; -import { HomeAssistant } from "../../../types"; -import { fireEvent } from "../../../common/dom/fire_event"; -import { computeRTL } from "../../../common/util/compute_rtl"; +import { fireEvent } from "../common/dom/fire_event"; import { customElement } from "lit-element"; declare global { @@ -17,12 +15,11 @@ declare global { } } -@customElement("hui-yaml-editor") -export class HuiYamlEditor extends HTMLElement { - public _hass?: HomeAssistant; - - public codemirror!: any; - +@customElement("ha-yaml-editor") +export class HaYamlEditor extends HTMLElement { + public codemirror?: any; + private _autofocus = false; + private _rtl = false; private _value: string; public constructor() { @@ -47,8 +44,11 @@ export class HuiYamlEditor extends HTMLElement { background-color: var(--paper-dialog-background-color, var(--primary-background-color)); transition: 0.2s ease border-right; } + :host(.error-state) .CodeMirror-gutters { + border-color: var(--error-state-color, red); + } .CodeMirror-focused .CodeMirror-gutters { - border-right: 2px solid var(--paper-input-container-focus-color, var(--primary-color));; + border-right: 2px solid var(--paper-input-container-focus-color, var(--primary-color)); } .CodeMirror-linenumber { color: var(--paper-dialog-color, var(--primary-text-color)); @@ -63,13 +63,6 @@ export class HuiYamlEditor extends HTMLElement { `; } - set hass(hass: HomeAssistant) { - this._hass = hass; - if (this._hass) { - this.setScrollBarDirection(); - } - } - set value(value: string) { if (this.codemirror) { if (value !== this.codemirror.getValue()) { @@ -83,6 +76,22 @@ export class HuiYamlEditor extends HTMLElement { return this.codemirror.getValue(); } + set rtl(rtl: boolean) { + this._rtl = rtl; + this.setScrollBarDirection(); + } + + set autofocus(autofocus: boolean) { + this._autofocus = autofocus; + if (this.codemirror) { + this.codemirror.focus(); + } + } + + set error(error: boolean) { + this.classList.toggle("error-state", error); + } + get hasComments(): boolean { return this.shadowRoot!.querySelector("span.cm-comment") ? true : false; } @@ -96,16 +105,13 @@ export class HuiYamlEditor extends HTMLElement { lineNumbers: true, mode: "yaml", tabSize: 2, - autofocus: true, + autofocus: this._autofocus, viewportMargin: Infinity, extraKeys: { Tab: "indentMore", "Shift-Tab": "indentLess", }, - gutters: - this._hass && computeRTL(this._hass!) - ? ["rtl-gutter", "CodeMirror-linenumbers"] - : [], + gutters: this._rtl ? ["rtl-gutter", "CodeMirror-linenumbers"] : [], } ); this.setScrollBarDirection(); @@ -120,18 +126,14 @@ export class HuiYamlEditor extends HTMLElement { } private setScrollBarDirection(): void { - if (!this.codemirror) { - return; + if (this.codemirror) { + this.codemirror.getWrapperElement().classList.toggle("rtl", this._rtl); } - - this.codemirror - .getWrapperElement() - .classList.toggle("rtl", computeRTL(this._hass!)); } } declare global { interface HTMLElementTagNameMap { - "hui-yaml-editor": HuiYamlEditor; + "ha-yaml-editor": HaYamlEditor; } } diff --git a/src/panels/config/js/preact-types.ts b/src/panels/config/js/preact-types.ts index 374fbebb04..f103f63230 100644 --- a/src/panels/config/js/preact-types.ts +++ b/src/panels/config/js/preact-types.ts @@ -20,6 +20,7 @@ declare global { "ha-device-picker": any; "ha-device-condition-picker": any; "ha-textarea": any; + "ha-yaml-editor": any; "ha-service-picker": any; "mwc-button": any; "ha-device-trigger-picker": any; diff --git a/src/panels/config/js/yaml_textarea.tsx b/src/panels/config/js/yaml_textarea.tsx index 6e3ca7b04c..f9e8edf634 100644 --- a/src/panels/config/js/yaml_textarea.tsx +++ b/src/panels/config/js/yaml_textarea.tsx @@ -1,6 +1,8 @@ import { h, Component } from "preact"; import yaml from "js-yaml"; -import "../../../components/ha-textarea"; +import "../../../components/ha-yaml-editor"; +// tslint:disable-next-line +import { HaYamlEditor } from "../../../components/ha-yaml-editor"; const isEmpty = (obj: object) => { for (const key in obj) { @@ -12,6 +14,8 @@ const isEmpty = (obj: object) => { }; export default class YAMLTextArea extends Component { + private _yamlEditor!: HaYamlEditor; + constructor(props) { super(props); @@ -34,7 +38,7 @@ export default class YAMLTextArea extends Component { } public onChange(ev) { - const value = ev.target.value; + const value = ev.detail.value; let parsed; let isValid = true; @@ -59,22 +63,30 @@ export default class YAMLTextArea extends Component { } } + public componentDidMount() { + setTimeout(() => { + this._yamlEditor.codemirror.refresh(); + }, 1); + } + public render({ label }, { value, isValid }) { const style: any = { minWidth: 300, width: "100%", }; - if (!isValid) { - style.border = "1px solid red"; - } return ( - +
+

{label}

+ +
); } + + private _storeYamlEditorRef = (yamlEditor) => (this._yamlEditor = yamlEditor); } diff --git a/src/panels/lovelace/editor/card-editor/hui-card-editor.ts b/src/panels/lovelace/editor/card-editor/hui-card-editor.ts index b2eb3a6ec4..792cd9c118 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-editor.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-editor.ts @@ -15,11 +15,12 @@ import { HomeAssistant } from "../../../../types"; import { LovelaceCardConfig } from "../../../../data/lovelace"; import { LovelaceCardEditor } from "../../types"; import { getCardElementTag } from "../../common/get-card-element-tag"; +import { computeRTL } from "../../../../common/util/compute_rtl"; -import "../../components/hui-yaml-editor"; +import "../../../../components/ha-yaml-editor"; // This is not a duplicate import, one is for types, one is for element. // tslint:disable-next-line -import { HuiYamlEditor } from "../../components/hui-yaml-editor"; +import { HaYamlEditor } from "../../../../components/ha-yaml-editor"; import { fireEvent } from "../../../../common/dom/fire_event"; import { EntityConfig } from "../../entity-rows/types"; @@ -43,7 +44,7 @@ export interface UIConfigChangedEvent extends Event { @customElement("hui-card-editor") export class HuiCardEditor extends LitElement { - @property() public hass?: HomeAssistant; + @property() public hass!: HomeAssistant; @property() private _yaml?: string; @property() private _config?: LovelaceCardConfig; @@ -93,8 +94,8 @@ export class HuiCardEditor extends LitElement { return this._error !== undefined; } - private get _yamlEditor(): HuiYamlEditor { - return this.shadowRoot!.querySelector("hui-yaml-editor")!; + private get _yamlEditor(): HaYamlEditor { + return this.shadowRoot!.querySelector("ha-yaml-editor")!; } public toggleMode() { @@ -120,11 +121,12 @@ export class HuiCardEditor extends LitElement { ` : html`
- + >
`} ${this._error diff --git a/src/panels/lovelace/hui-editor.ts b/src/panels/lovelace/hui-editor.ts index d4570dcebe..ba225a95f5 100644 --- a/src/panels/lovelace/hui-editor.ts +++ b/src/panels/lovelace/hui-editor.ts @@ -14,11 +14,12 @@ import { Lovelace } from "./types"; import "../../components/ha-icon"; import { haStyle } from "../../resources/styles"; -import "./components/hui-yaml-editor"; +import "../../components/ha-yaml-editor"; // This is not a duplicate import, one is for types, one is for element. // tslint:disable-next-line -import { HuiYamlEditor } from "./components/hui-yaml-editor"; +import { HaYamlEditor } from "../../components/ha-yaml-editor"; import { HomeAssistant } from "../../types"; +import { computeRTL } from "../../common/util/compute_rtl"; const lovelaceStruct = struct.interface({ title: "string?", @@ -27,7 +28,7 @@ const lovelaceStruct = struct.interface({ }); class LovelaceFullConfigEditor extends LitElement { - public hass?: HomeAssistant; + public hass!: HomeAssistant; public lovelace?: Lovelace; public closeEditor?: () => void; private _saving?: boolean; @@ -80,12 +81,14 @@ class LovelaceFullConfigEditor extends LitElement {
- - +
`; @@ -205,8 +208,8 @@ class LovelaceFullConfigEditor extends LitElement { this._changed = false; } - private get yamlEditor(): HuiYamlEditor { - return this.shadowRoot!.querySelector("hui-yaml-editor")!; + private get yamlEditor(): HaYamlEditor { + return this.shadowRoot!.querySelector("ha-yaml-editor")!; } } diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index 3e57ed0b8d..577a79d5da 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -33,6 +33,8 @@ documentContainer.innerHTML = ` --scrollbar-thumb-color: rgb(194, 194, 194); + --error-state-color: #db4437; + /* states and badges */ --state-icon-color: #44739e; --state-icon-active-color: #FDD835;