From b3f9432ae1bc53d4ebb91641e64469e5a543a151 Mon Sep 17 00:00:00 2001 From: yosilevy <37745463+yosilevy@users.noreply.github.com> Date: Thu, 28 Mar 2019 06:10:07 +0200 Subject: [PATCH] Tab fix in yaml-editor edit card (#3008) * Fixed tabs not working in yaml editor in edit card * Improved docs * Fixed comments * Added dependencies * Added typescript mapping * Fixed data type issue + removed depednency since it breaks the UI. Non final. * Added iron-overlay-behavior package * Added dependency * Update iron-overlay-behavior * Lint --- package.json | 4 +- .../lovelace/components/dialog/ha-dialog.ts | 26 ++++++ .../dialog/ha-iron-focusables-helper.js | 90 +++++++++++++++++++ .../lovelace/components/hui-yaml-editor.ts | 4 + .../editor/card-editor/hui-edit-card.ts | 13 +-- yarn.lock | 8 +- 6 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 src/panels/lovelace/components/dialog/ha-dialog.ts create mode 100644 src/panels/lovelace/components/dialog/ha-iron-focusables-helper.js diff --git a/package.json b/package.json index dd9ac63620..d049b1ca4b 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@polymer/iron-input": "^3.0.1", "@polymer/iron-label": "^3.0.1", "@polymer/iron-media-query": "^3.0.1", + "@polymer/iron-overlay-behavior": "^3.0.2", "@polymer/iron-pages": "^3.0.1", "@polymer/iron-resizable-behavior": "^3.0.1", "@polymer/neon-animation": "^3.0.1", @@ -167,7 +168,8 @@ "@webcomponents/webcomponentsjs": "^2.2.6", "@webcomponents/shadycss": "^1.9.0", "@vaadin/vaadin-overlay": "3.2.2", - "@vaadin/vaadin-lumo-styles": "1.3.0" + "@vaadin/vaadin-lumo-styles": "1.3.0", + "@polymer/iron-overlay-behavior": "^3.0.2" }, "main": "src/home-assistant.js", "husky": { diff --git a/src/panels/lovelace/components/dialog/ha-dialog.ts b/src/panels/lovelace/components/dialog/ha-dialog.ts new file mode 100644 index 0000000000..25be5b934e --- /dev/null +++ b/src/panels/lovelace/components/dialog/ha-dialog.ts @@ -0,0 +1,26 @@ +import "@polymer/paper-dialog/paper-dialog"; +import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class"; +import { HaIronFocusablesHelper } from "./ha-iron-focusables-helper.js"; + +const paperDialogClass = customElements.get("paper-dialog"); + +// behavior that will override existing iron-overlay-behavior and call the fixed implementation +const haTabFixBehaviorImpl = { + get _focusableNodes() { + return HaIronFocusablesHelper.getTabbableNodes(this); + }, +}; + +// paper-dialog that uses the haTabFixBehaviorImpl behvaior +// export class HaPaperDialog extends paperDialogClass {} +export class HaPaperDialog extends mixinBehaviors( + [haTabFixBehaviorImpl], + paperDialogClass +) {} + +declare global { + interface HTMLElementTagNameMap { + "ha-paper-dialog": HaPaperDialog; + } +} +customElements.define("ha-paper-dialog", HaPaperDialog); diff --git a/src/panels/lovelace/components/dialog/ha-iron-focusables-helper.js b/src/panels/lovelace/components/dialog/ha-iron-focusables-helper.js new file mode 100644 index 0000000000..4ae78090e5 --- /dev/null +++ b/src/panels/lovelace/components/dialog/ha-iron-focusables-helper.js @@ -0,0 +1,90 @@ +/** +@license +Copyright (c) 2016 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at +http://polymer.github.io/LICENSE.txt The complete set of authors may be found at +http://polymer.github.io/AUTHORS.txt The complete set of contributors may be +found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as +part of the polymer project is also subject to an additional IP rights grant +found at http://polymer.github.io/PATENTS.txt +*/ +/* + Fixes issue with not using shadow dom properly in iron-overlay-behavior/icon-focusables-helper.js +*/ +import { dom } from "@polymer/polymer/lib/legacy/polymer.dom.js"; + +import { IronFocusablesHelper } from "@polymer/iron-overlay-behavior/iron-focusables-helper.js"; + +export const HaIronFocusablesHelper = { + /** + * Returns a sorted array of tabbable nodes, including the root node. + * It searches the tabbable nodes in the light and shadow dom of the chidren, + * sorting the result by tabindex. + * @param {!Node} node + * @return {!Array} + */ + getTabbableNodes: function(node) { + var result = []; + // If there is at least one element with tabindex > 0, we need to sort + // the final array by tabindex. + var needsSortByTabIndex = this._collectTabbableNodes(node, result); + if (needsSortByTabIndex) { + return IronFocusablesHelper._sortByTabIndex(result); + } + return result; + }, + + /** + * Searches for nodes that are tabbable and adds them to the `result` array. + * Returns if the `result` array needs to be sorted by tabindex. + * @param {!Node} node The starting point for the search; added to `result` + * if tabbable. + * @param {!Array} result + * @return {boolean} + * @private + */ + _collectTabbableNodes: function(node, result) { + // If not an element or not visible, no need to explore children. + if ( + node.nodeType !== Node.ELEMENT_NODE || + !IronFocusablesHelper._isVisible(node) + ) { + return false; + } + var element = /** @type {!HTMLElement} */ (node); + var tabIndex = IronFocusablesHelper._normalizedTabIndex(element); + var needsSort = tabIndex > 0; + if (tabIndex >= 0) { + result.push(element); + } + + // In ShadowDOM v1, tab order is affected by the order of distrubution. + // E.g. getTabbableNodes(#root) in ShadowDOM v1 should return [#A, #B]; + // in ShadowDOM v0 tab order is not affected by the distrubution order, + // in fact getTabbableNodes(#root) returns [#B, #A]. + //