text: define(["exports", "require", "../../@polymer/polymer/polymer-element.js", "../../@polymer/polymer/lib/legacy/polymer.dom.js", "../../@polymer/polymer/lib/utils/flattened-nodes-observer.js", "../../@polymer/polymer/lib/utils/flush.js", "../../@polymer/polymer/lib/utils/render-status.js", "../../@polymer/polymer/lib/utils/async.js", "./lib/haxutils.js", "../simple-colors/simple-colors.js", "./lib/hax-text-context.js", "./lib/hax-ce-context.js", "./lib/hax-plate-context.js", "./lib/hax-input-mixer.js", "./lib/hax-shared-styles.js"], function (_exports, _require, _polymerElement, _polymerDom, _flattenedNodesObserver, _flush, _renderStatus, async, _haxutils, _simpleColors, _haxTextContext, _haxCeContext, _haxPlateContext, _haxInputMixer, _haxSharedStyles) {
    "use strict";
  
    Object.defineProperty(_exports, "__esModule", {
      value: true
    });
    _exports.HaxBody = void 0;
    _require = babelHelpers.interopRequireWildcard(_require);
    async = babelHelpers.interopRequireWildcard(async);
  
    function _templateObject_ece2eff0c3a011e99204fd28bf05b7e9() {
      var data = babelHelpers.taggedTemplateLiteral(["\n      <style include=\"simple-colors-shared-styles hax-shared-styles\">\n        :host {\n          display: block;\n          min-height: 32px;\n          min-width: 32px;\n          outline: none;\n        }\n        .hax-context-menu {\n          padding: 0;\n          margin-left: -5000px;\n          position: absolute;\n          visibility: hidden;\n          opacity: 0;\n          z-index: 1000;\n          float: left;\n          display: block;\n          pointer-events: none;\n          transition: 0.8s opacity ease-in-out, 0.8s visibility ease-in-out;\n        }\n        #haxinputmixer {\n          z-index: 10000000;\n        }\n        .hax-context-visible.hax-active-hover {\n          visibility: visible;\n          opacity: 1;\n          pointer-events: all;\n          margin-left: unset;\n        }\n        :host #bodycontainer ::slotted(h1) {\n          font-size: var(--haxcms-base-styles-h1-font-size, 2.5em);\n          line-height: var(--haxcms-base-styles-h1-line-height, 2.5em);\n        }\n        :host #bodycontainer ::slotted(h2) {\n          font-size: var(--haxcms-base-styles-h2-font-size, 2em);\n        }\n        :host #bodycontainer ::slotted(h3) {\n          font-size: var(--haxcms-base-styles-h3-font-size, 1.75em);\n        }\n        :host #bodycontainer ::slotted(h4) {\n          font-size: var(--haxcms-base-styles-h4-font-size, 1.5em);\n        }\n        :host #bodycontainer ::slotted(h5) {\n          font-size: var(--haxcms-base-styles-h5-font-size, 1.25em);\n        }\n        :host #bodycontainer ::slotted(h6) {\n          font-size: var(--haxcms-base-styles-h6-font-size, 1.25em);\n        }\n        :host #bodycontainer ::slotted(p) {\n          min-height: 26px;\n          font-size: var(--haxcms-base-styles-p-font-size, 24px);\n          line-height: var(--haxcms-base-styles-p-line-height, 1.8);\n          letter-spacing: var(--haxcms-base-styles-p-letter-spacing, 0.5px);\n        }\n\n        :host #bodycontainer ::slotted(a),\n        :host #bodycontainer ::slotted(a:visited),\n        :host #bodycontainer ::slotted(a:active) {\n          color: #000;\n        }\n        :host #bodycontainer ::slotted(a:hover) {\n          color: #2196f3;\n        }\n        :host #bodycontainer ::slotted(ol),\n        :host #bodycontainer ::slotted(ul),\n        :host #bodycontainer ::slotted(li) {\n          padding-bottom: 1.5em;\n          line-height: 40px;\n          font-size: 24px;\n          max-width: 28em;\n        }\n        :host #bodycontainer ::slotted(ol > li:last-child),\n        :host #bodycontainer ::slotted(ul > li:last-child) {\n          padding-bottom: 1em;\n        }\n        :host #bodycontainer ::slotted(ul),\n        :host #bodycontainer ::slotted(ol) {\n          padding-left: 20px;\n          margin-left: 20px;\n        }\n\n        :host([edit-mode]) #bodycontainer ::slotted(*[data-editable]) {\n          outline: none;\n          outline-offset: 2px;\n          transition: 0.2s width ease-in-out, 0.2s height ease-in-out,\n            0.2s margin ease-in-out;\n          caret-color: var(--hax-color-text);\n        }\n        :host([edit-mode]) #bodycontainer ::slotted(*[data-editable]:hover) {\n          outline: 1px solid rgba(145, 151, 162, 0.25);\n          caret-color: #000000;\n        }\n        :host([edit-mode])\n          #bodycontainer\n          ::slotted(*.hax-active[data-editable]:hover) {\n          cursor: text !important;\n          outline: 1px solid rgba(145, 151, 162, 0.25);\n        }\n        :host([edit-mode])\n          #bodycontainer\n          ::slotted(*[data-editable] .hax-active:hover) {\n          cursor: text !important;\n          outline: 1px solid rgba(145, 151, 162, 0.25);\n        }\n        :host([edit-mode])\n          #bodycontainer\n          ::slotted(code.hax-active[data-editable]) {\n          display: block;\n        }\n        :host([edit-mode]) #bodycontainer ::slotted(hr[data-editable]) {\n          height: 2px;\n          background-color: #eeeeee;\n          padding-top: 4px;\n          padding-bottom: 4px;\n        }\n        /** Fix to support safari as it defaults to none */\n        :host([edit-mode]) #bodycontainer ::slotted(*[data-editable]) {\n          -webkit-user-select: text;\n          cursor: pointer;\n        }\n\n        :host([edit-mode])\n          #bodycontainer\n          ::slotted(*[data-editable]::-moz-selection),\n        :host([edit-mode])\n          #bodycontainer\n          ::slotted(*[data-editable] *::-moz-selection) {\n          background-color: var(--hax-body-highlight, --paper-yellow-300);\n          color: black;\n        }\n        :host([edit-mode])\n          #bodycontainer\n          ::slotted(*[data-editable]::selection),\n        :host([edit-mode])\n          #bodycontainer\n          ::slotted(*[data-editable] *::selection) {\n          background-color: var(--hax-body-highlight, --paper-yellow-300);\n          color: black;\n        }\n        #bodycontainer {\n          -webkit-user-select: text;\n          user-select: text;\n        }\n        :host([edit-mode][hax-ray-mode])\n          #bodycontainer\n          ::slotted(*[data-editable]):before {\n          content: attr(data-hax-ray) \" \" attr(resource) \" \" attr(typeof) \" \"\n            attr(property) \" \" attr(content);\n          font-size: 10px;\n          font-style: italic;\n          left: unset;\n          right: unset;\n          top: unset;\n          background-color: #d3d3d3;\n          color: #000000;\n          bottom: unset;\n          width: auto;\n          padding: 8px;\n          margin: 0;\n          z-index: 1;\n          margin: -16px 0 0 0;\n          float: right;\n          line-height: 2;\n        }\n      </style>\n      <div id=\"bodycontainer\" class=\"ignore-activation\">\n        <slot id=\"body\"></slot>\n      </div>\n      <hax-text-context\n        id=\"textcontextmenu\"\n        class=\"hax-context-menu ignore-activation\"\n      ></hax-text-context>\n      <hax-ce-context\n        id=\"cecontextmenu\"\n        class=\"hax-context-menu ignore-activation\"\n      ></hax-ce-context>\n      <hax-plate-context\n        id=\"platecontextmenu\"\n        class=\"hax-context-menu ignore-activation\"\n      ></hax-plate-context>\n      <hax-input-mixer\n        id=\"haxinputmixer\"\n        class=\"hax-context-menu ignore-activation\"\n      ></hax-input-mixer>\n    "]);
  
      _templateObject_ece2eff0c3a011e99204fd28bf05b7e9 = function _templateObject_ece2eff0c3a011e99204fd28bf05b7e9() {
        return data;
      };
  
      return data;
    }
  
    /**
     * `hax-body`
     * `Manager of the body area that can be modified`
     * @microcopy - the mental model for this element
     *  - body is effectively a body of content that can be manipulated in the browser. This is for other HAX elements ultimately to interface with and reside in. It is the controller of input and output for all of HAX as it exists in a document. body is not the <body> tag but we need a similar mental model container for all our other elements.
     *  - text-context - the context menu that shows up when an item is active so it can have text based operations performed to it.
     *  - plate/grid plate - a plate or grid plate is a container that we can operate on in HAX. it can also have layout / "global" type of body operations performed on it such as delete, duplicate and higher level format styling.
     */
    var HaxBody =
    /*#__PURE__*/
    function (_PolymerElement) {
      babelHelpers.inherits(HaxBody, _PolymerElement);
  
      function HaxBody() {
        var _this;
  
        babelHelpers.classCallCheck(this, HaxBody);
        _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(HaxBody).call(this));
        new Promise(function (res, rej) {
          return _require.default(["../../@polymer/iron-a11y-keys/iron-a11y-keys.js"], res, rej);
        });
        new Promise(function (res, rej) {
          return _require.default(["../../@polymer/paper-item/paper-item.js"], res, rej);
        });
        new Promise(function (res, rej) {
          return _require.default(["../grid-plate/grid-plate.js"], res, rej);
        });
        return _this;
      }
  
      babelHelpers.createClass(HaxBody, [{
        key: "ready",
  
        /**
         * Ready state to tee everything up.
         */
        value: function ready() {
          babelHelpers.get(babelHelpers.getPrototypeOf(HaxBody.prototype), "ready", this).call(this);
          this.dispatchEvent(new CustomEvent("hax-register-body", {
            bubbles: true,
            cancelable: true,
            composed: true,
            detail: this
          }));
          this.polyfillSafe = window.HaxStore.instance.computePolyfillSafe(); // mutation observer that ensures state of hax applied correctly
  
          (0, _renderStatus.afterNextRender)(this, function () {
            var _this2 = this;
  
            this._observer = new _flattenedNodesObserver.FlattenedNodesObserver(this, function (info) {
              // MAKE SURE WE KNOW WHAT JUST GOT ADDED HERE
              (0, _flush.flush)(); // if we've got new nodes, we have to react to that
  
              if (info.addedNodes.length > 0) {
                info.addedNodes.map(function (node) {
                  if (_this2._haxElementTest(node)) {
                    if (_this2._HTMLPrimativeTest(node)) {
                      node.contentEditable = _this2.editMode;
                    } // this does the real targetting
  
  
                    node.setAttribute("data-editable", _this2.editMode);
                    var haxRay = node.tagName.replace("-", " ").toLowerCase();
                    var i = window.HaxStore.instance.gizmoList.findIndex(function (j) {
                      return j.tag === node.tagName.toLowerCase();
                    });
  
                    if (i !== -1) {
                      haxRay = window.HaxStore.instance.gizmoList[i].title;
                    }
  
                    node.setAttribute("data-hax-ray", haxRay);
  
                    _this2.dispatchEvent(new CustomEvent("hax-body-tag-added", {
                      bubbles: true,
                      cancelable: true,
                      composed: true,
                      detail: {
                        node: node
                      }
                    }));
                  }
                });
              } // if we dropped nodes via the UI (delete event basically)
  
  
              if (info.removedNodes.length > 0) {
                // handle removing items... not sure we need to do anything here
                info.removedNodes.map(function (node) {
                  if (_this2._haxElementTest(node) && !node.classList.contains("hax-active")) {
                    _this2.dispatchEvent(new CustomEvent("hax-body-tag-removed", {
                      bubbles: true,
                      cancelable: true,
                      composed: true,
                      detail: {
                        node: node
                      }
                    }));
                  }
                });
              }
            });
            this.addEventListener("hax-context-item-selected", this._haxContextOperation.bind(this));
            this.addEventListener("hax-input-mixer-update", this._haxInputMixerOperation.bind(this));
            this.addEventListener("place-holder-replace", this.replacePlaceholder.bind(this)); // try to normalize paragraph insert on enter
  
            try {
              document.execCommand("enableObjectResizing", false, false);
              document.execCommand("defaultParagraphSeparator", false, "p");
            } catch (e) {
              console.log(e);
            }
  
            window.addEventListener("keydown", this._onKeyDown.bind(this));
            window.addEventListener("keypress", this._onKeyPress.bind(this));
            this.shadowRoot.querySelector("slot").addEventListener("mousemove", this.hoverEvent.bind(this));
            this.shadowRoot.querySelector("slot").addEventListener("mouseup", function (e) {
              var tmp = window.HaxStore.getSelection();
              window.HaxStore._tmpSelection = tmp;
  
              try {
                var range = window.HaxStore.getRange();
  
                if (range.cloneRange) {
                  window.HaxStore._tmpRange = range.cloneRange();
                }
              } catch (e) {
                console.log(e);
              }
            });
            document.body.addEventListener("hax-store-property-updated", this._haxStorePropertyUpdated.bind(this));
            window.addEventListener("scroll", this._keepContextVisible.bind(this));
            this.addEventListener("focusin", this._focusIn.bind(this));
            this.addEventListener("mousedown", this._focusIn.bind(this));
          });
        }
        /**
         * Attached to the DOM; now we can fire event to the store that
         * we exist and are the thing being edited.
         */
  
      }, {
        key: "connectedCallback",
        value: function connectedCallback() {
          babelHelpers.get(babelHelpers.getPrototypeOf(HaxBody.prototype), "connectedCallback", this).call(this);
          (0, _renderStatus.afterNextRender)(this, function () {
            // in case we miss this on the initial setup. possible in auto opening environments.
            this.editMode = window.HaxStore.instance.editMode; // ensure this resets every append
  
            this.__tabTrap = false;
          });
        }
        /**
         * Keep the context menu visible if needed
         */
  
      }, {
        key: "_keepContextVisible",
        value: function _keepContextVisible(e) {
          // see if the text context menu is visible
          var el = false;
  
          if (this.$.textcontextmenu.classList.contains("hax-context-visible")) {
            el = this.$.textcontextmenu;
          } else if (this.$.cecontextmenu.classList.contains("hax-context-visible")) {
            el = this.$.cecontextmenu;
          } // if we see it, ensure we don't have the pin
  
  
          if (el) {
            if (this.elementInViewport(el)) {
              el.classList.remove("hax-context-pin-bottom", "hax-context-pin-top");
            } else {
              if (this.__OffBottom) {
                el.classList.add("hax-context-pin-top");
              } else {
                el.classList.add("hax-context-pin-bottom");
              }
            }
          }
        }
      }, {
        key: "_onKeyDown",
        value: function _onKeyDown(e) {
          var _this3 = this;
  
          if (this.editMode && this.getAttribute("contenteditable")) {
            setTimeout(function () {
              var rng = window.HaxStore.getRange();
  
              switch (e.key) {
                case "Tab":
                  if (window.HaxStore.instance.isTextElement(_this3.activeContainerNode)) {
                    if (e.detail.keyboardEvent) {
                      e.detail.keyboardEvent.preventDefault();
                      e.detail.keyboardEvent.stopPropagation();
                      e.detail.keyboardEvent.stopImmediatePropagation();
                    }
  
                    e.preventDefault();
                    e.stopPropagation();
                    e.stopImmediatePropagation();
  
                    if (e.shiftKey) {
                      _this3._tabBackKeyPressed();
                    } else {
                      _this3._tabKeyPressed();
                    }
                  }
  
                  break;
  
                case "Enter":
                  _this3.setAttribute("contenteditable", true);
  
                  setTimeout(function () {
                    if (rng.commonAncestorContainer && typeof rng.commonAncestorContainer.focus === "function") {
                      rng.commonAncestorContainer.focus();
  
                      _this3.__focusLogic(rng.commonAncestorContainer);
                    }
                  }, 900);
                  break;
  
                case "ArrowUp":
                case "ArrowDown":
                case "ArrowLeft":
                case "ArrowRight":
                  if (rng.commonAncestorContainer && _this3.activeNode !== rng.commonAncestorContainer && typeof rng.commonAncestorContainer.focus === "function") {
                    if (rng.commonAncestorContainer.tagName !== "HAX-BODY") {
                      if (window.HaxStore.instance.isTextElement(rng.commonAncestorContainer)) {
                        _this3.setAttribute("contenteditable", true);
                      } else {
                        _this3.removeAttribute("contenteditable");
                      }
  
                      setTimeout(function () {
                        rng.commonAncestorContainer.focus();
  
                        _this3.__focusLogic(rng.commonAncestorContainer);
                      }, 900);
                    }
                  } // need to check on the parent too if this was a text node
                  else if (rng.commonAncestorContainer && rng.commonAncestorContainer.parentNode && _this3.activeNode !== rng.commonAncestorContainer.parentNode && typeof rng.commonAncestorContainer.parentNode.focus === "function") {
                      if (rng.commonAncestorContainer.parentNode.tagName !== "HAX-BODY") {
                        if (window.HaxStore.instance.isTextElement(rng.commonAncestorContainer.parentNode)) {
                          _this3.setAttribute("contenteditable", true);
                        } else {
                          _this3.removeAttribute("contenteditable");
                        }
  
                        setTimeout(function () {
                          rng.commonAncestorContainer.parentNode.focus();
  
                          _this3.__focusLogic(rng.commonAncestorContainer.parentNode);
                        }, 900);
                      }
                    }
  
                  break;
              }
            }, 100);
  
            if (this.$.platecontextmenu.classList.contains("hax-active-hover")) {
              this.__dropActiveHover();
            }
          }
        }
      }, {
        key: "_onKeyPress",
        value: function _onKeyPress(e) {
          if (this.editMode && this.$.platecontextmenu.classList.contains("hax-active-hover")) {
            this.__dropActiveHover();
          }
        }
        /**
         * on mouse over then fire the hax ray value if we have one
         */
  
      }, {
        key: "hoverEvent",
        value: function hoverEvent(e) {
          if (this.editMode) {
            if (e.target && e.target.getAttribute("data-hax-ray") != null) {
              this.__activeHover = e.target;
              this.dispatchEvent(new CustomEvent("hax-active-hover-name", {
                bubbles: true,
                cancelable: true,
                composed: true,
                detail: e.target.getAttribute("data-hax-ray")
              }));
            } else if (e.target && e.target.parentNode && e.target.parentNode.getAttribute("data-hax-ray") != null) {
              this.__activeHover = e.target.parentNode;
              this.dispatchEvent(new CustomEvent("hax-active-hover-name", {
                bubbles: true,
                cancelable: true,
                composed: true,
                detail: e.target.parentNode.getAttribute("data-hax-ray")
              }));
            }
  
            if (!this.$.platecontextmenu.classList.contains("hax-active-hover")) {
              var normalizedEvent = (0, _polymerDom.dom)(e);
              var local = normalizedEvent.localTarget; // see if the target is relevent when showing the edit menu operations
  
              if (e.target === this.$.cecontextmenu || e.target === this.$.textcontextmenu || e.target === this.$.platecontextmenu || local === this.activeNode || local === this.activeContainerNode || e.target === this.activeNode || e.target === this.activeContainerNode || local.parentNode === this.activeContainerNode || local.parentNode.parentNode === this.activeContainerNode || local.parentNode.parentNode.parentNode === this.activeContainerNode) {
                this.__addActiveHover();
  
                this.__typeLock = false;
              } else {
                this.__dropActiveHover();
              }
            }
          }
        }
      }, {
        key: "__addActiveHover",
        value: function __addActiveHover() {
          this.$.cecontextmenu.classList.add("hax-active-hover");
          this.$.textcontextmenu.classList.add("hax-active-hover");
          this.$.platecontextmenu.classList.add("hax-active-hover");
        }
      }, {
        key: "__dropActiveHover",
        value: function __dropActiveHover() {
          this.$.cecontextmenu.classList.remove("hax-active-hover");
          this.$.textcontextmenu.classList.remove("hax-active-hover");
          this.$.platecontextmenu.classList.remove("hax-active-hover");
        }
        /**
         * Check if part of the passed element is int he viewport
         */
  
      }, {
        key: "elementInViewport",
        value: function elementInViewport(el) {
          var top = el.offsetTop - 32 - window.HaxStore.instance.haxPanel.$.drawer.offsetHeight;
          var left = el.offsetLeft;
          var width = el.offsetWidth;
          var height = el.offsetHeight;
  
          while (el.offsetParent) {
            el = el.offsetParent;
            top += el.offsetTop;
            left += el.offsetLeft;
          }
  
          this.__OffBottom = top < window.pageYOffset + window.innerHeight;
          return top < window.pageYOffset + window.innerHeight && left < window.pageXOffset + window.innerWidth && top + height > window.pageYOffset && left + width > window.pageXOffset;
        }
        /**
         * Replace place holder after an event has called for it in the element itself
         */
  
      }, {
        key: "replacePlaceholder",
        value: function replacePlaceholder(e) {
          var _this4 = this;
  
          // generate a paragraph of text here on click
          if (e.detail === "text") {
            // make sure text just escalates to a paragraph tag
            var p = document.createElement("p");
            p.innerHTML = "<br/>";
            this.haxReplaceNode(this.activeNode, p, (0, _polymerDom.dom)(this.activeNode).parentNode); // allow swap out to happen
  
            setTimeout(function () {
              // set active to this p tag
              _this4.activeNode = p;
              window.HaxStore.write("activeNode", p, _this4);
  
              _this4.activeContainerNode.setAttribute("contenteditable", true); // focus on it
  
  
              p.focus();
  
              _this4.__focusLogic(p);
            }, 210);
          } else {
            this.replaceElementWorkflow();
          }
        }
        /**
         * Whole workflow of replacing something in place contextually.
         * This can fire for things like events needing this workflow to
         * invoke whether it's a "convert" event or a "replace placeholder" event
         */
  
      }, {
        key: "replaceElementWorkflow",
        value: function replaceElementWorkflow() {
          var element = window.HaxStore.nodeToHaxElement(this.activeNode, null);
          var type = "*";
          var skipPropMatch = false; // special support for place holder which defines exactly
          // what the user wants this replaced with
  
          if (element.tag === "place-holder" && babelHelpers.typeof(element.properties["type"]) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
            type = element.properties["type"];
            skipPropMatch = true;
          }
  
          var props = {}; // see if we have a gizmo as it's not a requirement to registration
          // as well as having handlers since mapping is not required either
  
          if (babelHelpers.typeof(window.HaxStore.instance.elementList[element.tag]) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && window.HaxStore.instance.elementList[element.tag].gizmo !== false && babelHelpers.typeof(window.HaxStore.instance.elementList[element.tag].gizmo.handles) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && window.HaxStore.instance.elementList[element.tag].gizmo.handles.length > 0) {
            // get the haxProperties for this item
            var gizmo = window.HaxStore.instance.elementList[element.tag].gizmo; // walk through each handler
  
            for (var i = 0; i < gizmo.handles.length; i++) {
              // walk the properties defined as they would be to the
              // left side of the ledger and tell us which property to
              // mesh with. This effectively rehydrates / inverts that
              // relationship where we have an element and want to say
              // "oh ya, but what could have handled this" so that we
              // can use that translation to offer up convertion to a
              // new element. This is insane.
              for (var prop in gizmo.handles[i]) {
                // type is a reserved handler but any other property
                // which we actually have in our element let's go for it
                if (prop !== "type" && babelHelpers.typeof(element.properties[gizmo.handles[i][prop]]) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
                  // The cake is a lie... oh wait... no it's not.
                  // This will completely bend your mind when it comes to
                  // what HTML is, how it should operate and what universe
                  // we can now contort as a result. This effectively allows
                  // reverse engineering any element on the page into any
                  // other compatible element based on the properties in
                  // each element claiming to be compatible.
                  props[prop] = element.properties[gizmo.handles[i][prop]];
                }
              }
            }
          }
  
          var haxElements = window.HaxStore.guessGizmo(type, props, skipPropMatch); // see if we got anything
  
          if (haxElements.length > 0) {
            // hand off to hax-app-picker to deal with the rest of this
            var tag = this.activeNode.tagName.toLowerCase();
            var humanName = tag.replace("-", " ");
  
            if (babelHelpers.typeof(window.HaxStore.instance.elementList[tag]) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && window.HaxStore.instance.elementList[tag].gizmo !== false) {
              humanName = window.HaxStore.instance.elementList[tag].gizmo.title;
            }
  
            window.HaxStore.instance.haxAppPicker.presentOptions(haxElements, "__convert", "Transform ".concat(humanName, " to.."), "gizmo");
          } else {
            window.HaxStore.toast("Sorry, this can not be transformed!", 5000);
          }
        }
        /**
         * Global prefs updated, let's visualize stuff from hax-ray
         */
  
      }, {
        key: "_globalPreferencesUpdated",
        value: function _globalPreferencesUpdated(newValue, oldValue) {
          if (babelHelpers.typeof(newValue) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && newValue != null) {
            this.haxRayMode = newValue.haxRayMode;
          }
        }
        /**
         * Store updated, sync.
         */
  
      }, {
        key: "_haxStorePropertyUpdated",
        value: function _haxStorePropertyUpdated(e) {
          if (e.detail && babelHelpers.typeof(e.detail.value) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && e.detail.property) {
            if (babelHelpers.typeof(e.detail.value) === "object") {
              this.set(e.detail.property, null);
            }
  
            this.set(e.detail.property, e.detail.value);
          }
        }
        /**
         * Clear area.
         */
  
      }, {
        key: "haxClearBody",
        value: function haxClearBody() {
          var confirm = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
          var status = true; // only confirm if asked so we can support wipes without it
  
          if (confirm) {
            status = prompt("Are you sure you want to delete all content?");
          } // ensure they said yes
  
  
          if (status) {
            (0, _haxutils.wipeSlot)(this);
          }
        }
        /**
         * Insert new tag + content into the local DOM as a node.
         */
  
      }, {
        key: "haxInsert",
        value: function haxInsert(tag, content) {
          var _this5 = this;
  
          var properties = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
          var waitForLock = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
          this.__activeHover = null; // verify this tag is a valid one
          // create a new element fragment w/ content in it
          // if this is a custom-element it won't expand though
  
          var frag = document.createElement(tag); // set text forcibly
          //frag.innerText = content;
          // now set html forcibly which would overwrite the other one
  
          frag.innerHTML = content; // clone the fragment which will force an escalation to full node
  
          var newNode = frag.cloneNode(true); // support for properties if they exist
  
          for (var property in properties) {
            var attributeName = window.HaxStore.camelToDash(property);
  
            if (properties.hasOwnProperty(property)) {
              // special supporting for boolean because html is weird :p
              if (properties[property] === true) {
                newNode.setAttribute(attributeName, attributeName);
              } else if (properties[property] === false) {
                newNode.removeAttribute(attributeName);
              } else if (properties[property] != null && properties[property].constructor === Array) {
                if (newNode.properties && newNode.properties[property].readOnly) {} else {
                  newNode.set(attributeName, properties[property]);
                }
              } else if (properties[property] != null && properties[property].constructor === Object) {
                if (newNode.properties && newNode.properties[property].readOnly) {} else {
                  newNode.set(attributeName, properties[property]);
                }
              } else {
                newNode.setAttribute(attributeName, properties[property]);
              }
            }
          } // special support for a drag and drop into a place-holder tag
          // as this is a more aggressive operation then the others
  
  
          if (window.HaxStore.instance.activePlaceHolder !== null && babelHelpers.typeof(window.HaxStore.instance.activePlaceHolder.style) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
            // replicate styles so that it doesn't jar the UI
            newNode.style.width = window.HaxStore.instance.activePlaceHolder.style.width;
            newNode.style.float = window.HaxStore.instance.activePlaceHolder.style.float;
            newNode.style.margin = window.HaxStore.instance.activePlaceHolder.style.margin;
            newNode.style.display = window.HaxStore.instance.activePlaceHolder.style.display;
            this.haxReplaceNode(window.HaxStore.instance.activePlaceHolder, newNode, (0, _polymerDom.dom)(window.HaxStore.instance.activePlaceHolder).parentNode);
            window.HaxStore.instance.activePlaceHolder = null;
          } // insert at active insert point if we have one
          else if (this.activeContainerNode != null) {
              // allow for inserting things into things but not grid plate
              if (newNode.tagName !== "GRID-PLATE" && this.activeContainerNode.tagName === "GRID-PLATE" && this.activeContainerNode !== this.activeNode) {
                if (this.activeNode.getAttribute("slot") != null) {
                  newNode.setAttribute("slot", this.activeNode.getAttribute("slot"));
                }
  
                (0, _polymerDom.dom)(this.activeContainerNode).insertBefore(newNode, this.activeNode);
              } else {
                (0, _polymerDom.dom)(this).insertBefore(newNode, this.activeContainerNode.nextElementSibling);
              }
            } else {
              // send this into the root, which should filter it back down into the slot
              (0, _polymerDom.dom)(this).appendChild(newNode);
            }
  
          this.$.textcontextmenu.highlightOps = false;
          this.__updateLockFocus = newNode; // wait so that the DOM can have the node to then attach to
  
          if (waitForLock) {
            setTimeout(function () {
              _this5.breakUpdateLock();
            }, 50);
          }
  
          return true;
        }
      }, {
        key: "breakUpdateLock",
        value: function breakUpdateLock() {
          window.HaxStore.write("activeContainerNode", this.__updateLockFocus, this);
          window.HaxStore.write("activeNode", this.__updateLockFocus, this); // attempt to focus on the new node, may not always work
  
          this.__updateLockFocus.focus(); // scroll to it
  
  
          if (typeof this.__updateLockFocus.scrollIntoViewIfNeeded === "function") {
            this.__updateLockFocus.scrollIntoViewIfNeeded(true);
          } else {
            this.__updateLockFocus.scrollIntoView({
              behavior: "smooth",
              inline: "center"
            });
          }
        }
        /**
         * Return the current hax content area as text that could be
         * inserted into something.
         */
  
      }, {
        key: "haxToContent",
        value: function haxToContent() {
          this.hideContextMenus();
          var __active = this.activeNode; // null this to drop hax based classes
  
          this.set("activeNode", null);
          this.set("activeContainerNode", null);
          window.HaxStore.write("activeNode", null, this);
          window.HaxStore.write("activeContainerNode", null, this);
          var children = (0, _polymerDom.dom)(this.$.body).getDistributedNodes();
  
          if (this.globalPreferences.haxDeveloperMode) {
            console.log(children);
          }
  
          var content = "";
  
          for (var i = 0, len = children.length; i < len; i++) {
            // some mild front-end sanitization
            if (this._haxElementTest(children[i])) {
              children[i].removeAttribute("data-editable");
              children[i].removeAttribute("data-hax-ray");
              children[i].contentEditable = false;
              content += window.HaxStore.nodeToContent(children[i]);
  
              if (children[i].tagName.toLowerCase() === "grid-plate") {
                this._applyContentEditable(this.editMode, children[i]);
              }
            } // keep comments with a special case since they need wrapped
            else if (children[i].nodeType === 8) {
                content += "<!-- " + children[i].textContent + " -->";
              } // keep everything NOT an element at this point, this helps
              // preserve whitespace because we're crazy about accuracy
              else if (children[i].nodeType !== 1 && babelHelpers.typeof(children[i].textContent) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && children[i].textContent !== "undefined") {
                  content += children[i].textContent;
                }
          } // remove the contenteditable attribute
  
  
          content = content.replace(/\scontenteditable=\"false\"/g, ""); // remove the data-editable attribute
  
          content = content.replace(/\sdata-editable=\"true\"/g, "");
          content = content.replace(/\sdata-editable=\"false\"/g, "");
          content = content.replace(/\sdata-editable=\""/g, ""); // remove other attributes that can linger in slots
  
          content = content.replace(/\sdata-editable/g, "");
          content = content.replace(/\scontenteditable/g, "");
          content = content.replace(/\sdraggable/g, "");
          content = content.replace(/\sdata-draggable/g, ""); // clean up stray hax-ray leftovers
  
          content = content.replace(/\sdata-hax-ray=\".*?\"/g, ""); // remove HAX specific classes / scoping classes
  
          if (this.parentNode.tagName) {
            var parentTag = this.parentNode.tagName.toLowerCase();
            var string = "style-scope " + parentTag + " x-scope";
            var re = new RegExp(string, "g");
            content = content.replace(re, ""); // remove without the deeeper scope as well for primitives
  
            string = "style-scope " + parentTag;
            re = new RegExp(string, "g");
            content = content.replace(re, ""); // remove the last common one unpacked
  
            string = "x-scope " + parentTag + "-0";
            re = new RegExp(string, "g");
            content = content.replace(re, ""); // now all tags we have defined as valid
  
            var tags = window.HaxStore.instance.validTagList;
            tags.push("hax-preview");
  
            for (var i in tags) {
              string = "style-scope " + tags[i];
              re = new RegExp(string, "g");
              content = content.replace(re, "");
              string = "x-scope " + tags[i] + "-0 ";
              re = new RegExp(string, "g");
              content = content.replace(re, "");
              string = "x-scope " + tags[i] + "-0";
              re = new RegExp(string, "g");
              content = content.replace(re, "");
            }
          } // remove empty class structures
  
  
          content = content.replace(/\sclass=\"\"/g, "");
          content = content.replace(/\sclass=\"\s\"/g, ""); // re-apply contenteditable if needed
  
          this._applyContentEditable(this.editMode); // set active again
  
  
          window.HaxStore.write("activeNode", __active, this);
          window.HaxStore.write("activeContainerNode", __active, this); // oh one last thing. escape all script/style tags
  
          content = (0, _haxutils.encapScript)(content);
  
          if (this.globalPreferences.haxDeveloperMode) {
            console.log(content);
          }
  
          return content;
        }
        /**
         * Duplicate node into the local DOM below the current item if we can.
         */
  
      }, {
        key: "haxDuplicateNode",
        value: function haxDuplicateNode(node) {
          var _this6 = this;
  
          var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this;
          // move the context menu before duplicating!!!!
          this.hideContextMenus(); // convert the node to a hax element
  
          var haxElement = window.HaxStore.nodeToHaxElement(node, null); // support for deep API call to clean up special elements
  
          if (babelHelpers.typeof(node.preProcessHaxInsertContent) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
            haxElement = node.preProcessHaxInsertContent(haxElement);
          } // convert it back to a clone, seems odd I'm sure but this ensures that all props are copied
          // correctly and that we get a brand new object
  
  
          var nodeClone = window.HaxStore.haxElementToNode(haxElement.tag, haxElement.content, haxElement.properties);
  
          if (nodeClone.tagName.toLowerCase() === "webview" && window.HaxStore.instance._isSandboxed && babelHelpers.typeof(nodeClone.guestinstance) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
            delete nodeClone.guestinstance;
          } // shouldn't be possible but might as well check
  
  
          if (node !== null) {
            (0, _polymerDom.dom)(parent).insertBefore(nodeClone, (0, _polymerDom.dom)(node).nextSibling);
          } else {
            (0, _polymerDom.dom)(parent).appendChild(nodeClone);
          }
  
          setTimeout(function () {
            // test for a grid plate clone
            if (parent === _this6) {
              window.HaxStore.write("activeContainerNode", nodeClone, _this6);
            }
  
            window.HaxStore.write("activeNode", nodeClone, _this6);
          }, 50);
          return true;
        }
        /**
         * Hide all context menus.
         */
  
      }, {
        key: "hideContextMenus",
        value: function hideContextMenus() {
          // primary context menus
          this._hideContextMenu(this.$.textcontextmenu);
  
          this._hideContextMenu(this.$.cecontextmenu); // secondary menus and clean up areas
  
  
          this._hideContextMenu(this.$.platecontextmenu);
  
          this._hideContextMenu(this.$.haxinputmixer); // force context menu state to closed
  
  
          this.$.textcontextmenu.highlightOps = false;
        }
        /**
         * Reposition context menus to match an element.
         */
  
      }, {
        key: "positionContextMenus",
        value: function positionContextMenus(node, container) {
          if (node) {
            var tag = node.tagName.toLowerCase();
  
            if (window.HaxStore.instance._isSandboxed && tag === "webview") {
              tag = "iframe";
            }
  
            var props = window.HaxStore.instance.elementList[tag]; // try and work against anything NOT a P tag
  
            if (babelHelpers.typeof(props) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && !window.HaxStore.instance.isTextElement(node)) {
              this.__activeContextType = this.$.cecontextmenu;
              props.element = node;
  
              this.__activeContextType.setHaxProperties(props);
            } else {
              this.__activeContextType = this.$.textcontextmenu;
            }
  
            this._positionContextMenu(this.__activeContextType, container, -39, -39);
  
            this._positionContextMenu(this.$.platecontextmenu, container, -31, 0); // special case for node not matching container
  
  
            if (container && !this._HTMLPrimativeTest(node) && node !== container) {
              container.contentEditable = false;
            } else if (container && this._HTMLPrimativeTest(container)) {
              container.contentEditable = true;
            }
          }
        }
        /**
         * Move grid plate around
         */
  
      }, {
        key: "haxMoveGridPlate",
        value: function haxMoveGridPlate(direction, node, container) {
          var _this7 = this;
  
          // menu is actually in the element for render purposes
          // support moving things multiple directions
          switch (direction) {
            case "first":
              // ensure we can go up, first being a mode of up
              if (container.previousElementSibling !== null) {
                (0, _polymerDom.dom)(this).insertBefore(container, (0, _polymerDom.dom)(this).firstChild);
              }
  
              break;
  
            case "up":
              // ensure we can go up
              if (container.previousElementSibling !== null) {
                (0, _polymerDom.dom)(this).insertBefore(container, container.previousElementSibling);
              }
  
              break;
  
            case "down":
              if (container.nextElementSibling !== null) {
                (0, _polymerDom.dom)(this).insertBefore(container.nextElementSibling, container);
              }
  
              break;
  
            case "last":
              if (container.nextElementSibling !== null) {
                (0, _polymerDom.dom)(this).appendChild(container);
              }
  
              break;
            // @todo support other directions for when inside of an element
          }
  
          setTimeout(function () {
            _this7.positionContextMenus(node, container);
  
            if (typeof container.scrollIntoViewIfNeeded === "function") {
              container.scrollIntoViewIfNeeded(true);
            } else {
              container.scrollIntoView({
                behavior: "smooth",
                inline: "center"
              });
            }
          }, 50);
          return true;
        }
        /**
         * Convert an element from one tag to another.
         */
  
      }, {
        key: "haxReplaceNode",
        value: function haxReplaceNode(node, replacement) {
          var parent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this;
          // ensure we're not in the document tree for the replaced node
          this.hideContextMenus(); // Switch, try loop in case we screwed up elsewhere
  
          try {
            // test for slots to match
            if (node.getAttribute("slot") != null) {
              replacement.setAttribute("slot", node.getAttribute("slot"));
            }
  
            if (node == null) {
              node = this.__oldActiveNode;
              parent = this.__oldActiveNode.parentNode;
            }
  
            (0, _polymerDom.dom)(parent).replaceChild(replacement, node);
          } catch (e) {
            console.log(e);
          }
  
          return replacement;
        }
        /**
         * Convert an element from one tag to another.
         */
  
      }, {
        key: "haxChangeTagName",
        value: function haxChangeTagName(node, tagName, newNode) {
          // ensure we're not in the document tree for the replaced node
          this.hideContextMenus(); // Create a replacement tag of the desired type
  
          var replacement = document.createElement(tagName); // Grab all of the original's attributes, and pass them to the replacement
  
          for (var i = 0, l = node.attributes.length; i < l; ++i) {
            var nodeName = node.attributes.item(i).nodeName;
            var value = node.attributes.item(i).value;
            replacement.setAttribute(nodeName, value);
          } // Persist contents
          // account for empty list and ordered list items
  
  
          replacement.innerHTML = node.innerHTML.trim();
  
          if (tagName == "ul" || tagName == "ol") {
            if (replacement.innerHTML == "") {
              replacement.innerHTML = "<li></li>";
            } else if (!(node.tagName.toLowerCase() == "ul" || node.tagName.toLowerCase() == "ol")) {
              replacement.innerHTML = "<li>" + node.innerHTML.trim().replace(/<br\/>/g, "</li>\n<li>").replace(/<br>/g, "</li>\n<li>") + "</li>";
            }
          } else if (node.tagName.toLowerCase() == "ul" || node.tagName.toLowerCase() == "ol") {
            // if we're coming from ul or ol strip out the li tags
            replacement.innerHTML = replacement.innerHTML.replace(/<ul>/g, "").replace(/<\/ul>/g, "").replace(/<li><\/li>/g, "").replace(/<li>/g, "").replace(/<\/li>/g, "<br/>");
          } // Switch!
  
  
          try {
            (0, _polymerDom.dom)(this).replaceChild(replacement, node); // focus on the thing switched to
  
            setTimeout(function () {
              var children = (0, _polymerDom.dom)(replacement).getEffectiveChildNodes(); // see if there's a child element and focus that instead if there is
  
              if (children[0] && children.tagName) {
                children[0].focus();
              } else {
                replacement.focus();
              }
            }, 50);
          } catch (e) {
            console.log(e);
            console.log(replacement);
            console.log(node);
          }
  
          return replacement;
        }
        /**
         * Delete the node passed in
         */
  
      }, {
        key: "haxDeleteNode",
        value: function haxDeleteNode(node) {
          var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this;
          // move the context menu before deleting!!!!
          this.hideContextMenus(); // shift active to a viable replacement
  
          if (this.activeContainerNode != null && this.activeContainerNode.previousElementSibling !== null) {
            this.activeContainerNode.previousElementSibling.focus(); // cursor at the END of the element assuming not empty
  
            if (this.activeContainerNode != null && window.HaxStore.instance.isTextElement(this.activeContainerNode) && (0, _polymerDom.dom)(this.activeContainerNode).textContent !== "") {
              try {
                var range = document.createRange();
                var sel = window.HaxStore.getSelection();
                range.setStart(this.activeContainerNode, 1);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
                this.activeContainerNode.focus();
              } catch (e) {
                console.log(e);
              }
            }
          } else if (this.activeContainerNode != null && this.activeContainerNode.nextElementSibling !== null) {
            this.activeContainerNode.nextElementSibling.focus();
          } else {
            this.set("activeNode", null);
            this.set("activeContainerNode", null);
            window.HaxStore.write("activeNode", null, this);
            window.HaxStore.write("activeContainerNode", null, this);
          } // @todo figure out why this is complaining
  
  
          try {
            return (0, _polymerDom.dom)(parent).removeChild(node);
          } catch (e) {
            console.log(e);
          }
        }
        /**
         * Bulk import HTML with option to clear what is currently
         * in the slot of this tag. This also validates tags
         * that are being inserted for security based on the
         * internal whitelist.
         */
  
      }, {
        key: "importContent",
        value: function importContent(html) {
          var _this8 = this;
  
          var clear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  
          // kill the slot of the active body, all of it
          if (clear) {
            (0, _haxutils.wipeSlot)(this, "*");
          } // pause quickly to ensure wipe goes through successfully
  
  
          setTimeout(function () {
            html = (0, _haxutils.encapScript)(html);
            var fragment = document.createElement("div");
            fragment.insertAdjacentHTML("beforeend", html);
  
            while (fragment.firstChild !== null) {
              if (babelHelpers.typeof(fragment.firstChild.tagName) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
                // ensure import doesn't import non-sandbox safe things!
                if (window.HaxStore.instance._isSandboxed && fragment.firstChild.tagName.toLowerCase() === "iframe") {
                  // Create a replacement tag of the desired type
                  var replacement = document.createElement("webview"); // Grab all of the original's attributes, and pass them to the replacement
  
                  for (var j = 0, l = fragment.firstChild.attributes.length; j < l; ++j) {
                    var nodeName = fragment.firstChild.attributes.item(j).nodeName;
                    var value = fragment.firstChild.attributes.item(j).value;
  
                    if (nodeName === "height" || nodeName === "width") {
                      replacement.style[nodeName] == value;
                    }
  
                    replacement.setAttribute(nodeName, value);
                  }
  
                  (0, _polymerDom.dom)(_this8).appendChild(replacement);
                } else {
                  (0, _polymerDom.dom)(_this8).appendChild(fragment.firstChild);
                }
              } else {
                // @todo might want to support appending or keeping track of comments / non tags
                // but this is not a must have
                fragment.removeChild(fragment.firstChild);
              }
            }
          }, 50);
        }
        /**
         * Respond to hax operations.
         */
  
      }, {
        key: "_haxContextOperation",
        value: function _haxContextOperation(e) {
          var _this9 = this;
  
          var detail = e.detail;
          var haxElement; // support a simple insert event to bubble up or everything else
  
          switch (detail.eventName) {
            // text based operations for primatives
            case "p":
            case "ol":
            case "ul":
            case "h2":
            case "h3":
            case "h4":
            case "h5":
            case "h6":
            case "blockquote":
            case "code":
              // trigger the default selected value in context menu to match
              this.$.textcontextmenu.selectedValue = detail.eventName;
              window.HaxStore.write("activeContainerNode", this.haxChangeTagName(this.activeContainerNode, detail.eventName), this);
              this.positionContextMenus(this.activeNode, this.activeContainerNode);
              break;
  
            case "text-align-left":
              this.activeNode.style.textAlign = null;
              this.positionContextMenus(this.activeNode, this.activeContainerNode);
              break;
            // grid plate based operations
            // allow for transforming this haxElement into another one
  
            case "grid-plate-convert":
              this.replaceElementWorkflow();
              break;
            // duplicate the active item or container
  
            case "grid-plate-duplicate":
              if (this.activeNode === this.activeContainerNode) {
                this.haxDuplicateNode(this.activeNode);
              } else {
                this.haxDuplicateNode(this.activeNode, this.activeContainerNode);
              }
  
              break;
  
            case "grid-plate-delete":
              if (this.activeNode != null) {
                var options = [{
                  icon: "thumb-up",
                  color: "green",
                  title: "Yes"
                }, {
                  icon: "thumb-down",
                  color: "red",
                  title: "No"
                }];
                var tag = this.activeNode.tagName.toLowerCase();
                var humanName = tag.replace("-", " ");
  
                if (babelHelpers.typeof(window.HaxStore.instance.elementList[tag]) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && window.HaxStore.instance.elementList[tag].gizmo !== false) {
                  humanName = window.HaxStore.instance.elementList[tag].gizmo.title;
                }
  
                window.HaxStore.instance.haxAppPicker.presentOptions(options, "", "Remove this `".concat(humanName, "`?"), "delete");
              }
  
              break;
  
            case "grid-plate-first":
              this.haxMoveGridPlate("first", this.activeNode, this.activeContainerNode);
              break;
  
            case "grid-plate-up":
              this.haxMoveGridPlate("up", this.activeNode, this.activeContainerNode);
              break;
  
            case "hax-manager-open":
              window.HaxStore.write("activeHaxElement", {}, this);
              window.HaxStore.instance.haxManager.resetManager(parseInt(detail.value));
              window.HaxStore.instance.haxManager.toggleDialog();
              break;
  
            case "grid-plate-down":
              this.haxMoveGridPlate("down", this.activeNode, this.activeContainerNode);
              break;
  
            case "grid-plate-last":
              this.haxMoveGridPlate("last", this.activeNode, this.activeContainerNode);
              break;
  
            case "close-menu":
              this.set("activeNode", null);
              this.set("activeContainerNode", null);
              window.HaxStore.write("activeNode", null, this);
              window.HaxStore.write("activeContainerNode", null, this);
              break;
  
            case "hax-edit-property":
              var haxInputMixer = this.$.haxinputmixer;
              haxInputMixer.label = detail.target.label;
              haxInputMixer.options = detail.target.options;
              haxInputMixer.icon = detail.target.icon;
              haxInputMixer.description = detail.target.description;
              haxInputMixer.required = detail.target.required;
              haxInputMixer.validation = detail.target.validation;
              haxInputMixer.validationType = detail.target.validationType;
              haxInputMixer.inputMethod = detail.target.inputMethod;
              haxInputMixer.value = ""; // see if response should bind to the slot or property
  
              if (babelHelpers.typeof(detail.target.propertyToBind) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && detail.target.propertyToBind != null && detail.target.propertyToBind != false) {
                haxInputMixer.propertyToBind = detail.target.propertyToBind;
  
                if (babelHelpers.typeof(this.activeNode[detail.target.propertyToBind]) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
                  haxInputMixer.value = this.activeNode[detail.target.propertyToBind];
                } // try to get an attribute bind
                else {
                    haxInputMixer.value = this.activeNode.getAttribute(detail.target.propertyToBind);
                  } // @todo need to be able to support slot binding
  
              } // make input mixer show up
  
  
              this._positionContextMenu(haxInputMixer, this.activeContainerNode, -1, -38);
  
              var style = this.$.cecontextmenu.currentStyle || window.getComputedStyle(this.$.cecontextmenu); // force input mixes to match width of the ce context menu currently
  
              haxInputMixer.style.width = style.width.replace("px", "") - 40 + "px";
              break;
            // directional / proportion operations
  
            case "hax-align-left":
              this.activeNode.style.float = null;
              this.activeNode.style.margin = null;
              this.activeNode.style.display = null;
              setTimeout(function () {
                _this9.positionContextMenus(_this9.activeNode, _this9.activeContainerNode);
              }, 200);
              break;
  
            case "hax-align-center":
              this.activeNode.style.float = null;
              this.activeNode.style.margin = "0 auto";
              this.activeNode.style.display = "block";
              setTimeout(function () {
                _this9.positionContextMenus(_this9.activeNode, _this9.activeContainerNode);
              }, 200);
              break;
  
            case "hax-size-change":
              if (this.activeNode) {
                this.activeNode.style.width = detail.value + "%";
                setTimeout(function () {
                  _this9.positionContextMenus(_this9.activeNode, _this9.activeContainerNode);
                }, 200);
              }
  
              break;
            // settings button selected from hax-ce-context bar
            // which means we should skip to the settings page after
            // we set the thing selected as the active element to work
            // on in the manager
  
            case "hax-manager-configure":
              // make sure input mixer is closed
              this._hideContextMenu(this.$.haxinputmixer); // reset the manager
  
  
              window.HaxStore.instance.haxManager.resetManager(); // write activeElement updated so it'll go into the preview
  
              haxElement = window.HaxStore.nodeToHaxElement(window.HaxStore.instance.activeNode);
              window.HaxStore.write("activeHaxElement", haxElement, this); // clean up the manager before opening
  
              window.HaxStore.instance.haxManager.editExistingNode = true;
              window.HaxStore.instance.haxManager.selectStep("configure");
              window.HaxStore.instance.haxManager.toggleDialog(); // accessibility enhancement to keyboard focus configure button
  
              setTimeout(function () {
                window.HaxStore.instance.haxManager.$.preview.$.configurebutton.focus();
              }, 100);
              break;
            // container / layout settings button has been activated
  
            case "hax-manager-configure-container":
              window.HaxStore.write("activeNode", window.HaxStore.instance.activeContainerNode, this); // make sure input mixer is closed
  
              this._hideContextMenu(this.$.haxinputmixer); // reset the manager
  
  
              window.HaxStore.instance.haxManager.resetManager(); // write activeElement updated so it'll go into the preview
  
              haxElement = window.HaxStore.nodeToHaxElement(window.HaxStore.instance.activeNode);
              window.HaxStore.write("activeHaxElement", haxElement, this); // clean up the manager before opening
  
              window.HaxStore.instance.haxManager.editExistingNode = true;
              window.HaxStore.instance.haxManager.selectStep("configure");
              window.HaxStore.instance.haxManager.toggleDialog(); // accessibility enhancement to keyboard focus configure button
  
              setTimeout(function () {
                window.HaxStore.instance.haxManager.$.preview.$.configurebutton.focus();
              }, 100);
              break;
          }
        }
        /**
         * Respond to an input mixer call.
         */
  
      }, {
        key: "_haxInputMixerOperation",
        value: function _haxInputMixerOperation(e) {
          // this is a big deal how simple this part is in the end
          var mixer = e.detail.inputMixer; // if we have a property to bind, set that value from the
          // widget that was dictated by the element itself
  
          if (mixer.propertyToBind != null) {
            this.activeNode[mixer.propertyToBind] = mixer.value;
          } // if we're told instead to do a slot bind, make a span tag
          // with height same as parent and then mix in the innerHTML
          else if (mixer.slotToBind != null) {
              item = document.createElement("span");
              item.style.height = "inherit";
              item.innerHTML = mixer.value; //item.attribute.slot = mixer.slotToBind;
  
              item.slot = mixer.slotToBind;
              this.activeNode.appendChild(item);
            } // hide mixer
  
  
          this._hideContextMenu(this.$.haxinputmixer);
        }
        /**
         * Item has gained focus, change active element to match
         */
  
      }, {
        key: "_focusIn",
        value: function _focusIn(e) {
          var normalizedEvent = (0, _polymerDom.dom)(e);
  
          if (this.__focusLogic(normalizedEvent.localTarget)) {
            e.stopPropagation();
          }
        }
        /**
         * Focus a target and update the data model to reflect this.
         * This helps ensure that keyboard and non click based focusing
         * registers the same as click events
         */
  
      }, {
        key: "__focusLogic",
        value: function __focusLogic(target) {
          var stopProp = false; // only worry about these when we are in edit mode
  
          if (this.editMode && !this.__tabTrap) {
            var containerNode = target;
            var activeNode = null; // ensure this is valid
  
            if (this._haxElementTest(containerNode) && containerNode.parentNode != null) {
              // keep looking til we are juuuust below the container
              // @todo this is where we force a selection on highest level
              // of the document
              while (containerNode.parentNode.tagName != "HAX-BODY") {
                // make sure active is set after closest legit element
                if (activeNode === null && containerNode.tagName !== "LI" && containerNode.tagName !== "B" && containerNode.tagName !== "I" && containerNode.tagName !== "STRONG" && containerNode.tagName !== "EM") {
                  activeNode = containerNode;
                }
  
                containerNode = containerNode.parentNode;
              } // case with simple element
  
  
              if (activeNode === null) {
                activeNode = containerNode;
              } // we only allow disconnected node from container when
              // the container is a grid plate
              else if (!window.HaxStore.instance.isGridPlateElement(containerNode)) {
                  activeNode = containerNode;
                } // won't deal with lists inside of p tags
                else if (["UL", "OL", "LI", "P", "GRID-PLATE"].includes(containerNode.tagName) && ["UL", "OL", "LI"].includes(activeNode.tagName)) {
                    activeNode = containerNode;
                  } // ensure this is a tag we care about / have support for and
              // that it is a new value
  
  
              if (this.activeContainerNode !== containerNode && !containerNode.classList.contains("ignore-activation")) {
                this.hideContextMenus();
                this.activeContainerNode = containerNode;
                window.HaxStore.write("activeContainerNode", containerNode, this);
                stopProp = true;
              } else if (containerNode.classList.contains("ignore-activation")) {
                stopProp = true;
              } // test for active node changing
  
  
              if (this.activeNode !== activeNode && !activeNode.classList.contains("ignore-activation")) {
                this.activeNode = activeNode;
                window.HaxStore.write("activeNode", activeNode, this);
                this.positionContextMenus(activeNode, containerNode);
                stopProp = true;
              }
            }
          } else {
            this.__tabTrap = false;
          }
  
          return stopProp;
        }
        /**
         * Notice the change between states for editing.
         */
  
      }, {
        key: "_editModeChanged",
        value: function _editModeChanged(newValue, oldValue) {
          // fire above that we have changed states so things can react if needed
          if (babelHelpers.typeof(oldValue) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
            this._applyContentEditable(newValue);
  
            this.setAttribute("tabindex", "-1");
  
            if (newValue !== false && babelHelpers.typeof(this.activeNode) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && this.activeNode !== null) {
              this.positionContextMenus(this.activeNode, this.activeContainerNode);
            }
          } // hide menus when state changes
  
  
          if (newValue === false) {
            this.removeAttribute("contenteditable");
            this.hideContextMenus();
          }
        }
        /**
         * Test if this is a HAX element or not
         */
  
      }, {
        key: "_haxResolvePreviousElement",
        value: function _haxResolvePreviousElement(node) {
          node = (0, _polymerDom.dom)(node).previousElementSibling;
  
          while (node != null && babelHelpers.typeof(node.tagName) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && node.tagName.substring(0, 4) === "HAX-") {
            node = (0, _polymerDom.dom)(node).previousElementSibling;
          }
  
          return node;
        }
        /**
         * Test if this is a HAX element or not
         */
  
      }, {
        key: "_haxElementTest",
        value: function _haxElementTest(node) {
          if (babelHelpers.typeof(node.tagName) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && node.tagName.substring(0, 4) !== "HAX-") {
            return true;
          }
  
          return false;
        }
        /**
         * Test if this is an HTML primative
         */
  
      }, {
        key: "_HTMLPrimativeTest",
        value: function _HTMLPrimativeTest(node) {
          if (node != null && babelHelpers.typeof(node.tagName) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && node.tagName.indexOf("-") == -1) {
            return true;
          }
  
          return false;
        }
        /**
         * Walk everything we find and either enable or disable editable state.
         */
  
      }, {
        key: "_applyContentEditable",
        value: function _applyContentEditable(status) {
          var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.$.body;
          var children = (0, _polymerDom.dom)(target).getDistributedNodes(); // fallback for content nodes if not polymer managed nodes above
  
          if (children.length === 0) {
            children = (0, _polymerDom.dom)(target).getEffectiveChildNodes();
          }
  
          for (var i = 0, len = children.length; i < len; i++) {
            // we have to tell the browser that primatives are editable
            if (this._HTMLPrimativeTest(children[i])) {
              if (status) {
                children[i].setAttribute("contenteditable", status);
                children[i].setAttribute("data-editable", status);
  
                if (children[i].querySelectorAll("a").length > 0) {
                  var links = children[i].querySelectorAll("a");
  
                  for (var j = 0, len2 = links.length; j < len2; j++) {
                    links[j].setAttribute("contenteditable", status);
                    links[j].setAttribute("data-editable", status);
                    links[j].addEventListener("click", function (e) {
                      e.preventDefault();
                      e.stopPropagation();
                      e.stopImmediatePropagation();
                    });
                  }
                }
              } else {
                children[i].removeAttribute("data-editable", status);
                children[i].removeAttribute("contenteditable", status);
  
                if (children[i].querySelectorAll("a").length > 0) {
                  var _links = children[i].querySelectorAll("a");
  
                  for (var j = 0, len2 = _links.length; j < len2; j++) {
                    _links[j].removeAttribute("data-editable", status);
  
                    _links[j].removeAttribute("contenteditable", status);
  
                    _links[j].removeEventListener("click", function (e) {
                      e.preventDefault();
                      e.stopPropagation();
                      e.stopImmediatePropagation();
                    });
                  }
                }
              }
            } // this does the real targetting
  
  
            if (this._haxElementTest(children[i])) {
              if (status) {
                children[i].setAttribute("data-editable", status);
                var haxRay = children[i].tagName.replace("-", " ").toLowerCase();
                var l = window.HaxStore.instance.gizmoList.findIndex(function (j) {
                  return j.tag === children[i].tagName.toLowerCase();
                });
  
                if (l !== -1) {
                  haxRay = window.HaxStore.instance.gizmoList[l].title;
                }
  
                children[i].setAttribute("data-hax-ray", haxRay);
              } else {
                children[i].removeAttribute("data-editable");
                children[i].removeAttribute("data-hax-ray");
              }
            }
          }
        }
        /**
         * Container has changed
         */
  
      }, {
        key: "_activeContainerNodeChanged",
        value: function _activeContainerNodeChanged(newValue, oldValue) {
          if (this.editMode && babelHelpers.typeof(newValue) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && newValue != null && newValue.tagName != null) {
            if (window.HaxStore.instance.isTextElement(newValue) || window.HaxStore.instance.isGridPlateElement(newValue)) {
              newValue.setAttribute("contenteditable", true);
              this.setAttribute("contenteditable", true);
            } else {
              newValue.removeAttribute("contenteditable");
              this.removeAttribute("contenteditable");
            }
  
            var tag = newValue.tagName.toLowerCase(); // special case for the grid plate since it brings in dom nodes
            // nested in it and needs to be put into an editMode
  
            if (tag === "grid-plate") {
              newValue.editMode = this.editMode;
  
              this._applyContentEditable(this.editMode, newValue);
            }
          }
        }
        /**
         * React to a new node being set to active.
         */
  
      }, {
        key: "_activeNodeChanged",
        value: function _activeNodeChanged(newValue, oldValue) {
          var _this10 = this;
  
          // clean up the older one
          if (babelHelpers.typeof(oldValue) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && oldValue != null) {
            oldValue.classList.remove("hax-active");
          }
  
          if (this.editMode && babelHelpers.typeof(newValue) !== (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined)) && newValue !== null) {
            var tag = newValue.tagName.toLowerCase(); // remove the menu, establish the new active, then reapply
            // this is nessecary because the context menu gets appended into
            // the document
            // only hide if we change containers
  
            newValue.classList.add("hax-active");
  
            if (window.HaxStore.instance.isTextElement(newValue) || window.HaxStore.instance.isGridPlateElement(newValue)) {
              newValue.setAttribute("contenteditable", true);
              this.setAttribute("contenteditable", true);
            } else {
              newValue.removeAttribute("contenteditable");
              this.removeAttribute("contenteditable");
            }
  
            this.$.textcontextmenu.selectedValue = tag; // position the operations / in context element
  
            setTimeout(function () {
              _this10.positionContextMenus(newValue, window.HaxStore.instance.activeContainerNode);
            }, 100);
  
            if (newValue.style.textAlign == "left") {
              this.$.textcontextmenu.justifyIcon = "editor:format-align-left";
              this.$.textcontextmenu.justifyValue = "text-align-left";
            } else if (newValue.style.float == "left") {
              this.$.cecontextmenu.justifyIcon = "editor:format-align-left";
              this.$.cecontextmenu.justifyValue = "hax-align-left";
            } else if (newValue.style.margin == "0 auto") {
              this.$.cecontextmenu.justifyIcon = "editor:format-align-center";
              this.$.cecontextmenu.justifyValue = "hax-align-center";
            }
          } // just hide menus if we don't have an active item
          else if (newValue === null) {
              this.hideContextMenus();
              this.__oldActiveNode = oldValue;
              this.$.textcontextmenu.justifyIcon = "editor:format-align-left";
              this.$.textcontextmenu.justifyValue = "text-align-left";
            }
        }
        /**
         * walk parents and find the correct position from top of document
         * https://stackoverflow.com/questions/11805955/how-to-get-the-distance-from-the-top-for-an-element
         */
  
      }, {
        key: "_getPosition",
        value: function _getPosition(element) {
          var xPosition = element.offsetLeft - element.scrollLeft + element.clientLeft;
          var yPosition = element.offsetTop - element.scrollTop + element.clientTop;
          return {
            x: xPosition,
            y: yPosition
          };
        }
        /**
         * Handle display and position of the context menu
         */
  
      }, {
        key: "_positionContextMenu",
        value: function _positionContextMenu(menu, target, xoffset, yoffset) {
          var _this11 = this;
  
          // make it account for the offset if it's floated over to one side
          // or inside of something that's over that way
          if (target != null) {
            var pos = this._getPosition(target);
  
            if (xoffset != null) {
              menu.style["left"] = pos.x + xoffset + "px";
            } else {
              menu.style["left"] = pos.x + "px";
            }
  
            if (yoffset != null) {
              menu.style["top"] = pos.y + yoffset + "px";
            } else {
              menu.style["top"] = pos.y + "px";
            }
          }
  
          menu.classList.add("hax-context-visible"); // text we want to operate this way
  
          if (this.__activeHover) {
            menu.classList.add("hax-active-hover");
            menu.style.marginLeft = "";
            this.__typeLock = false;
          }
  
          setTimeout(function () {
            async.microTask.run(_this11._keepContextVisible());
          }, 100);
        }
        /**
         * Simple hide / reset of whatever menu it's handed.
         */
  
      }, {
        key: "_hideContextMenu",
        value: function _hideContextMenu(menu) {
          menu.classList.remove("hax-context-visible", "hax-context-pin-top", "hax-context-pin-bottom");
          menu.style.left = "-100px";
        }
        /**
         * Find the next thing to tab forward to.
         */
  
      }, {
        key: "_tabKeyPressed",
        value: function _tabKeyPressed() {
          var focus = false;
          var node = this.activeContainerNode;
          var activeNodeTagName = this.activeContainerNode.tagName; // try selection / tab block since range can cause issues
  
          try {
            var range = window.HaxStore.getRange().cloneRange();
            var tagTest = range.commonAncestorContainer.tagName;
  
            if (babelHelpers.typeof(tagTest) === (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
              tagTest = range.commonAncestorContainer.parentNode.tagName;
            }
  
            if (["UL", "OL", "LI"].includes(activeNodeTagName) || ["UL", "OL", "LI"].includes(tagTest)) {
              if (this.polyfillSafe) {
                document.execCommand("indent");
                this.__tabTrap = true;
              }
            } else {
              while (!focus) {
                // do nothing
                if ((0, _polymerDom.dom)(node).nextSibling == null) {
                  focus = true;
                } else if ((0, _polymerDom.dom)(node).nextSibling.focus === "function") {
                  (0, _polymerDom.dom)(node).nextSibling.focus();
                  focus = true;
                } else {
                  node = (0, _polymerDom.dom)(node).nextSibling;
                }
              }
            }
          } catch (e) {
            console.log(e);
          }
        }
        /**
         * Move back through things when tab back pressed
         */
  
      }, {
        key: "_tabBackKeyPressed",
        value: function _tabBackKeyPressed() {
          var node = this.activeContainerNode;
          var activeNodeTagName = this.activeContainerNode.tagName; // try selection / tab block since range can cause issues
  
          try {
            var range = window.HaxStore.getRange().cloneRange();
            var tagTest = range.commonAncestorContainer.tagName;
  
            if (babelHelpers.typeof(tagTest) === (typeof undefined === "undefined" ? "undefined" : babelHelpers.typeof(undefined))) {
              tagTest = range.commonAncestorContainer.parentNode.tagName;
            }
  
            if (["UL", "OL", "LI"].includes(activeNodeTagName) || ["UL", "OL", "LI"].includes(tagTest)) {
              if (this.polyfillSafe) {
                document.execCommand("outdent");
                this.__tabTrap = true;
              }
            } else {
              if (node != null) {
                // step back ignoring hax- prefixed elements
                while (node != null && !this._haxElementTest(node)) {
                  node = (0, _polymerDom.dom)(node).previousSibling;
                }
              }
  
              if (node != null) {
                setTimeout(function () {
                  node.focus();
                }, 50);
              }
            }
          } catch (e) {
            console.log(e);
          }
        }
      }], [{
        key: "tag",
        get: function get() {
          return "hax-body";
        }
      }, {
        key: "template",
        get: function get() {
          return (0, _polymerElement.html)(_templateObject_ece2eff0c3a011e99204fd28bf05b7e9());
        }
      }, {
        key: "properties",
        get: function get() {
          return {
            /**
             * State of if we are editing or not.
             */
            editMode: {
              type: Boolean,
              value: false,
              reflectToAttribute: true,
              observer: "_editModeChanged"
            },
  
            /**
             * Access to the global properties object.
             */
            globalPreferences: {
              type: Object,
              value: {},
              observer: "_globalPreferencesUpdated"
            },
  
            /**
             * Bust out the HAX Ray mode
             */
            haxRayMode: {
              type: Boolean,
              value: false,
              reflectToAttribute: true
            },
  
            /**
             * A reference to the active node in the slot.
             */
            activeNode: {
              type: Object,
              value: null,
              notify: true,
              observer: "_activeNodeChanged"
            },
  
            /**
             * A reference to the active node in the slot.
             */
            activeContainerNode: {
              type: Object,
              value: null,
              notify: true,
              observer: "_activeContainerNodeChanged"
            }
          };
        }
      }]);
      return HaxBody;
    }(_polymerElement.PolymerElement);
  
    _exports.HaxBody = HaxBody;
    window.customElements.define(HaxBody.tag, HaxBody);
  });