/**
 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
 * Licensed under the LGPL or a commercial license.
 * For LGPL see License.txt in the project root for license information.
 * For commercial licenses see https://www.tiny.cloud/
 *
 * Version: 5.9.2 (2021-09-08)
 */
(function () {
    'use strict';

    var __assign = function () {
      __assign = Object.assign || function __assign(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
          s = arguments[i];
          for (var p in s)
            if (Object.prototype.hasOwnProperty.call(s, p))
              t[p] = s[p];
        }
        return t;
      };
      return __assign.apply(this, arguments);
    };
    function __rest(s, e) {
      var t = {};
      for (var p in s)
        if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
          t[p] = s[p];
      if (s != null && typeof Object.getOwnPropertySymbols === 'function')
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
          if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
            t[p[i]] = s[p[i]];
        }
      return t;
    }
    function __spreadArray(to, from, pack) {
      if (pack || arguments.length === 2)
        for (var i = 0, l = from.length, ar; i < l; i++) {
          if (ar || !(i in from)) {
            if (!ar)
              ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
          }
        }
      return to.concat(ar || Array.prototype.slice.call(from));
    }

    var typeOf = function (x) {
      var t = typeof x;
      if (x === null) {
        return 'null';
      } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) {
        return 'array';
      } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) {
        return 'string';
      } else {
        return t;
      }
    };
    var isType$1 = function (type) {
      return function (value) {
        return typeOf(value) === type;
      };
    };
    var isSimpleType = function (type) {
      return function (value) {
        return typeof value === type;
      };
    };
    var eq$1 = function (t) {
      return function (a) {
        return t === a;
      };
    };
    var isString = isType$1('string');
    var isObject = isType$1('object');
    var isArray = isType$1('array');
    var isNull = eq$1(null);
    var isBoolean = isSimpleType('boolean');
    var isUndefined = eq$1(undefined);
    var isNullable = function (a) {
      return a === null || a === undefined;
    };
    var isNonNullable = function (a) {
      return !isNullable(a);
    };
    var isFunction = isSimpleType('function');
    var isNumber = isSimpleType('number');

    var noop = function () {
    };
    var compose = function (fa, fb) {
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        return fa(fb.apply(null, args));
      };
    };
    var compose1 = function (fbc, fab) {
      return function (a) {
        return fbc(fab(a));
      };
    };
    var constant$1 = function (value) {
      return function () {
        return value;
      };
    };
    var identity = function (x) {
      return x;
    };
    var tripleEquals = function (a, b) {
      return a === b;
    };
    function curry(fn) {
      var initialArgs = [];
      for (var _i = 1; _i < arguments.length; _i++) {
        initialArgs[_i - 1] = arguments[_i];
      }
      return function () {
        var restArgs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          restArgs[_i] = arguments[_i];
        }
        var all = initialArgs.concat(restArgs);
        return fn.apply(null, all);
      };
    }
    var not = function (f) {
      return function (t) {
        return !f(t);
      };
    };
    var die = function (msg) {
      return function () {
        throw new Error(msg);
      };
    };
    var apply$1 = function (f) {
      return f();
    };
    var never = constant$1(false);
    var always = constant$1(true);

    var none = function () {
      return NONE;
    };
    var NONE = function () {
      var call = function (thunk) {
        return thunk();
      };
      var id = identity;
      var me = {
        fold: function (n, _s) {
          return n();
        },
        isSome: never,
        isNone: always,
        getOr: id,
        getOrThunk: call,
        getOrDie: function (msg) {
          throw new Error(msg || 'error: getOrDie called on none.');
        },
        getOrNull: constant$1(null),
        getOrUndefined: constant$1(undefined),
        or: id,
        orThunk: call,
        map: none,
        each: noop,
        bind: none,
        exists: never,
        forall: always,
        filter: function () {
          return none();
        },
        toArray: function () {
          return [];
        },
        toString: constant$1('none()')
      };
      return me;
    }();
    var some = function (a) {
      var constant_a = constant$1(a);
      var self = function () {
        return me;
      };
      var bind = function (f) {
        return f(a);
      };
      var me = {
        fold: function (n, s) {
          return s(a);
        },
        isSome: always,
        isNone: never,
        getOr: constant_a,
        getOrThunk: constant_a,
        getOrDie: constant_a,
        getOrNull: constant_a,
        getOrUndefined: constant_a,
        or: self,
        orThunk: self,
        map: function (f) {
          return some(f(a));
        },
        each: function (f) {
          f(a);
        },
        bind: bind,
        exists: bind,
        forall: bind,
        filter: function (f) {
          return f(a) ? me : NONE;
        },
        toArray: function () {
          return [a];
        },
        toString: function () {
          return 'some(' + a + ')';
        }
      };
      return me;
    };
    var from = function (value) {
      return value === null || value === undefined ? NONE : some(value);
    };
    var Optional = {
      some: some,
      none: none,
      from: from
    };

    var cached = function (f) {
      var called = false;
      var r;
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (!called) {
          called = true;
          r = f.apply(null, args);
        }
        return r;
      };
    };

    var DeviceType = function (os, browser, userAgent, mediaMatch) {
      var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
      var isiPhone = os.isiOS() && !isiPad;
      var isMobile = os.isiOS() || os.isAndroid();
      var isTouch = isMobile || mediaMatch('(pointer:coarse)');
      var isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)');
      var isPhone = isiPhone || isMobile && !isTablet;
      var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
      var isDesktop = !isPhone && !isTablet && !iOSwebview;
      return {
        isiPad: constant$1(isiPad),
        isiPhone: constant$1(isiPhone),
        isTablet: constant$1(isTablet),
        isPhone: constant$1(isPhone),
        isTouch: constant$1(isTouch),
        isAndroid: os.isAndroid,
        isiOS: os.isiOS,
        isWebView: constant$1(iOSwebview),
        isDesktop: constant$1(isDesktop)
      };
    };

    var nativeSlice = Array.prototype.slice;
    var nativeIndexOf = Array.prototype.indexOf;
    var nativePush = Array.prototype.push;
    var rawIndexOf = function (ts, t) {
      return nativeIndexOf.call(ts, t);
    };
    var contains$1 = function (xs, x) {
      return rawIndexOf(xs, x) > -1;
    };
    var exists = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return true;
        }
      }
      return false;
    };
    var map$2 = function (xs, f) {
      var len = xs.length;
      var r = new Array(len);
      for (var i = 0; i < len; i++) {
        var x = xs[i];
        r[i] = f(x, i);
      }
      return r;
    };
    var each$1 = function (xs, f) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        f(x, i);
      }
    };
    var eachr = function (xs, f) {
      for (var i = xs.length - 1; i >= 0; i--) {
        var x = xs[i];
        f(x, i);
      }
    };
    var filter$2 = function (xs, pred) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          r.push(x);
        }
      }
      return r;
    };
    var foldr = function (xs, f, acc) {
      eachr(xs, function (x, i) {
        acc = f(acc, x, i);
      });
      return acc;
    };
    var foldl = function (xs, f, acc) {
      each$1(xs, function (x, i) {
        acc = f(acc, x, i);
      });
      return acc;
    };
    var findUntil = function (xs, pred, until) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Optional.some(x);
        } else if (until(x, i)) {
          break;
        }
      }
      return Optional.none();
    };
    var find$2 = function (xs, pred) {
      return findUntil(xs, pred, never);
    };
    var findIndex$1 = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; i++) {
        var x = xs[i];
        if (pred(x, i)) {
          return Optional.some(i);
        }
      }
      return Optional.none();
    };
    var flatten = function (xs) {
      var r = [];
      for (var i = 0, len = xs.length; i < len; ++i) {
        if (!isArray(xs[i])) {
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
        }
        nativePush.apply(r, xs[i]);
      }
      return r;
    };
    var bind$3 = function (xs, f) {
      return flatten(map$2(xs, f));
    };
    var forall = function (xs, pred) {
      for (var i = 0, len = xs.length; i < len; ++i) {
        var x = xs[i];
        if (pred(x, i) !== true) {
          return false;
        }
      }
      return true;
    };
    var reverse = function (xs) {
      var r = nativeSlice.call(xs, 0);
      r.reverse();
      return r;
    };
    var difference = function (a1, a2) {
      return filter$2(a1, function (x) {
        return !contains$1(a2, x);
      });
    };
    var pure$2 = function (x) {
      return [x];
    };
    var sort = function (xs, comparator) {
      var copy = nativeSlice.call(xs, 0);
      copy.sort(comparator);
      return copy;
    };
    var get$d = function (xs, i) {
      return i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
    };
    var head = function (xs) {
      return get$d(xs, 0);
    };
    var findMap = function (arr, f) {
      for (var i = 0; i < arr.length; i++) {
        var r = f(arr[i], i);
        if (r.isSome()) {
          return r;
        }
      }
      return Optional.none();
    };

    var firstMatch = function (regexes, s) {
      for (var i = 0; i < regexes.length; i++) {
        var x = regexes[i];
        if (x.test(s)) {
          return x;
        }
      }
      return undefined;
    };
    var find$1 = function (regexes, agent) {
      var r = firstMatch(regexes, agent);
      if (!r) {
        return {
          major: 0,
          minor: 0
        };
      }
      var group = function (i) {
        return Number(agent.replace(r, '$' + i));
      };
      return nu$8(group(1), group(2));
    };
    var detect$4 = function (versionRegexes, agent) {
      var cleanedAgent = String(agent).toLowerCase();
      if (versionRegexes.length === 0) {
        return unknown$3();
      }
      return find$1(versionRegexes, cleanedAgent);
    };
    var unknown$3 = function () {
      return nu$8(0, 0);
    };
    var nu$8 = function (major, minor) {
      return {
        major: major,
        minor: minor
      };
    };
    var Version = {
      nu: nu$8,
      detect: detect$4,
      unknown: unknown$3
    };

    var detectBrowser$1 = function (browsers, userAgentData) {
      return findMap(userAgentData.brands, function (uaBrand) {
        var lcBrand = uaBrand.brand.toLowerCase();
        return find$2(browsers, function (browser) {
          var _a;
          return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase());
        }).map(function (info) {
          return {
            current: info.name,
            version: Version.nu(parseInt(uaBrand.version, 10), 0)
          };
        });
      });
    };

    var detect$3 = function (candidates, userAgent) {
      var agent = String(userAgent).toLowerCase();
      return find$2(candidates, function (candidate) {
        return candidate.search(agent);
      });
    };
    var detectBrowser = function (browsers, userAgent) {
      return detect$3(browsers, userAgent).map(function (browser) {
        var version = Version.detect(browser.versionRegexes, userAgent);
        return {
          current: browser.name,
          version: version
        };
      });
    };
    var detectOs = function (oses, userAgent) {
      return detect$3(oses, userAgent).map(function (os) {
        var version = Version.detect(os.versionRegexes, userAgent);
        return {
          current: os.name,
          version: version
        };
      });
    };

    var checkRange = function (str, substr, start) {
      return substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
    };
    var supplant = function (str, obj) {
      var isStringOrNumber = function (a) {
        var t = typeof a;
        return t === 'string' || t === 'number';
      };
      return str.replace(/\$\{([^{}]*)\}/g, function (fullMatch, key) {
        var value = obj[key];
        return isStringOrNumber(value) ? value.toString() : fullMatch;
      });
    };
    var contains = function (str, substr) {
      return str.indexOf(substr) !== -1;
    };
    var endsWith = function (str, suffix) {
      return checkRange(str, suffix, str.length - suffix.length);
    };
    var blank = function (r) {
      return function (s) {
        return s.replace(r, '');
      };
    };
    var trim = blank(/^\s+|\s+$/g);

    var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
    var checkContains = function (target) {
      return function (uastring) {
        return contains(uastring, target);
      };
    };
    var browsers = [
      {
        name: 'Edge',
        versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
        search: function (uastring) {
          return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit');
        }
      },
      {
        name: 'Chrome',
        brand: 'Chromium',
        versionRegexes: [
          /.*?chrome\/([0-9]+)\.([0-9]+).*/,
          normalVersionRegex
        ],
        search: function (uastring) {
          return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe');
        }
      },
      {
        name: 'IE',
        versionRegexes: [
          /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
          /.*?rv:([0-9]+)\.([0-9]+).*/
        ],
        search: function (uastring) {
          return contains(uastring, 'msie') || contains(uastring, 'trident');
        }
      },
      {
        name: 'Opera',
        versionRegexes: [
          normalVersionRegex,
          /.*?opera\/([0-9]+)\.([0-9]+).*/
        ],
        search: checkContains('opera')
      },
      {
        name: 'Firefox',
        versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
        search: checkContains('firefox')
      },
      {
        name: 'Safari',
        versionRegexes: [
          normalVersionRegex,
          /.*?cpu os ([0-9]+)_([0-9]+).*/
        ],
        search: function (uastring) {
          return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit');
        }
      }
    ];
    var oses = [
      {
        name: 'Windows',
        search: checkContains('win'),
        versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'iOS',
        search: function (uastring) {
          return contains(uastring, 'iphone') || contains(uastring, 'ipad');
        },
        versionRegexes: [
          /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
          /.*cpu os ([0-9]+)_([0-9]+).*/,
          /.*cpu iphone os ([0-9]+)_([0-9]+).*/
        ]
      },
      {
        name: 'Android',
        search: checkContains('android'),
        versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/]
      },
      {
        name: 'OSX',
        search: checkContains('mac os x'),
        versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]
      },
      {
        name: 'Linux',
        search: checkContains('linux'),
        versionRegexes: []
      },
      {
        name: 'Solaris',
        search: checkContains('sunos'),
        versionRegexes: []
      },
      {
        name: 'FreeBSD',
        search: checkContains('freebsd'),
        versionRegexes: []
      },
      {
        name: 'ChromeOS',
        search: checkContains('cros'),
        versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/]
      }
    ];
    var PlatformInfo = {
      browsers: constant$1(browsers),
      oses: constant$1(oses)
    };

    var edge = 'Edge';
    var chrome = 'Chrome';
    var ie = 'IE';
    var opera = 'Opera';
    var firefox = 'Firefox';
    var safari = 'Safari';
    var unknown$2 = function () {
      return nu$7({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$7 = function (info) {
      var current = info.current;
      var version = info.version;
      var isBrowser = function (name) {
        return function () {
          return current === name;
        };
      };
      return {
        current: current,
        version: version,
        isEdge: isBrowser(edge),
        isChrome: isBrowser(chrome),
        isIE: isBrowser(ie),
        isOpera: isBrowser(opera),
        isFirefox: isBrowser(firefox),
        isSafari: isBrowser(safari)
      };
    };
    var Browser = {
      unknown: unknown$2,
      nu: nu$7,
      edge: constant$1(edge),
      chrome: constant$1(chrome),
      ie: constant$1(ie),
      opera: constant$1(opera),
      firefox: constant$1(firefox),
      safari: constant$1(safari)
    };

    var windows = 'Windows';
    var ios = 'iOS';
    var android = 'Android';
    var linux = 'Linux';
    var osx = 'OSX';
    var solaris = 'Solaris';
    var freebsd = 'FreeBSD';
    var chromeos = 'ChromeOS';
    var unknown$1 = function () {
      return nu$6({
        current: undefined,
        version: Version.unknown()
      });
    };
    var nu$6 = function (info) {
      var current = info.current;
      var version = info.version;
      var isOS = function (name) {
        return function () {
          return current === name;
        };
      };
      return {
        current: current,
        version: version,
        isWindows: isOS(windows),
        isiOS: isOS(ios),
        isAndroid: isOS(android),
        isOSX: isOS(osx),
        isLinux: isOS(linux),
        isSolaris: isOS(solaris),
        isFreeBSD: isOS(freebsd),
        isChromeOS: isOS(chromeos)
      };
    };
    var OperatingSystem = {
      unknown: unknown$1,
      nu: nu$6,
      windows: constant$1(windows),
      ios: constant$1(ios),
      android: constant$1(android),
      linux: constant$1(linux),
      osx: constant$1(osx),
      solaris: constant$1(solaris),
      freebsd: constant$1(freebsd),
      chromeos: constant$1(chromeos)
    };

    var detect$2 = function (userAgent, userAgentDataOpt, mediaMatch) {
      var browsers = PlatformInfo.browsers();
      var oses = PlatformInfo.oses();
      var browser = userAgentDataOpt.bind(function (userAgentData) {
        return detectBrowser$1(browsers, userAgentData);
      }).orThunk(function () {
        return detectBrowser(browsers, userAgent);
      }).fold(Browser.unknown, Browser.nu);
      var os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu);
      var deviceType = DeviceType(os, browser, userAgent, mediaMatch);
      return {
        browser: browser,
        os: os,
        deviceType: deviceType
      };
    };
    var PlatformDetection = { detect: detect$2 };

    var mediaMatch = function (query) {
      return window.matchMedia(query).matches;
    };
    var platform$1 = cached(function () {
      return PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch);
    });
    var detect$1 = function () {
      return platform$1();
    };

    var constant = constant$1;
    var touchstart = constant('touchstart');
    var touchmove = constant('touchmove');
    var touchend = constant('touchend');
    var mousedown = constant('mousedown');
    var mousemove = constant('mousemove');
    var mouseup = constant('mouseup');
    var mouseover = constant('mouseover');
    var keydown = constant('keydown');
    var keyup = constant('keyup');
    var input$1 = constant('input');
    var change = constant('change');
    var click = constant('click');
    var transitionend = constant('transitionend');
    var selectstart = constant('selectstart');

    var prefixName = function (name) {
      return constant$1('alloy.' + name);
    };
    var alloy = { tap: prefixName('tap') };
    var focus$4 = prefixName('focus');
    var postBlur = prefixName('blur.post');
    var postPaste = prefixName('paste.post');
    var receive$1 = prefixName('receive');
    var execute$5 = prefixName('execute');
    var focusItem = prefixName('focus.item');
    var tap = alloy.tap;
    var longpress = prefixName('longpress');
    var systemInit = prefixName('system.init');
    var attachedToDom = prefixName('system.attached');
    var detachedFromDom = prefixName('system.detached');
    var focusShifted = prefixName('focusmanager.shifted');
    var highlight$1 = prefixName('highlight');
    var dehighlight$1 = prefixName('dehighlight');

    var emit = function (component, event) {
      dispatchWith(component, component.element, event, {});
    };
    var emitWith = function (component, event, properties) {
      dispatchWith(component, component.element, event, properties);
    };
    var emitExecute = function (component) {
      emit(component, execute$5());
    };
    var dispatch = function (component, target, event) {
      dispatchWith(component, target, event, {});
    };
    var dispatchWith = function (component, target, event, properties) {
      var data = __assign({ target: target }, properties);
      component.getSystem().triggerEvent(event, target, data);
    };
    var dispatchEvent = function (component, target, event, simulatedEvent) {
      component.getSystem().triggerEvent(event, target, simulatedEvent.event);
    };
    var dispatchFocus = function (component, target) {
      component.getSystem().triggerFocus(target, component.element);
    };

    var DOCUMENT = 9;
    var DOCUMENT_FRAGMENT = 11;
    var ELEMENT = 1;
    var TEXT = 3;

    var fromHtml$2 = function (html, scope) {
      var doc = scope || document;
      var div = doc.createElement('div');
      div.innerHTML = html;
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
        console.error('HTML does not have a single root node', html);
        throw new Error('HTML must have a single root node');
      }
      return fromDom(div.childNodes[0]);
    };
    var fromTag = function (tag, scope) {
      var doc = scope || document;
      var node = doc.createElement(tag);
      return fromDom(node);
    };
    var fromText = function (text, scope) {
      var doc = scope || document;
      var node = doc.createTextNode(text);
      return fromDom(node);
    };
    var fromDom = function (node) {
      if (node === null || node === undefined) {
        throw new Error('Node cannot be null or undefined');
      }
      return { dom: node };
    };
    var fromPoint = function (docElm, x, y) {
      return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
    };
    var SugarElement = {
      fromHtml: fromHtml$2,
      fromTag: fromTag,
      fromText: fromText,
      fromDom: fromDom,
      fromPoint: fromPoint
    };

    var is$1 = function (element, selector) {
      var dom = element.dom;
      if (dom.nodeType !== ELEMENT) {
        return false;
      } else {
        var elem = dom;
        if (elem.matches !== undefined) {
          return elem.matches(selector);
        } else if (elem.msMatchesSelector !== undefined) {
          return elem.msMatchesSelector(selector);
        } else if (elem.webkitMatchesSelector !== undefined) {
          return elem.webkitMatchesSelector(selector);
        } else if (elem.mozMatchesSelector !== undefined) {
          return elem.mozMatchesSelector(selector);
        } else {
          throw new Error('Browser lacks native selectors');
        }
      }
    };
    var bypassSelector = function (dom) {
      return dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
    };
    var all$2 = function (selector, scope) {
      var base = scope === undefined ? document : scope.dom;
      return bypassSelector(base) ? [] : map$2(base.querySelectorAll(selector), SugarElement.fromDom);
    };
    var one = function (selector, scope) {
      var base = scope === undefined ? document : scope.dom;
      return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
    };

    var eq = function (e1, e2) {
      return e1.dom === e2.dom;
    };

    typeof window !== 'undefined' ? window : Function('return this;')();

    var name$1 = function (element) {
      var r = element.dom.nodeName;
      return r.toLowerCase();
    };
    var type = function (element) {
      return element.dom.nodeType;
    };
    var isType = function (t) {
      return function (element) {
        return type(element) === t;
      };
    };
    var isElement = isType(ELEMENT);
    var isText = isType(TEXT);
    var isDocument = isType(DOCUMENT);
    var isDocumentFragment = isType(DOCUMENT_FRAGMENT);

    var owner$2 = function (element) {
      return SugarElement.fromDom(element.dom.ownerDocument);
    };
    var documentOrOwner = function (dos) {
      return isDocument(dos) ? dos : owner$2(dos);
    };
    var defaultView = function (element) {
      return SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
    };
    var parent = function (element) {
      return Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
    };
    var parents = function (element, isRoot) {
      var stop = isFunction(isRoot) ? isRoot : never;
      var dom = element.dom;
      var ret = [];
      while (dom.parentNode !== null && dom.parentNode !== undefined) {
        var rawParent = dom.parentNode;
        var p = SugarElement.fromDom(rawParent);
        ret.push(p);
        if (stop(p) === true) {
          break;
        } else {
          dom = rawParent;
        }
      }
      return ret;
    };
    var siblings$2 = function (element) {
      var filterSelf = function (elements) {
        return filter$2(elements, function (x) {
          return !eq(element, x);
        });
      };
      return parent(element).map(children).map(filterSelf).getOr([]);
    };
    var nextSibling = function (element) {
      return Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
    };
    var children = function (element) {
      return map$2(element.dom.childNodes, SugarElement.fromDom);
    };
    var child = function (element, index) {
      var cs = element.dom.childNodes;
      return Optional.from(cs[index]).map(SugarElement.fromDom);
    };
    var firstChild = function (element) {
      return child(element, 0);
    };

    var before$1 = function (marker, element) {
      var parent$1 = parent(marker);
      parent$1.each(function (v) {
        v.dom.insertBefore(element.dom, marker.dom);
      });
    };
    var after$2 = function (marker, element) {
      var sibling = nextSibling(marker);
      sibling.fold(function () {
        var parent$1 = parent(marker);
        parent$1.each(function (v) {
          append$2(v, element);
        });
      }, function (v) {
        before$1(v, element);
      });
    };
    var prepend$1 = function (parent, element) {
      var firstChild$1 = firstChild(parent);
      firstChild$1.fold(function () {
        append$2(parent, element);
      }, function (v) {
        parent.dom.insertBefore(element.dom, v.dom);
      });
    };
    var append$2 = function (parent, element) {
      parent.dom.appendChild(element.dom);
    };
    var appendAt = function (parent, element, index) {
      child(parent, index).fold(function () {
        append$2(parent, element);
      }, function (v) {
        before$1(v, element);
      });
    };

    var append$1 = function (parent, elements) {
      each$1(elements, function (x) {
        append$2(parent, x);
      });
    };

    var empty = function (element) {
      element.dom.textContent = '';
      each$1(children(element), function (rogue) {
        remove$7(rogue);
      });
    };
    var remove$7 = function (element) {
      var dom = element.dom;
      if (dom.parentNode !== null) {
        dom.parentNode.removeChild(dom);
      }
    };

    var isShadowRoot = function (dos) {
      return isDocumentFragment(dos) && isNonNullable(dos.dom.host);
    };
    var supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
    var isSupported$1 = constant$1(supported);
    var getRootNode = supported ? function (e) {
      return SugarElement.fromDom(e.dom.getRootNode());
    } : documentOrOwner;
    var getShadowRoot = function (e) {
      var r = getRootNode(e);
      return isShadowRoot(r) ? Optional.some(r) : Optional.none();
    };
    var getShadowHost = function (e) {
      return SugarElement.fromDom(e.dom.host);
    };
    var getOriginalEventTarget = function (event) {
      if (isSupported$1() && isNonNullable(event.target)) {
        var el = SugarElement.fromDom(event.target);
        if (isElement(el) && isOpenShadowHost(el)) {
          if (event.composed && event.composedPath) {
            var composedPath = event.composedPath();
            if (composedPath) {
              return head(composedPath);
            }
          }
        }
      }
      return Optional.from(event.target);
    };
    var isOpenShadowHost = function (element) {
      return isNonNullable(element.dom.shadowRoot);
    };

    var inBody = function (element) {
      var dom = isText(element) ? element.dom.parentNode : element.dom;
      if (dom === undefined || dom === null || dom.ownerDocument === null) {
        return false;
      }
      var doc = dom.ownerDocument;
      return getShadowRoot(SugarElement.fromDom(dom)).fold(function () {
        return doc.body.contains(dom);
      }, compose1(inBody, getShadowHost));
    };
    var body = function () {
      return getBody(SugarElement.fromDom(document));
    };
    var getBody = function (doc) {
      var b = doc.dom.body;
      if (b === null || b === undefined) {
        throw new Error('Body is not available yet');
      }
      return SugarElement.fromDom(b);
    };

    var fireDetaching = function (component) {
      emit(component, detachedFromDom());
      var children = component.components();
      each$1(children, fireDetaching);
    };
    var fireAttaching = function (component) {
      var children = component.components();
      each$1(children, fireAttaching);
      emit(component, attachedToDom());
    };
    var attach$1 = function (parent, child) {
      append$2(parent.element, child.element);
    };
    var detachChildren = function (component) {
      each$1(component.components(), function (childComp) {
        return remove$7(childComp.element);
      });
      empty(component.element);
      component.syncComponents();
    };
    var replaceChildren = function (component, newChildren) {
      var subs = component.components();
      detachChildren(component);
      var deleted = difference(subs, newChildren);
      each$1(deleted, function (comp) {
        fireDetaching(comp);
        component.getSystem().removeFromWorld(comp);
      });
      each$1(newChildren, function (childComp) {
        if (!childComp.getSystem().isConnected()) {
          component.getSystem().addToWorld(childComp);
          attach$1(component, childComp);
          if (inBody(component.element)) {
            fireAttaching(childComp);
          }
        } else {
          attach$1(component, childComp);
        }
        component.syncComponents();
      });
    };

    var attach = function (parent, child) {
      attachWith(parent, child, append$2);
    };
    var attachWith = function (parent, child, insertion) {
      parent.getSystem().addToWorld(child);
      insertion(parent.element, child.element);
      if (inBody(parent.element)) {
        fireAttaching(child);
      }
      parent.syncComponents();
    };
    var doDetach = function (component) {
      fireDetaching(component);
      remove$7(component.element);
      component.getSystem().removeFromWorld(component);
    };
    var detach = function (component) {
      var parent$1 = parent(component.element).bind(function (p) {
        return component.getSystem().getByDom(p).toOptional();
      });
      doDetach(component);
      parent$1.each(function (p) {
        p.syncComponents();
      });
    };
    var attachSystemAfter = function (element, guiSystem) {
      attachSystemWith(element, guiSystem, after$2);
    };
    var attachSystemWith = function (element, guiSystem, inserter) {
      inserter(element, guiSystem.element);
      var children$1 = children(guiSystem.element);
      each$1(children$1, function (child) {
        guiSystem.getByDom(child).each(fireAttaching);
      });
    };
    var detachSystem = function (guiSystem) {
      var children$1 = children(guiSystem.element);
      each$1(children$1, function (child) {
        guiSystem.getByDom(child).each(fireDetaching);
      });
      remove$7(guiSystem.element);
    };

    var keys = Object.keys;
    var hasOwnProperty = Object.hasOwnProperty;
    var each = function (obj, f) {
      var props = keys(obj);
      for (var k = 0, len = props.length; k < len; k++) {
        var i = props[k];
        var x = obj[i];
        f(x, i);
      }
    };
    var map$1 = function (obj, f) {
      return tupleMap(obj, function (x, i) {
        return {
          k: i,
          v: f(x, i)
        };
      });
    };
    var tupleMap = function (obj, f) {
      var r = {};
      each(obj, function (x, i) {
        var tuple = f(x, i);
        r[tuple.k] = tuple.v;
      });
      return r;
    };
    var objAcc = function (r) {
      return function (x, i) {
        r[i] = x;
      };
    };
    var internalFilter = function (obj, pred, onTrue, onFalse) {
      var r = {};
      each(obj, function (x, i) {
        (pred(x, i) ? onTrue : onFalse)(x, i);
      });
      return r;
    };
    var filter$1 = function (obj, pred) {
      var t = {};
      internalFilter(obj, pred, objAcc(t), noop);
      return t;
    };
    var mapToArray = function (obj, f) {
      var r = [];
      each(obj, function (value, name) {
        r.push(f(value, name));
      });
      return r;
    };
    var find = function (obj, pred) {
      var props = keys(obj);
      for (var k = 0, len = props.length; k < len; k++) {
        var i = props[k];
        var x = obj[i];
        if (pred(x, i, obj)) {
          return Optional.some(x);
        }
      }
      return Optional.none();
    };
    var values = function (obj) {
      return mapToArray(obj, identity);
    };
    var get$c = function (obj, key) {
      return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
    };
    var has$2 = function (obj, key) {
      return hasOwnProperty.call(obj, key);
    };
    var hasNonNullableKey = function (obj, key) {
      return has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
    };

    var rawSet = function (dom, key, value) {
      if (isString(value) || isBoolean(value) || isNumber(value)) {
        dom.setAttribute(key, value + '');
      } else {
        console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
        throw new Error('Attribute value was not simple');
      }
    };
    var set$8 = function (element, key, value) {
      rawSet(element.dom, key, value);
    };
    var setAll$1 = function (element, attrs) {
      var dom = element.dom;
      each(attrs, function (v, k) {
        rawSet(dom, k, v);
      });
    };
    var get$b = function (element, key) {
      var v = element.dom.getAttribute(key);
      return v === null ? undefined : v;
    };
    var getOpt = function (element, key) {
      return Optional.from(get$b(element, key));
    };
    var has$1 = function (element, key) {
      var dom = element.dom;
      return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
    };
    var remove$6 = function (element, key) {
      element.dom.removeAttribute(key);
    };

    var read$2 = function (element, attr) {
      var value = get$b(element, attr);
      return value === undefined || value === '' ? [] : value.split(' ');
    };
    var add$3 = function (element, attr, id) {
      var old = read$2(element, attr);
      var nu = old.concat([id]);
      set$8(element, attr, nu.join(' '));
      return true;
    };
    var remove$5 = function (element, attr, id) {
      var nu = filter$2(read$2(element, attr), function (v) {
        return v !== id;
      });
      if (nu.length > 0) {
        set$8(element, attr, nu.join(' '));
      } else {
        remove$6(element, attr);
      }
      return false;
    };

    var supports = function (element) {
      return element.dom.classList !== undefined;
    };
    var get$a = function (element) {
      return read$2(element, 'class');
    };
    var add$2 = function (element, clazz) {
      return add$3(element, 'class', clazz);
    };
    var remove$4 = function (element, clazz) {
      return remove$5(element, 'class', clazz);
    };

    var add$1 = function (element, clazz) {
      if (supports(element)) {
        element.dom.classList.add(clazz);
      } else {
        add$2(element, clazz);
      }
    };
    var cleanClass = function (element) {
      var classList = supports(element) ? element.dom.classList : get$a(element);
      if (classList.length === 0) {
        remove$6(element, 'class');
      }
    };
    var remove$3 = function (element, clazz) {
      if (supports(element)) {
        var classList = element.dom.classList;
        classList.remove(clazz);
      } else {
        remove$4(element, clazz);
      }
      cleanClass(element);
    };
    var has = function (element, clazz) {
      return supports(element) && element.dom.classList.contains(clazz);
    };

    var swap = function (element, addCls, removeCls) {
      remove$3(element, removeCls);
      add$1(element, addCls);
    };
    var toAlpha = function (component, swapConfig, _swapState) {
      swap(component.element, swapConfig.alpha, swapConfig.omega);
    };
    var toOmega = function (component, swapConfig, _swapState) {
      swap(component.element, swapConfig.omega, swapConfig.alpha);
    };
    var clear$1 = function (component, swapConfig, _swapState) {
      remove$3(component.element, swapConfig.alpha);
      remove$3(component.element, swapConfig.omega);
    };
    var isAlpha = function (component, swapConfig, _swapState) {
      return has(component.element, swapConfig.alpha);
    };
    var isOmega = function (component, swapConfig, _swapState) {
      return has(component.element, swapConfig.omega);
    };

    var SwapApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        toAlpha: toAlpha,
        toOmega: toOmega,
        isAlpha: isAlpha,
        isOmega: isOmega,
        clear: clear$1
    });

    var value$2 = function (o) {
      var or = function (_opt) {
        return value$2(o);
      };
      var orThunk = function (_f) {
        return value$2(o);
      };
      var map = function (f) {
        return value$2(f(o));
      };
      var mapError = function (_f) {
        return value$2(o);
      };
      var each = function (f) {
        f(o);
      };
      var bind = function (f) {
        return f(o);
      };
      var fold = function (_, onValue) {
        return onValue(o);
      };
      var exists = function (f) {
        return f(o);
      };
      var forall = function (f) {
        return f(o);
      };
      var toOptional = function () {
        return Optional.some(o);
      };
      return {
        isValue: always,
        isError: never,
        getOr: constant$1(o),
        getOrThunk: constant$1(o),
        getOrDie: constant$1(o),
        or: or,
        orThunk: orThunk,
        fold: fold,
        map: map,
        mapError: mapError,
        each: each,
        bind: bind,
        exists: exists,
        forall: forall,
        toOptional: toOptional
      };
    };
    var error = function (message) {
      var getOrThunk = function (f) {
        return f();
      };
      var getOrDie = function () {
        return die(String(message))();
      };
      var or = identity;
      var orThunk = function (f) {
        return f();
      };
      var map = function (_f) {
        return error(message);
      };
      var mapError = function (f) {
        return error(f(message));
      };
      var bind = function (_f) {
        return error(message);
      };
      var fold = function (onError, _) {
        return onError(message);
      };
      return {
        isValue: never,
        isError: always,
        getOr: identity,
        getOrThunk: getOrThunk,
        getOrDie: getOrDie,
        or: or,
        orThunk: orThunk,
        fold: fold,
        map: map,
        mapError: mapError,
        each: noop,
        bind: bind,
        exists: never,
        forall: always,
        toOptional: Optional.none
      };
    };
    var fromOption = function (opt, err) {
      return opt.fold(function () {
        return error(err);
      }, value$2);
    };
    var Result = {
      value: value$2,
      error: error,
      fromOption: fromOption
    };

    var SimpleResultType;
    (function (SimpleResultType) {
      SimpleResultType[SimpleResultType['Error'] = 0] = 'Error';
      SimpleResultType[SimpleResultType['Value'] = 1] = 'Value';
    }(SimpleResultType || (SimpleResultType = {})));
    var fold$1 = function (res, onError, onValue) {
      return res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue);
    };
    var partition$1 = function (results) {
      var values = [];
      var errors = [];
      each$1(results, function (obj) {
        fold$1(obj, function (err) {
          return errors.push(err);
        }, function (val) {
          return values.push(val);
        });
      });
      return {
        values: values,
        errors: errors
      };
    };
    var mapError = function (res, f) {
      if (res.stype === SimpleResultType.Error) {
        return {
          stype: SimpleResultType.Error,
          serror: f(res.serror)
        };
      } else {
        return res;
      }
    };
    var map = function (res, f) {
      if (res.stype === SimpleResultType.Value) {
        return {
          stype: SimpleResultType.Value,
          svalue: f(res.svalue)
        };
      } else {
        return res;
      }
    };
    var bind$2 = function (res, f) {
      if (res.stype === SimpleResultType.Value) {
        return f(res.svalue);
      } else {
        return res;
      }
    };
    var bindError = function (res, f) {
      if (res.stype === SimpleResultType.Error) {
        return f(res.serror);
      } else {
        return res;
      }
    };
    var svalue = function (v) {
      return {
        stype: SimpleResultType.Value,
        svalue: v
      };
    };
    var serror = function (e) {
      return {
        stype: SimpleResultType.Error,
        serror: e
      };
    };
    var toResult$1 = function (res) {
      return fold$1(res, Result.error, Result.value);
    };
    var fromResult = function (res) {
      return res.fold(serror, svalue);
    };
    var SimpleResult = {
      fromResult: fromResult,
      toResult: toResult$1,
      svalue: svalue,
      partition: partition$1,
      serror: serror,
      bind: bind$2,
      bindError: bindError,
      map: map,
      mapError: mapError,
      fold: fold$1
    };

    var field$3 = function (key, newKey, presence, prop) {
      return {
        tag: 'field',
        key: key,
        newKey: newKey,
        presence: presence,
        prop: prop
      };
    };
    var customField$1 = function (newKey, instantiator) {
      return {
        tag: 'custom',
        newKey: newKey,
        instantiator: instantiator
      };
    };
    var fold = function (value, ifField, ifCustom) {
      switch (value.tag) {
      case 'field':
        return ifField(value.key, value.newKey, value.presence, value.prop);
      case 'custom':
        return ifCustom(value.newKey, value.instantiator);
      }
    };

    var shallow$1 = function (old, nu) {
      return nu;
    };
    var deep = function (old, nu) {
      var bothObjects = isObject(old) && isObject(nu);
      return bothObjects ? deepMerge(old, nu) : nu;
    };
    var baseMerge = function (merger) {
      return function () {
        var objects = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          objects[_i] = arguments[_i];
        }
        if (objects.length === 0) {
          throw new Error('Can\'t merge zero objects');
        }
        var ret = {};
        for (var j = 0; j < objects.length; j++) {
          var curObject = objects[j];
          for (var key in curObject) {
            if (has$2(curObject, key)) {
              ret[key] = merger(ret[key], curObject[key]);
            }
          }
        }
        return ret;
      };
    };
    var deepMerge = baseMerge(deep);
    var merge$1 = baseMerge(shallow$1);

    var required$2 = function () {
      return {
        tag: 'required',
        process: {}
      };
    };
    var defaultedThunk = function (fallbackThunk) {
      return {
        tag: 'defaultedThunk',
        process: fallbackThunk
      };
    };
    var defaulted$1 = function (fallback) {
      return defaultedThunk(constant$1(fallback));
    };
    var asOption = function () {
      return {
        tag: 'option',
        process: {}
      };
    };
    var mergeWithThunk = function (baseThunk) {
      return {
        tag: 'mergeWithThunk',
        process: baseThunk
      };
    };
    var mergeWith = function (base) {
      return mergeWithThunk(constant$1(base));
    };

    var mergeValues$1 = function (values, base) {
      return values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge$1.apply(undefined, values))) : SimpleResult.svalue(base);
    };
    var mergeErrors$1 = function (errors) {
      return compose(SimpleResult.serror, flatten)(errors);
    };
    var consolidateObj = function (objects, base) {
      var partition = SimpleResult.partition(objects);
      return partition.errors.length > 0 ? mergeErrors$1(partition.errors) : mergeValues$1(partition.values, base);
    };
    var consolidateArr = function (objects) {
      var partitions = SimpleResult.partition(objects);
      return partitions.errors.length > 0 ? mergeErrors$1(partitions.errors) : SimpleResult.svalue(partitions.values);
    };
    var ResultCombine = {
      consolidateObj: consolidateObj,
      consolidateArr: consolidateArr
    };

    var formatObj = function (input) {
      return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2);
    };
    var formatErrors = function (errors) {
      var es = errors.length > 10 ? errors.slice(0, 10).concat([{
          path: [],
          getErrorInfo: constant$1('... (only showing first ten failures)')
        }]) : errors;
      return map$2(es, function (e) {
        return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo();
      });
    };

    var nu$5 = function (path, getErrorInfo) {
      return SimpleResult.serror([{
          path: path,
          getErrorInfo: getErrorInfo
        }]);
    };
    var missingRequired = function (path, key, obj) {
      return nu$5(path, function () {
        return 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj);
      });
    };
    var missingKey = function (path, key) {
      return nu$5(path, function () {
        return 'Choice schema did not contain choice key: "' + key + '"';
      });
    };
    var missingBranch = function (path, branches, branch) {
      return nu$5(path, function () {
        return 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches);
      });
    };
    var unsupportedFields = function (path, unsupported) {
      return nu$5(path, function () {
        return 'There are unsupported fields: [' + unsupported.join(', ') + '] specified';
      });
    };
    var custom = function (path, err) {
      return nu$5(path, constant$1(err));
    };

    var value$1 = function (validator) {
      var extract = function (path, val) {
        return SimpleResult.bindError(validator(val), function (err) {
          return custom(path, err);
        });
      };
      var toString = constant$1('val');
      return {
        extract: extract,
        toString: toString
      };
    };
    var anyValue$1 = value$1(SimpleResult.svalue);

    var requiredAccess = function (path, obj, key, bundle) {
      return get$c(obj, key).fold(function () {
        return missingRequired(path, key, obj);
      }, bundle);
    };
    var fallbackAccess = function (obj, key, fallback, bundle) {
      var v = get$c(obj, key).getOrThunk(function () {
        return fallback(obj);
      });
      return bundle(v);
    };
    var optionAccess = function (obj, key, bundle) {
      return bundle(get$c(obj, key));
    };
    var optionDefaultedAccess = function (obj, key, fallback, bundle) {
      var opt = get$c(obj, key).map(function (val) {
        return val === true ? fallback(obj) : val;
      });
      return bundle(opt);
    };
    var extractField = function (field, path, obj, key, prop) {
      var bundle = function (av) {
        return prop.extract(path.concat([key]), av);
      };
      var bundleAsOption = function (optValue) {
        return optValue.fold(function () {
          return SimpleResult.svalue(Optional.none());
        }, function (ov) {
          var result = prop.extract(path.concat([key]), ov);
          return SimpleResult.map(result, Optional.some);
        });
      };
      switch (field.tag) {
      case 'required':
        return requiredAccess(path, obj, key, bundle);
      case 'defaultedThunk':
        return fallbackAccess(obj, key, field.process, bundle);
      case 'option':
        return optionAccess(obj, key, bundleAsOption);
      case 'defaultedOptionThunk':
        return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
      case 'mergeWithThunk': {
          return fallbackAccess(obj, key, constant$1({}), function (v) {
            var result = deepMerge(field.process(obj), v);
            return bundle(result);
          });
        }
      }
    };
    var extractFields = function (path, obj, fields) {
      var success = {};
      var errors = [];
      for (var _i = 0, fields_1 = fields; _i < fields_1.length; _i++) {
        var field = fields_1[_i];
        fold(field, function (key, newKey, presence, prop) {
          var result = extractField(presence, path, obj, key, prop);
          SimpleResult.fold(result, function (err) {
            errors.push.apply(errors, err);
          }, function (res) {
            success[newKey] = res;
          });
        }, function (newKey, instantiator) {
          success[newKey] = instantiator(obj);
        });
      }
      return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success);
    };
    var getSetKeys = function (obj) {
      return keys(filter$1(obj, isNonNullable));
    };
    var objOfOnly = function (fields) {
      var delegate = objOf(fields);
      var fieldNames = foldr(fields, function (acc, value) {
        return fold(value, function (key) {
          var _a;
          return deepMerge(acc, (_a = {}, _a[key] = true, _a));
        }, constant$1(acc));
      }, {});
      var extract = function (path, o) {
        var keys = isBoolean(o) ? [] : getSetKeys(o);
        var extra = filter$2(keys, function (k) {
          return !hasNonNullableKey(fieldNames, k);
        });
        return extra.length === 0 ? delegate.extract(path, o) : unsupportedFields(path, extra);
      };
      return {
        extract: extract,
        toString: delegate.toString
      };
    };
    var objOf = function (values) {
      var extract = function (path, o) {
        return extractFields(path, o, values);
      };
      var toString = function () {
        var fieldStrings = map$2(values, function (value) {
          return fold(value, function (key, _okey, _presence, prop) {
            return key + ' -> ' + prop.toString();
          }, function (newKey, _instantiator) {
            return 'state(' + newKey + ')';
          });
        });
        return 'obj{\n' + fieldStrings.join('\n') + '}';
      };
      return {
        extract: extract,
        toString: toString
      };
    };
    var arrOf = function (prop) {
      var extract = function (path, array) {
        var results = map$2(array, function (a, i) {
          return prop.extract(path.concat(['[' + i + ']']), a);
        });
        return ResultCombine.consolidateArr(results);
      };
      var toString = function () {
        return 'array(' + prop.toString() + ')';
      };
      return {
        extract: extract,
        toString: toString
      };
    };
    var setOf$1 = function (validator, prop) {
      var validateKeys = function (path, keys) {
        return arrOf(value$1(validator)).extract(path, keys);
      };
      var extract = function (path, o) {
        var keys$1 = keys(o);
        var validatedKeys = validateKeys(path, keys$1);
        return SimpleResult.bind(validatedKeys, function (validKeys) {
          var schema = map$2(validKeys, function (vk) {
            return field$3(vk, vk, required$2(), prop);
          });
          return objOf(schema).extract(path, o);
        });
      };
      var toString = function () {
        return 'setOf(' + prop.toString() + ')';
      };
      return {
        extract: extract,
        toString: toString
      };
    };

    var anyValue = constant$1(anyValue$1);
    var typedValue = function (validator, expectedType) {
      return value$1(function (a) {
        var actualType = typeof a;
        return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror('Expected type: ' + expectedType + ' but got: ' + actualType);
      });
    };
    var functionProcessor = typedValue(isFunction, 'function');

    var chooseFrom = function (path, input, branches, ch) {
      var fields = get$c(branches, ch);
      return fields.fold(function () {
        return missingBranch(path, branches, ch);
      }, function (vp) {
        return vp.extract(path.concat(['branch: ' + ch]), input);
      });
    };
    var choose$2 = function (key, branches) {
      var extract = function (path, input) {
        var choice = get$c(input, key);
        return choice.fold(function () {
          return missingKey(path, key);
        }, function (chosen) {
          return chooseFrom(path, input, branches, chosen);
        });
      };
      var toString = function () {
        return 'chooseOn(' + key + '). Possible values: ' + keys(branches);
      };
      return {
        extract: extract,
        toString: toString
      };
    };

    var valueOf = function (validator) {
      return value$1(function (v) {
        return validator(v).fold(SimpleResult.serror, SimpleResult.svalue);
      });
    };
    var setOf = function (validator, prop) {
      return setOf$1(function (v) {
        return SimpleResult.fromResult(validator(v));
      }, prop);
    };
    var extractValue = function (label, prop, obj) {
      var res = prop.extract([label], obj);
      return SimpleResult.mapError(res, function (errs) {
        return {
          input: obj,
          errors: errs
        };
      });
    };
    var asRaw = function (label, prop, obj) {
      return SimpleResult.toResult(extractValue(label, prop, obj));
    };
    var getOrDie = function (extraction) {
      return extraction.fold(function (errInfo) {
        throw new Error(formatError(errInfo));
      }, identity);
    };
    var asRawOrDie$1 = function (label, prop, obj) {
      return getOrDie(asRaw(label, prop, obj));
    };
    var formatError = function (errInfo) {
      return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input);
    };
    var choose$1 = function (key, branches) {
      return choose$2(key, map$1(branches, objOf));
    };

    var field$2 = field$3;
    var customField = customField$1;
    var required$1 = function (key) {
      return field$2(key, key, required$2(), anyValue());
    };
    var requiredOf = function (key, schema) {
      return field$2(key, key, required$2(), schema);
    };
    var requiredFunction = function (key) {
      return requiredOf(key, functionProcessor);
    };
    var forbid = function (key, message) {
      return field$2(key, key, asOption(), value$1(function (_v) {
        return SimpleResult.serror('The field: ' + key + ' is forbidden. ' + message);
      }));
    };
    var requiredObjOf = function (key, objSchema) {
      return field$2(key, key, required$2(), objOf(objSchema));
    };
    var option = function (key) {
      return field$2(key, key, asOption(), anyValue());
    };
    var optionOf = function (key, schema) {
      return field$2(key, key, asOption(), schema);
    };
    var optionObjOf = function (key, objSchema) {
      return optionOf(key, objOf(objSchema));
    };
    var optionObjOfOnly = function (key, objSchema) {
      return optionOf(key, objOfOnly(objSchema));
    };
    var defaulted = function (key, fallback) {
      return field$2(key, key, defaulted$1(fallback), anyValue());
    };
    var defaultedOf = function (key, fallback, schema) {
      return field$2(key, key, defaulted$1(fallback), schema);
    };
    var defaultedFunction = function (key, fallback) {
      return defaultedOf(key, fallback, functionProcessor);
    };
    var defaultedObjOf = function (key, fallback, objSchema) {
      return defaultedOf(key, fallback, objOf(objSchema));
    };

    var SwapSchema = [
      required$1('alpha'),
      required$1('omega')
    ];

    var generate$5 = function (cases) {
      if (!isArray(cases)) {
        throw new Error('cases must be an array');
      }
      if (cases.length === 0) {
        throw new Error('there must be at least one case');
      }
      var constructors = [];
      var adt = {};
      each$1(cases, function (acase, count) {
        var keys$1 = keys(acase);
        if (keys$1.length !== 1) {
          throw new Error('one and only one name per case');
        }
        var key = keys$1[0];
        var value = acase[key];
        if (adt[key] !== undefined) {
          throw new Error('duplicate key detected:' + key);
        } else if (key === 'cata') {
          throw new Error('cannot have a case named cata (sorry)');
        } else if (!isArray(value)) {
          throw new Error('case arguments must be an array');
        }
        constructors.push(key);
        adt[key] = function () {
          var args = [];
          for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
          }
          var argLength = args.length;
          if (argLength !== value.length) {
            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
          }
          var match = function (branches) {
            var branchKeys = keys(branches);
            if (constructors.length !== branchKeys.length) {
              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
            }
            var allReqd = forall(constructors, function (reqKey) {
              return contains$1(branchKeys, reqKey);
            });
            if (!allReqd) {
              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
            }
            return branches[key].apply(null, args);
          };
          return {
            fold: function () {
              var foldArgs = [];
              for (var _i = 0; _i < arguments.length; _i++) {
                foldArgs[_i] = arguments[_i];
              }
              if (foldArgs.length !== cases.length) {
                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
              }
              var target = foldArgs[count];
              return target.apply(null, args);
            },
            match: match,
            log: function (label) {
              console.log(label, {
                constructors: constructors,
                constructor: key,
                params: args
              });
            }
          };
        };
      });
      return adt;
    };
    var Adt = { generate: generate$5 };

    Adt.generate([
      {
        bothErrors: [
          'error1',
          'error2'
        ]
      },
      {
        firstError: [
          'error1',
          'value2'
        ]
      },
      {
        secondError: [
          'value1',
          'error2'
        ]
      },
      {
        bothValues: [
          'value1',
          'value2'
        ]
      }
    ]);
    var partition = function (results) {
      var errors = [];
      var values = [];
      each$1(results, function (result) {
        result.fold(function (err) {
          errors.push(err);
        }, function (value) {
          values.push(value);
        });
      });
      return {
        errors: errors,
        values: values
      };
    };

    var exclude$1 = function (obj, fields) {
      var r = {};
      each(obj, function (v, k) {
        if (!contains$1(fields, k)) {
          r[k] = v;
        }
      });
      return r;
    };

    var wrap$1 = function (key, value) {
      var _a;
      return _a = {}, _a[key] = value, _a;
    };
    var wrapAll$1 = function (keyvalues) {
      var r = {};
      each$1(keyvalues, function (kv) {
        r[kv.key] = kv.value;
      });
      return r;
    };

    var exclude = function (obj, fields) {
      return exclude$1(obj, fields);
    };
    var wrap = function (key, value) {
      return wrap$1(key, value);
    };
    var wrapAll = function (keyvalues) {
      return wrapAll$1(keyvalues);
    };
    var mergeValues = function (values, base) {
      return values.length === 0 ? Result.value(base) : Result.value(deepMerge(base, merge$1.apply(undefined, values)));
    };
    var mergeErrors = function (errors) {
      return Result.error(flatten(errors));
    };
    var consolidate = function (objs, base) {
      var partitions = partition(objs);
      return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : mergeValues(partitions.values, base);
    };

    var is = function (lhs, rhs, comparator) {
      if (comparator === void 0) {
        comparator = tripleEquals;
      }
      return lhs.exists(function (left) {
        return comparator(left, rhs);
      });
    };
    var cat = function (arr) {
      var r = [];
      var push = function (x) {
        r.push(x);
      };
      for (var i = 0; i < arr.length; i++) {
        arr[i].each(push);
      }
      return r;
    };
    var sequence = function (arr) {
      var r = [];
      for (var i = 0; i < arr.length; i++) {
        var x = arr[i];
        if (x.isSome()) {
          r.push(x.getOrDie());
        } else {
          return Optional.none();
        }
      }
      return Optional.some(r);
    };
    var lift2 = function (oa, ob, f) {
      return oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
    };
    var someIf = function (b, a) {
      return b ? Optional.some(a) : Optional.none();
    };

    var ensureIsRoot = function (isRoot) {
      return isFunction(isRoot) ? isRoot : never;
    };
    var ancestor$2 = function (scope, transform, isRoot) {
      var element = scope.dom;
      var stop = ensureIsRoot(isRoot);
      while (element.parentNode) {
        element = element.parentNode;
        var el = SugarElement.fromDom(element);
        var transformed = transform(el);
        if (transformed.isSome()) {
          return transformed;
        } else if (stop(el)) {
          break;
        }
      }
      return Optional.none();
    };
    var closest$3 = function (scope, transform, isRoot) {
      var current = transform(scope);
      var stop = ensureIsRoot(isRoot);
      return current.orThunk(function () {
        return stop(scope) ? Optional.none() : ancestor$2(scope, transform, stop);
      });
    };

    var isSource = function (component, simulatedEvent) {
      return eq(component.element, simulatedEvent.event.target);
    };

    var defaultEventHandler = {
      can: always,
      abort: never,
      run: noop
    };
    var nu$4 = function (parts) {
      if (!hasNonNullableKey(parts, 'can') && !hasNonNullableKey(parts, 'abort') && !hasNonNullableKey(parts, 'run')) {
        throw new Error('EventHandler defined by: ' + JSON.stringify(parts, null, 2) + ' does not have can, abort, or run!');
      }
      return __assign(__assign({}, defaultEventHandler), parts);
    };
    var all$1 = function (handlers, f) {
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        return foldl(handlers, function (acc, handler) {
          return acc && f(handler).apply(undefined, args);
        }, true);
      };
    };
    var any = function (handlers, f) {
      return function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        return foldl(handlers, function (acc, handler) {
          return acc || f(handler).apply(undefined, args);
        }, false);
      };
    };
    var read$1 = function (handler) {
      return isFunction(handler) ? {
        can: always,
        abort: never,
        run: handler
      } : handler;
    };
    var fuse$1 = function (handlers) {
      var can = all$1(handlers, function (handler) {
        return handler.can;
      });
      var abort = any(handlers, function (handler) {
        return handler.abort;
      });
      var run = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        each$1(handlers, function (handler) {
          handler.run.apply(undefined, args);
        });
      };
      return {
        can: can,
        abort: abort,
        run: run
      };
    };

    var derive$3 = function (configs) {
      return wrapAll(configs);
    };
    var abort = function (name, predicate) {
      return {
        key: name,
        value: nu$4({ abort: predicate })
      };
    };
    var can = function (name, predicate) {
      return {
        key: name,
        value: nu$4({ can: predicate })
      };
    };
    var run = function (name, handler) {
      return {
        key: name,
        value: nu$4({ run: handler })
      };
    };
    var runActionExtra = function (name, action, extra) {
      return {
        key: name,
        value: nu$4({
          run: function (component, simulatedEvent) {
            action.apply(undefined, [
              component,
              simulatedEvent
            ].concat(extra));
          }
        })
      };
    };
    var runOnName = function (name) {
      return function (handler) {
        return run(name, handler);
      };
    };
    var runOnSourceName = function (name) {
      return function (handler) {
        return {
          key: name,
          value: nu$4({
            run: function (component, simulatedEvent) {
              if (isSource(component, simulatedEvent)) {
                handler(component, simulatedEvent);
              }
            }
          })
        };
      };
    };
    var redirectToUid = function (name, uid) {
      return run(name, function (component, simulatedEvent) {
        component.getSystem().getByUid(uid).each(function (redirectee) {
          dispatchEvent(redirectee, redirectee.element, name, simulatedEvent);
        });
      });
    };
    var redirectToPart = function (name, detail, partName) {
      var uid = detail.partUids[partName];
      return redirectToUid(name, uid);
    };
    var cutter = function (name) {
      return run(name, function (component, simulatedEvent) {
        simulatedEvent.cut();
      });
    };
    var stopper = function (name) {
      return run(name, function (component, simulatedEvent) {
        simulatedEvent.stop();
      });
    };
    var runOnSource = function (name, f) {
      return runOnSourceName(name)(f);
    };
    var runOnAttached = runOnSourceName(attachedToDom());
    var runOnDetached = runOnSourceName(detachedFromDom());
    var runOnInit = runOnSourceName(systemInit());
    var runOnExecute = runOnName(execute$5());

    var markAsBehaviourApi = function (f, apiName, apiFunction) {
      var delegate = apiFunction.toString();
      var endIndex = delegate.indexOf(')') + 1;
      var openBracketIndex = delegate.indexOf('(');
      var parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
      f.toFunctionAnnotation = function () {
        return {
          name: apiName,
          parameters: cleanParameters(parameters.slice(0, 1).concat(parameters.slice(3)))
        };
      };
      return f;
    };
    var cleanParameters = function (parameters) {
      return map$2(parameters, function (p) {
        return endsWith(p, '/*') ? p.substring(0, p.length - '/*'.length) : p;
      });
    };
    var markAsExtraApi = function (f, extraName) {
      var delegate = f.toString();
      var endIndex = delegate.indexOf(')') + 1;
      var openBracketIndex = delegate.indexOf('(');
      var parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
      f.toFunctionAnnotation = function () {
        return {
          name: extraName,
          parameters: cleanParameters(parameters)
        };
      };
      return f;
    };
    var markAsSketchApi = function (f, apiFunction) {
      var delegate = apiFunction.toString();
      var endIndex = delegate.indexOf(')') + 1;
      var openBracketIndex = delegate.indexOf('(');
      var parameters = delegate.substring(openBracketIndex + 1, endIndex - 1).split(/,\s*/);
      f.toFunctionAnnotation = function () {
        return {
          name: 'OVERRIDE',
          parameters: cleanParameters(parameters.slice(1))
        };
      };
      return f;
    };

    var nu$3 = function (s) {
      return {
        classes: isUndefined(s.classes) ? [] : s.classes,
        attributes: isUndefined(s.attributes) ? {} : s.attributes,
        styles: isUndefined(s.styles) ? {} : s.styles
      };
    };
    var merge = function (defnA, mod) {
      return __assign(__assign({}, defnA), {
        attributes: __assign(__assign({}, defnA.attributes), mod.attributes),
        styles: __assign(__assign({}, defnA.styles), mod.styles),
        classes: defnA.classes.concat(mod.classes)
      });
    };

    var executeEvent = function (bConfig, bState, executor) {
      return runOnExecute(function (component) {
        executor(component, bConfig, bState);
      });
    };
    var loadEvent = function (bConfig, bState, f) {
      return runOnInit(function (component, _simulatedEvent) {
        f(component, bConfig, bState);
      });
    };
    var create$6 = function (schema, name, active, apis, extra, state) {
      var configSchema = objOfOnly(schema);
      var schemaSchema = optionObjOf(name, [optionObjOfOnly('config', schema)]);
      return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
    };
    var createModes$1 = function (modes, name, active, apis, extra, state) {
      var configSchema = modes;
      var schemaSchema = optionObjOf(name, [optionOf('config', modes)]);
      return doCreate(configSchema, schemaSchema, name, active, apis, extra, state);
    };
    var wrapApi = function (bName, apiFunction, apiName) {
      var f = function (component) {
        var rest = [];
        for (var _i = 1; _i < arguments.length; _i++) {
          rest[_i - 1] = arguments[_i];
        }
        var args = [component].concat(rest);
        return component.config({ name: constant$1(bName) }).fold(function () {
          throw new Error('We could not find any behaviour configuration for: ' + bName + '. Using API: ' + apiName);
        }, function (info) {
          var rest = Array.prototype.slice.call(args, 1);
          return apiFunction.apply(undefined, [
            component,
            info.config,
            info.state
          ].concat(rest));
        });
      };
      return markAsBehaviourApi(f, apiName, apiFunction);
    };
    var revokeBehaviour = function (name) {
      return {
        key: name,
        value: undefined
      };
    };
    var doCreate = function (configSchema, schemaSchema, name, active, apis, extra, state) {
      var getConfig = function (info) {
        return hasNonNullableKey(info, name) ? info[name]() : Optional.none();
      };
      var wrappedApis = map$1(apis, function (apiF, apiName) {
        return wrapApi(name, apiF, apiName);
      });
      var wrappedExtra = map$1(extra, function (extraF, extraName) {
        return markAsExtraApi(extraF, extraName);
      });
      var me = __assign(__assign(__assign({}, wrappedExtra), wrappedApis), {
        revoke: curry(revokeBehaviour, name),
        config: function (spec) {
          var prepared = asRawOrDie$1(name + '-config', configSchema, spec);
          return {
            key: name,
            value: {
              config: prepared,
              me: me,
              configAsRaw: cached(function () {
                return asRawOrDie$1(name + '-config', configSchema, spec);
              }),
              initialConfig: spec,
              state: state
            }
          };
        },
        schema: constant$1(schemaSchema),
        exhibit: function (info, base) {
          return lift2(getConfig(info), get$c(active, 'exhibit'), function (behaviourInfo, exhibitor) {
            return exhibitor(base, behaviourInfo.config, behaviourInfo.state);
          }).getOrThunk(function () {
            return nu$3({});
          });
        },
        name: constant$1(name),
        handlers: function (info) {
          return getConfig(info).map(function (behaviourInfo) {
            var getEvents = get$c(active, 'events').getOr(function () {
              return {};
            });
            return getEvents(behaviourInfo.config, behaviourInfo.state);
          }).getOr({});
        }
      });
      return me;
    };

    var NoState = {
      init: function () {
        return nu$2({ readState: constant$1('No State required') });
      }
    };
    var nu$2 = function (spec) {
      return spec;
    };

    var derive$2 = function (capabilities) {
      return wrapAll(capabilities);
    };
    var simpleSchema = objOfOnly([
      required$1('fields'),
      required$1('name'),
      defaulted('active', {}),
      defaulted('apis', {}),
      defaulted('state', NoState),
      defaulted('extra', {})
    ]);
    var create$5 = function (data) {
      var value = asRawOrDie$1('Creating behaviour: ' + data.name, simpleSchema, data);
      return create$6(value.fields, value.name, value.active, value.apis, value.extra, value.state);
    };
    var modeSchema = objOfOnly([
      required$1('branchKey'),
      required$1('branches'),
      required$1('name'),
      defaulted('active', {}),
      defaulted('apis', {}),
      defaulted('state', NoState),
      defaulted('extra', {})
    ]);
    var createModes = function (data) {
      var value = asRawOrDie$1('Creating behaviour: ' + data.name, modeSchema, data);
      return createModes$1(choose$1(value.branchKey, value.branches), value.name, value.active, value.apis, value.extra, value.state);
    };
    var revoke = constant$1(undefined);

    var Swapping = create$5({
      fields: SwapSchema,
      name: 'swapping',
      apis: SwapApis
    });

    var Cell = function (initial) {
      var value = initial;
      var get = function () {
        return value;
      };
      var set = function (v) {
        value = v;
      };
      return {
        get: get,
        set: set
      };
    };

    var getDocument = function () {
      return SugarElement.fromDom(document);
    };

    var focus$3 = function (element) {
      return element.dom.focus();
    };
    var blur$1 = function (element) {
      return element.dom.blur();
    };
    var hasFocus = function (element) {
      var root = getRootNode(element).dom;
      return element.dom === root.activeElement;
    };
    var active = function (root) {
      if (root === void 0) {
        root = getDocument();
      }
      return Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
    };
    var search = function (element) {
      return active(getRootNode(element)).filter(function (e) {
        return element.dom.contains(e.dom);
      });
    };

    var global$5 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');

    var global$4 = tinymce.util.Tools.resolve('tinymce.ThemeManager');

    var openLink = function (target) {
      var link = document.createElement('a');
      link.target = '_blank';
      link.href = target.href;
      link.rel = 'noreferrer noopener';
      var nuEvt = document.createEvent('MouseEvents');
      nuEvt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      document.body.appendChild(link);
      link.dispatchEvent(nuEvt);
      document.body.removeChild(link);
    };

    var DefaultStyleFormats = [
      {
        title: 'Headings',
        items: [
          {
            title: 'Heading 1',
            format: 'h1'
          },
          {
            title: 'Heading 2',
            format: 'h2'
          },
          {
            title: 'Heading 3',
            format: 'h3'
          },
          {
            title: 'Heading 4',
            format: 'h4'
          },
          {
            title: 'Heading 5',
            format: 'h5'
          },
          {
            title: 'Heading 6',
            format: 'h6'
          }
        ]
      },
      {
        title: 'Inline',
        items: [
          {
            title: 'Bold',
            icon: 'bold',
            format: 'bold'
          },
          {
            title: 'Italic',
            icon: 'italic',
            format: 'italic'
          },
          {
            title: 'Underline',
            icon: 'underline',
            format: 'underline'
          },
          {
            title: 'Strikethrough',
            icon: 'strikethrough',
            format: 'strikethrough'
          },
          {
            title: 'Superscript',
            icon: 'superscript',
            format: 'superscript'
          },
          {
            title: 'Subscript',
            icon: 'subscript',
            format: 'subscript'
          },
          {
            title: 'Code',
            icon: 'code',
            format: 'code'
          }
        ]
      },
      {
        title: 'Blocks',
        items: [
          {
            title: 'Paragraph',
            format: 'p'
          },
          {
            title: 'Blockquote',
            format: 'blockquote'
          },
          {
            title: 'Div',
            format: 'div'
          },
          {
            title: 'Pre',
            format: 'pre'
          }
        ]
      },
      {
        title: 'Alignment',
        items: [
          {
            title: 'Left',
            icon: 'alignleft',
            format: 'alignleft'
          },
          {
            title: 'Center',
            icon: 'aligncenter',
            format: 'aligncenter'
          },
          {
            title: 'Right',
            icon: 'alignright',
            format: 'alignright'
          },
          {
            title: 'Justify',
            icon: 'alignjustify',
            format: 'alignjustify'
          }
        ]
      }
    ];

    var defaults = [
      'undo',
      'bold',
      'italic',
      'link',
      'image',
      'bullist',
      'styleselect'
    ];
    var isSkinDisabled = function (editor) {
      return editor.getParam('skin') === false;
    };
    var readOnlyOnInit = function (_editor) {
      return false;
    };
    var getToolbar = function (editor) {
      return editor.getParam('toolbar', defaults, 'array');
    };
    var getStyleFormats = function (editor) {
      return editor.getParam('style_formats', DefaultStyleFormats, 'array');
    };
    var getSkinUrl = function (editor) {
      return editor.getParam('skin_url');
    };

    var formatChanged = 'formatChanged';
    var orientationChanged = 'orientationChanged';
    var dropupDismissed = 'dropupDismissed';

    var fromHtml$1 = function (html, scope) {
      var doc = scope || document;
      var div = doc.createElement('div');
      div.innerHTML = html;
      return children(SugarElement.fromDom(div));
    };

    var get$9 = function (element) {
      return element.dom.innerHTML;
    };
    var set$7 = function (element, content) {
      var owner = owner$2(element);
      var docDom = owner.dom;
      var fragment = SugarElement.fromDom(docDom.createDocumentFragment());
      var contentElements = fromHtml$1(content, docDom);
      append$1(fragment, contentElements);
      empty(element);
      append$2(element, fragment);
    };
    var getOuter = function (element) {
      var container = SugarElement.fromTag('div');
      var clone = SugarElement.fromDom(element.dom.cloneNode(true));
      append$2(container, clone);
      return get$9(container);
    };

    var clone = function (original, isDeep) {
      return SugarElement.fromDom(original.dom.cloneNode(isDeep));
    };
    var shallow = function (original) {
      return clone(original, false);
    };

    var getHtml = function (element) {
      if (isShadowRoot(element)) {
        return '#shadow-root';
      } else {
        var clone = shallow(element);
        return getOuter(clone);
      }
    };

    var element = function (elem) {
      return getHtml(elem);
    };

    var chooseChannels = function (channels, message) {
      return message.universal ? channels : filter$2(channels, function (ch) {
        return contains$1(message.channels, ch);
      });
    };
    var events$a = function (receiveConfig) {
      return derive$3([run(receive$1(), function (component, message) {
          var channelMap = receiveConfig.channels;
          var channels = keys(channelMap);
          var receivingData = message;
          var targetChannels = chooseChannels(channels, receivingData);
          each$1(targetChannels, function (ch) {
            var channelInfo = channelMap[ch];
            var channelSchema = channelInfo.schema;
            var data = asRawOrDie$1('channel[' + ch + '] data\nReceiver: ' + element(component.element), channelSchema, receivingData.data);
            channelInfo.onReceive(component, data);
          });
        })]);
    };

    var ActiveReceiving = /*#__PURE__*/Object.freeze({
        __proto__: null,
        events: events$a
    });

    var unknown = 'unknown';
    var EventConfiguration;
    (function (EventConfiguration) {
      EventConfiguration[EventConfiguration['STOP'] = 0] = 'STOP';
      EventConfiguration[EventConfiguration['NORMAL'] = 1] = 'NORMAL';
      EventConfiguration[EventConfiguration['LOGGING'] = 2] = 'LOGGING';
    }(EventConfiguration || (EventConfiguration = {})));
    var eventConfig = Cell({});
    var makeEventLogger = function (eventName, initialTarget) {
      var sequence = [];
      var startTime = new Date().getTime();
      return {
        logEventCut: function (_name, target, purpose) {
          sequence.push({
            outcome: 'cut',
            target: target,
            purpose: purpose
          });
        },
        logEventStopped: function (_name, target, purpose) {
          sequence.push({
            outcome: 'stopped',
            target: target,
            purpose: purpose
          });
        },
        logNoParent: function (_name, target, purpose) {
          sequence.push({
            outcome: 'no-parent',
            target: target,
            purpose: purpose
          });
        },
        logEventNoHandlers: function (_name, target) {
          sequence.push({
            outcome: 'no-handlers-left',
            target: target
          });
        },
        logEventResponse: function (_name, target, purpose) {
          sequence.push({
            outcome: 'response',
            purpose: purpose,
            target: target
          });
        },
        write: function () {
          var finishTime = new Date().getTime();
          if (contains$1([
              'mousemove',
              'mouseover',
              'mouseout',
              systemInit()
            ], eventName)) {
            return;
          }
          console.log(eventName, {
            event: eventName,
            time: finishTime - startTime,
            target: initialTarget.dom,
            sequence: map$2(sequence, function (s) {
              if (!contains$1([
                  'cut',
                  'stopped',
                  'response'
                ], s.outcome)) {
                return s.outcome;
              } else {
                return '{' + s.purpose + '} ' + s.outcome + ' at (' + element(s.target) + ')';
              }
            })
          });
        }
      };
    };
    var processEvent = function (eventName, initialTarget, f) {
      var status = get$c(eventConfig.get(), eventName).orThunk(function () {
        var patterns = keys(eventConfig.get());
        return findMap(patterns, function (p) {
          return eventName.indexOf(p) > -1 ? Optional.some(eventConfig.get()[p]) : Optional.none();
        });
      }).getOr(EventConfiguration.NORMAL);
      switch (status) {
      case EventConfiguration.NORMAL:
        return f(noLogger());
      case EventConfiguration.LOGGING: {
          var logger = makeEventLogger(eventName, initialTarget);
          var output = f(logger);
          logger.write();
          return output;
        }
      case EventConfiguration.STOP:
        return true;
      }
    };
    var path = [
      'alloy/data/Fields',
      'alloy/debugging/Debugging'
    ];
    var getTrace = function () {
      var err = new Error();
      if (err.stack !== undefined) {
        var lines = err.stack.split('\n');
        return find$2(lines, function (line) {
          return line.indexOf('alloy') > 0 && !exists(path, function (p) {
            return line.indexOf(p) > -1;
          });
        }).getOr(unknown);
      } else {
        return unknown;
      }
    };
    var ignoreEvent = {
      logEventCut: noop,
      logEventStopped: noop,
      logNoParent: noop,
      logEventNoHandlers: noop,
      logEventResponse: noop,
      write: noop
    };
    var monitorEvent = function (eventName, initialTarget, f) {
      return processEvent(eventName, initialTarget, f);
    };
    var noLogger = constant$1(ignoreEvent);

    var menuFields = constant$1([
      required$1('menu'),
      required$1('selectedMenu')
    ]);
    var itemFields = constant$1([
      required$1('item'),
      required$1('selectedItem')
    ]);
    constant$1(objOf(itemFields().concat(menuFields())));
    var itemSchema$1 = constant$1(objOf(itemFields()));

    var _initSize = requiredObjOf('initSize', [
      required$1('numColumns'),
      required$1('numRows')
    ]);
    var itemMarkers = function () {
      return requiredOf('markers', itemSchema$1());
    };
    var tieredMenuMarkers = function () {
      return requiredObjOf('markers', [required$1('backgroundMenu')].concat(menuFields()).concat(itemFields()));
    };
    var markers = function (required) {
      return requiredObjOf('markers', map$2(required, required$1));
    };
    var onPresenceHandler = function (label, fieldName, presence) {
      getTrace();
      return field$2(fieldName, fieldName, presence, valueOf(function (f) {
        return Result.value(function () {
          var args = [];
          for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
          }
          return f.apply(undefined, args);
        });
      }));
    };
    var onHandler = function (fieldName) {
      return onPresenceHandler('onHandler', fieldName, defaulted$1(noop));
    };
    var onKeyboardHandler = function (fieldName) {
      return onPresenceHandler('onKeyboardHandler', fieldName, defaulted$1(Optional.none));
    };
    var onStrictHandler = function (fieldName) {
      return onPresenceHandler('onHandler', fieldName, required$2());
    };
    var onStrictKeyboardHandler = function (fieldName) {
      return onPresenceHandler('onKeyboardHandler', fieldName, required$2());
    };
    var output = function (name, value) {
      return customField(name, constant$1(value));
    };
    var snapshot = function (name) {
      return customField(name, identity);
    };
    var initSize = constant$1(_initSize);

    var ReceivingSchema = [requiredOf('channels', setOf(Result.value, objOfOnly([
        onStrictHandler('onReceive'),
        defaulted('schema', anyValue())
      ])))];

    var Receiving = create$5({
      fields: ReceivingSchema,
      name: 'receiving',
      active: ActiveReceiving
    });

    var SetupBehaviourCellState = function (initialState) {
      var init = function () {
        var cell = Cell(initialState);
        var get = function () {
          return cell.get();
        };
        var set = function (newState) {
          return cell.set(newState);
        };
        var clear = function () {
          return cell.set(initialState);
        };
        var readState = function () {
          return cell.get();
        };
        return {
          get: get,
          set: set,
          clear: clear,
          readState: readState
        };
      };
      return { init: init };
    };

    var updateAriaState = function (component, toggleConfig, toggleState) {
      var ariaInfo = toggleConfig.aria;
      ariaInfo.update(component, ariaInfo, toggleState.get());
    };
    var updateClass = function (component, toggleConfig, toggleState) {
      toggleConfig.toggleClass.each(function (toggleClass) {
        if (toggleState.get()) {
          add$1(component.element, toggleClass);
        } else {
          remove$3(component.element, toggleClass);
        }
      });
    };
    var toggle = function (component, toggleConfig, toggleState) {
      set$6(component, toggleConfig, toggleState, !toggleState.get());
    };
    var on$1 = function (component, toggleConfig, toggleState) {
      toggleState.set(true);
      updateClass(component, toggleConfig, toggleState);
      updateAriaState(component, toggleConfig, toggleState);
    };
    var off = function (component, toggleConfig, toggleState) {
      toggleState.set(false);
      updateClass(component, toggleConfig, toggleState);
      updateAriaState(component, toggleConfig, toggleState);
    };
    var set$6 = function (component, toggleConfig, toggleState, state) {
      var action = state ? on$1 : off;
      action(component, toggleConfig, toggleState);
    };
    var isOn = function (component, toggleConfig, toggleState) {
      return toggleState.get();
    };
    var onLoad$5 = function (component, toggleConfig, toggleState) {
      set$6(component, toggleConfig, toggleState, toggleConfig.selected);
    };

    var ToggleApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        onLoad: onLoad$5,
        toggle: toggle,
        isOn: isOn,
        on: on$1,
        off: off,
        set: set$6
    });

    var exhibit$5 = function () {
      return nu$3({});
    };
    var events$9 = function (toggleConfig, toggleState) {
      var execute = executeEvent(toggleConfig, toggleState, toggle);
      var load = loadEvent(toggleConfig, toggleState, onLoad$5);
      return derive$3(flatten([
        toggleConfig.toggleOnExecute ? [execute] : [],
        [load]
      ]));
    };

    var ActiveToggle = /*#__PURE__*/Object.freeze({
        __proto__: null,
        exhibit: exhibit$5,
        events: events$9
    });

    var updatePressed = function (component, ariaInfo, status) {
      set$8(component.element, 'aria-pressed', status);
      if (ariaInfo.syncWithExpanded) {
        updateExpanded(component, ariaInfo, status);
      }
    };
    var updateSelected = function (component, ariaInfo, status) {
      set$8(component.element, 'aria-selected', status);
    };
    var updateChecked = function (component, ariaInfo, status) {
      set$8(component.element, 'aria-checked', status);
    };
    var updateExpanded = function (component, ariaInfo, status) {
      set$8(component.element, 'aria-expanded', status);
    };

    var ToggleSchema = [
      defaulted('selected', false),
      option('toggleClass'),
      defaulted('toggleOnExecute', true),
      defaultedOf('aria', { mode: 'none' }, choose$1('mode', {
        pressed: [
          defaulted('syncWithExpanded', false),
          output('update', updatePressed)
        ],
        checked: [output('update', updateChecked)],
        expanded: [output('update', updateExpanded)],
        selected: [output('update', updateSelected)],
        none: [output('update', noop)]
      }))
    ];

    var Toggling = create$5({
      fields: ToggleSchema,
      name: 'toggling',
      active: ActiveToggle,
      apis: ToggleApis,
      state: SetupBehaviourCellState(false)
    });

    var format = function (command, update) {
      return Receiving.config({
        channels: wrap(formatChanged, {
          onReceive: function (button, data) {
            if (data.command === command) {
              update(button, data.state);
            }
          }
        })
      });
    };
    var orientation = function (onReceive) {
      return Receiving.config({ channels: wrap(orientationChanged, { onReceive: onReceive }) });
    };
    var receive = function (channel, onReceive) {
      return {
        key: channel,
        value: { onReceive: onReceive }
      };
    };

    var prefix$2 = 'tinymce-mobile';
    var resolve = function (p) {
      return prefix$2 + '-' + p;
    };

    var pointerEvents = function () {
      var onClick = function (component, simulatedEvent) {
        simulatedEvent.stop();
        emitExecute(component);
      };
      return [
        run(click(), onClick),
        run(tap(), onClick),
        cutter(touchstart()),
        cutter(mousedown())
      ];
    };
    var events$8 = function (optAction) {
      var executeHandler = function (action) {
        return runOnExecute(function (component, simulatedEvent) {
          action(component);
          simulatedEvent.stop();
        });
      };
      return derive$3(flatten([
        optAction.map(executeHandler).toArray(),
        pointerEvents()
      ]));
    };

    var focus$2 = function (component, focusConfig) {
      if (!focusConfig.ignore) {
        focus$3(component.element);
        focusConfig.onFocus(component);
      }
    };
    var blur = function (component, focusConfig) {
      if (!focusConfig.ignore) {
        blur$1(component.element);
      }
    };
    var isFocused = function (component) {
      return hasFocus(component.element);
    };

    var FocusApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        focus: focus$2,
        blur: blur,
        isFocused: isFocused
    });

    var exhibit$4 = function (base, focusConfig) {
      var mod = focusConfig.ignore ? {} : { attributes: { tabindex: '-1' } };
      return nu$3(mod);
    };
    var events$7 = function (focusConfig) {
      return derive$3([run(focus$4(), function (component, simulatedEvent) {
          focus$2(component, focusConfig);
          simulatedEvent.stop();
        })].concat(focusConfig.stopMousedown ? [run(mousedown(), function (_, simulatedEvent) {
          simulatedEvent.event.prevent();
        })] : []));
    };

    var ActiveFocus = /*#__PURE__*/Object.freeze({
        __proto__: null,
        exhibit: exhibit$4,
        events: events$7
    });

    var FocusSchema = [
      onHandler('onFocus'),
      defaulted('stopMousedown', false),
      defaulted('ignore', false)
    ];

    var Focusing = create$5({
      fields: FocusSchema,
      name: 'focusing',
      active: ActiveFocus,
      apis: FocusApis
    });

    var isSupported = function (dom) {
      return dom.style !== undefined && isFunction(dom.style.getPropertyValue);
    };

    var internalSet = function (dom, property, value) {
      if (!isString(value)) {
        console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
        throw new Error('CSS value must be a string: ' + value);
      }
      if (isSupported(dom)) {
        dom.style.setProperty(property, value);
      }
    };
    var internalRemove = function (dom, property) {
      if (isSupported(dom)) {
        dom.style.removeProperty(property);
      }
    };
    var set$5 = function (element, property, value) {
      var dom = element.dom;
      internalSet(dom, property, value);
    };
    var setAll = function (element, css) {
      var dom = element.dom;
      each(css, function (v, k) {
        internalSet(dom, k, v);
      });
    };
    var get$8 = function (element, property) {
      var dom = element.dom;
      var styles = window.getComputedStyle(dom);
      var r = styles.getPropertyValue(property);
      return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
    };
    var getUnsafeProperty = function (dom, property) {
      return isSupported(dom) ? dom.style.getPropertyValue(property) : '';
    };
    var getRaw = function (element, property) {
      var dom = element.dom;
      var raw = getUnsafeProperty(dom, property);
      return Optional.from(raw).filter(function (r) {
        return r.length > 0;
      });
    };
    var remove$2 = function (element, property) {
      var dom = element.dom;
      internalRemove(dom, property);
      if (is(getOpt(element, 'style').map(trim), '')) {
        remove$6(element, 'style');
      }
    };
    var reflow = function (e) {
      return e.dom.offsetWidth;
    };

    var Dimension = function (name, getOffset) {
      var set = function (element, h) {
        if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
          throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
        }
        var dom = element.dom;
        if (isSupported(dom)) {
          dom.style[name] = h + 'px';
        }
      };
      var get = function (element) {
        var r = getOffset(element);
        if (r <= 0 || r === null) {
          var css = get$8(element, name);
          return parseFloat(css) || 0;
        }
        return r;
      };
      var getOuter = get;
      var aggregate = function (element, properties) {
        return foldl(properties, function (acc, property) {
          var val = get$8(element, property);
          var value = val === undefined ? 0 : parseInt(val, 10);
          return isNaN(value) ? acc : acc + value;
        }, 0);
      };
      var max = function (element, value, properties) {
        var cumulativeInclusions = aggregate(element, properties);
        var absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
        return absoluteMax;
      };
      return {
        set: set,
        get: get,
        getOuter: getOuter,
        aggregate: aggregate,
        max: max
      };
    };

    var api$3 = Dimension('height', function (element) {
      var dom = element.dom;
      return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
    });
    var get$7 = function (element) {
      return api$3.get(element);
    };

    var ancestors$1 = function (scope, predicate, isRoot) {
      return filter$2(parents(scope, isRoot), predicate);
    };
    var siblings$1 = function (scope, predicate) {
      return filter$2(siblings$2(scope), predicate);
    };

    var all = function (selector) {
      return all$2(selector);
    };
    var ancestors = function (scope, selector, isRoot) {
      return ancestors$1(scope, function (e) {
        return is$1(e, selector);
      }, isRoot);
    };
    var siblings = function (scope, selector) {
      return siblings$1(scope, function (e) {
        return is$1(e, selector);
      });
    };
    var descendants = function (scope, selector) {
      return all$2(selector, scope);
    };

    function ClosestOrAncestor (is, ancestor, scope, a, isRoot) {
      if (is(scope, a)) {
        return Optional.some(scope);
      } else if (isFunction(isRoot) && isRoot(scope)) {
        return Optional.none();
      } else {
        return ancestor(scope, a, isRoot);
      }
    }

    var ancestor$1 = function (scope, predicate, isRoot) {
      var element = scope.dom;
      var stop = isFunction(isRoot) ? isRoot : never;
      while (element.parentNode) {
        element = element.parentNode;
        var el = SugarElement.fromDom(element);
        if (predicate(el)) {
          return Optional.some(el);
        } else if (stop(el)) {
          break;
        }
      }
      return Optional.none();
    };
    var closest$2 = function (scope, predicate, isRoot) {
      var is = function (s, test) {
        return test(s);
      };
      return ClosestOrAncestor(is, ancestor$1, scope, predicate, isRoot);
    };
    var descendant$1 = function (scope, predicate) {
      var descend = function (node) {
        for (var i = 0; i < node.childNodes.length; i++) {
          var child_1 = SugarElement.fromDom(node.childNodes[i]);
          if (predicate(child_1)) {
            return Optional.some(child_1);
          }
          var res = descend(node.childNodes[i]);
          if (res.isSome()) {
            return res;
          }
        }
        return Optional.none();
      };
      return descend(scope.dom);
    };

    var first$1 = function (selector) {
      return one(selector);
    };
    var ancestor = function (scope, selector, isRoot) {
      return ancestor$1(scope, function (e) {
        return is$1(e, selector);
      }, isRoot);
    };
    var descendant = function (scope, selector) {
      return one(selector, scope);
    };
    var closest$1 = function (scope, selector, isRoot) {
      var is = function (element, selector) {
        return is$1(element, selector);
      };
      return ClosestOrAncestor(is, ancestor, scope, selector, isRoot);
    };

    var BACKSPACE = [8];
    var TAB = [9];
    var ENTER = [13];
    var ESCAPE = [27];
    var SPACE = [32];
    var LEFT = [37];
    var UP = [38];
    var RIGHT = [39];
    var DOWN = [40];

    var cyclePrev = function (values, index, predicate) {
      var before = reverse(values.slice(0, index));
      var after = reverse(values.slice(index + 1));
      return find$2(before.concat(after), predicate);
    };
    var tryPrev = function (values, index, predicate) {
      var before = reverse(values.slice(0, index));
      return find$2(before, predicate);
    };
    var cycleNext = function (values, index, predicate) {
      var before = values.slice(0, index);
      var after = values.slice(index + 1);
      return find$2(after.concat(before), predicate);
    };
    var tryNext = function (values, index, predicate) {
      var after = values.slice(index + 1);
      return find$2(after, predicate);
    };

    var inSet = function (keys) {
      return function (event) {
        var raw = event.raw;
        return contains$1(keys, raw.which);
      };
    };
    var and = function (preds) {
      return function (event) {
        return forall(preds, function (pred) {
          return pred(event);
        });
      };
    };
    var isShift = function (event) {
      var raw = event.raw;
      return raw.shiftKey === true;
    };
    var isControl = function (event) {
      var raw = event.raw;
      return raw.ctrlKey === true;
    };
    var isNotShift = not(isShift);

    var rule = function (matches, action) {
      return {
        matches: matches,
        classification: action
      };
    };
    var choose = function (transitions, event) {
      var transition = find$2(transitions, function (t) {
        return t.matches(event);
      });
      return transition.map(function (t) {
        return t.classification;
      });
    };

    var cycleBy = function (value, delta, min, max) {
      var r = value + delta;
      if (r > max) {
        return min;
      } else if (r < min) {
        return max;
      } else {
        return r;
      }
    };
    var clamp = function (value, min, max) {
      return Math.min(Math.max(value, min), max);
    };

    var dehighlightAllExcept = function (component, hConfig, hState, skip) {
      var highlighted = descendants(component.element, '.' + hConfig.highlightClass);
      each$1(highlighted, function (h) {
        if (!exists(skip, function (skipComp) {
            return skipComp.element === h;
          })) {
          remove$3(h, hConfig.highlightClass);
          component.getSystem().getByDom(h).each(function (target) {
            hConfig.onDehighlight(component, target);
            emit(target, dehighlight$1());
          });
        }
      });
    };
    var dehighlightAll = function (component, hConfig, hState) {
      return dehighlightAllExcept(component, hConfig, hState, []);
    };
    var dehighlight = function (component, hConfig, hState, target) {
      if (isHighlighted(component, hConfig, hState, target)) {
        remove$3(target.element, hConfig.highlightClass);
        hConfig.onDehighlight(component, target);
        emit(target, dehighlight$1());
      }
    };
    var highlight = function (component, hConfig, hState, target) {
      dehighlightAllExcept(component, hConfig, hState, [target]);
      if (!isHighlighted(component, hConfig, hState, target)) {
        add$1(target.element, hConfig.highlightClass);
        hConfig.onHighlight(component, target);
        emit(target, highlight$1());
      }
    };
    var highlightFirst = function (component, hConfig, hState) {
      getFirst(component, hConfig).each(function (firstComp) {
        highlight(component, hConfig, hState, firstComp);
      });
    };
    var highlightLast = function (component, hConfig, hState) {
      getLast(component, hConfig).each(function (lastComp) {
        highlight(component, hConfig, hState, lastComp);
      });
    };
    var highlightAt = function (component, hConfig, hState, index) {
      getByIndex(component, hConfig, hState, index).fold(function (err) {
        throw err;
      }, function (firstComp) {
        highlight(component, hConfig, hState, firstComp);
      });
    };
    var highlightBy = function (component, hConfig, hState, predicate) {
      var candidates = getCandidates(component, hConfig);
      var targetComp = find$2(candidates, predicate);
      targetComp.each(function (c) {
        highlight(component, hConfig, hState, c);
      });
    };
    var isHighlighted = function (component, hConfig, hState, queryTarget) {
      return has(queryTarget.element, hConfig.highlightClass);
    };
    var getHighlighted = function (component, hConfig, _hState) {
      return descendant(component.element, '.' + hConfig.highlightClass).bind(function (e) {
        return component.getSystem().getByDom(e).toOptional();
      });
    };
    var getByIndex = function (component, hConfig, hState, index) {
      var items = descendants(component.element, '.' + hConfig.itemClass);
      return Optional.from(items[index]).fold(function () {
        return Result.error(new Error('No element found with index ' + index));
      }, component.getSystem().getByDom);
    };
    var getFirst = function (component, hConfig, _hState) {
      return descendant(component.element, '.' + hConfig.itemClass).bind(function (e) {
        return component.getSystem().getByDom(e).toOptional();
      });
    };
    var getLast = function (component, hConfig, _hState) {
      var items = descendants(component.element, '.' + hConfig.itemClass);
      var last = items.length > 0 ? Optional.some(items[items.length - 1]) : Optional.none();
      return last.bind(function (c) {
        return component.getSystem().getByDom(c).toOptional();
      });
    };
    var getDelta = function (component, hConfig, hState, delta) {
      var items = descendants(component.element, '.' + hConfig.itemClass);
      var current = findIndex$1(items, function (item) {
        return has(item, hConfig.highlightClass);
      });
      return current.bind(function (selected) {
        var dest = cycleBy(selected, delta, 0, items.length - 1);
        return component.getSystem().getByDom(items[dest]).toOptional();
      });
    };
    var getPrevious = function (component, hConfig, hState) {
      return getDelta(component, hConfig, hState, -1);
    };
    var getNext = function (component, hConfig, hState) {
      return getDelta(component, hConfig, hState, +1);
    };
    var getCandidates = function (component, hConfig, _hState) {
      var items = descendants(component.element, '.' + hConfig.itemClass);
      return cat(map$2(items, function (i) {
        return component.getSystem().getByDom(i).toOptional();
      }));
    };

    var HighlightApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        dehighlightAll: dehighlightAll,
        dehighlight: dehighlight,
        highlight: highlight,
        highlightFirst: highlightFirst,
        highlightLast: highlightLast,
        highlightAt: highlightAt,
        highlightBy: highlightBy,
        isHighlighted: isHighlighted,
        getHighlighted: getHighlighted,
        getFirst: getFirst,
        getLast: getLast,
        getPrevious: getPrevious,
        getNext: getNext,
        getCandidates: getCandidates
    });

    var HighlightSchema = [
      required$1('highlightClass'),
      required$1('itemClass'),
      onHandler('onHighlight'),
      onHandler('onDehighlight')
    ];

    var Highlighting = create$5({
      fields: HighlightSchema,
      name: 'highlighting',
      apis: HighlightApis
    });

    var reportFocusShifting = function (component, prevFocus, newFocus) {
      var noChange = prevFocus.exists(function (p) {
        return newFocus.exists(function (n) {
          return eq(n, p);
        });
      });
      if (!noChange) {
        emitWith(component, focusShifted(), {
          prevFocus: prevFocus,
          newFocus: newFocus
        });
      }
    };
    var dom$2 = function () {
      var get = function (component) {
        return search(component.element);
      };
      var set = function (component, focusee) {
        var prevFocus = get(component);
        component.getSystem().triggerFocus(focusee, component.element);
        var newFocus = get(component);
        reportFocusShifting(component, prevFocus, newFocus);
      };
      return {
        get: get,
        set: set
      };
    };
    var highlights = function () {
      var get = function (component) {
        return Highlighting.getHighlighted(component).map(function (item) {
          return item.element;
        });
      };
      var set = function (component, element) {
        var prevFocus = get(component);
        component.getSystem().getByDom(element).fold(noop, function (item) {
          Highlighting.highlight(component, item);
        });
        var newFocus = get(component);
        reportFocusShifting(component, prevFocus, newFocus);
      };
      return {
        get: get,
        set: set
      };
    };

    var FocusInsideModes;
    (function (FocusInsideModes) {
      FocusInsideModes['OnFocusMode'] = 'onFocus';
      FocusInsideModes['OnEnterOrSpaceMode'] = 'onEnterOrSpace';
      FocusInsideModes['OnApiMode'] = 'onApi';
    }(FocusInsideModes || (FocusInsideModes = {})));

    var typical = function (infoSchema, stateInit, getKeydownRules, getKeyupRules, optFocusIn) {
      var schema = function () {
        return infoSchema.concat([
          defaulted('focusManager', dom$2()),
          defaultedOf('focusInside', 'onFocus', valueOf(function (val) {
            return contains$1([
              'onFocus',
              'onEnterOrSpace',
              'onApi'
            ], val) ? Result.value(val) : Result.error('Invalid value for focusInside');
          })),
          output('handler', me),
          output('state', stateInit),
          output('sendFocusIn', optFocusIn)
        ]);
      };
      var processKey = function (component, simulatedEvent, getRules, keyingConfig, keyingState) {
        var rules = getRules(component, simulatedEvent, keyingConfig, keyingState);
        return choose(rules, simulatedEvent.event).bind(function (rule) {
          return rule(component, simulatedEvent, keyingConfig, keyingState);
        });
      };
      var toEvents = function (keyingConfig, keyingState) {
        var onFocusHandler = keyingConfig.focusInside !== FocusInsideModes.OnFocusMode ? Optional.none() : optFocusIn(keyingConfig).map(function (focusIn) {
          return run(focus$4(), function (component, simulatedEvent) {
            focusIn(component, keyingConfig, keyingState);
            simulatedEvent.stop();
          });
        });
        var tryGoInsideComponent = function (component, simulatedEvent) {
          var isEnterOrSpace = inSet(SPACE.concat(ENTER))(simulatedEvent.event);
          if (keyingConfig.focusInside === FocusInsideModes.OnEnterOrSpaceMode && isEnterOrSpace && isSource(component, simulatedEvent)) {
            optFocusIn(keyingConfig).each(function (focusIn) {
              focusIn(component, keyingConfig, keyingState);
              simulatedEvent.stop();
            });
          }
        };
        var keyboardEvents = [
          run(keydown(), function (component, simulatedEvent) {
            processKey(component, simulatedEvent, getKeydownRules, keyingConfig, keyingState).fold(function () {
              tryGoInsideComponent(component, simulatedEvent);
            }, function (_) {
              simulatedEvent.stop();
            });
          }),
          run(keyup(), function (component, simulatedEvent) {
            processKey(component, simulatedEvent, getKeyupRules, keyingConfig, keyingState).each(function (_) {
              simulatedEvent.stop();
            });
          })
        ];
        return derive$3(onFocusHandler.toArray().concat(keyboardEvents));
      };
      var me = {
        schema: schema,
        processKey: processKey,
        toEvents: toEvents
      };
      return me;
    };

    var create$4 = function (cyclicField) {
      var schema = [
        option('onEscape'),
        option('onEnter'),
        defaulted('selector', '[data-alloy-tabstop="true"]:not(:disabled)'),
        defaulted('firstTabstop', 0),
        defaulted('useTabstopAt', always),
        option('visibilitySelector')
      ].concat([cyclicField]);
      var isVisible = function (tabbingConfig, element) {
        var target = tabbingConfig.visibilitySelector.bind(function (sel) {
          return closest$1(element, sel);
        }).getOr(element);
        return get$7(target) > 0;
      };
      var findInitial = function (component, tabbingConfig) {
        var tabstops = descendants(component.element, tabbingConfig.selector);
        var visibles = filter$2(tabstops, function (elem) {
          return isVisible(tabbingConfig, elem);
        });
        return Optional.from(visibles[tabbingConfig.firstTabstop]);
      };
      var findCurrent = function (component, tabbingConfig) {
        return tabbingConfig.focusManager.get(component).bind(function (elem) {
          return closest$1(elem, tabbingConfig.selector);
        });
      };
      var isTabstop = function (tabbingConfig, element) {
        return isVisible(tabbingConfig, element) && tabbingConfig.useTabstopAt(element);
      };
      var focusIn = function (component, tabbingConfig, _tabbingState) {
        findInitial(component, tabbingConfig).each(function (target) {
          tabbingConfig.focusManager.set(component, target);
        });
      };
      var goFromTabstop = function (component, tabstops, stopIndex, tabbingConfig, cycle) {
        return cycle(tabstops, stopIndex, function (elem) {
          return isTabstop(tabbingConfig, elem);
        }).fold(function () {
          return tabbingConfig.cyclic ? Optional.some(true) : Optional.none();
        }, function (target) {
          tabbingConfig.focusManager.set(component, target);
          return Optional.some(true);
        });
      };
      var go = function (component, _simulatedEvent, tabbingConfig, cycle) {
        var tabstops = descendants(component.element, tabbingConfig.selector);
        return findCurrent(component, tabbingConfig).bind(function (tabstop) {
          var optStopIndex = findIndex$1(tabstops, curry(eq, tabstop));
          return optStopIndex.bind(function (stopIndex) {
            return goFromTabstop(component, tabstops, stopIndex, tabbingConfig, cycle);
          });
        });
      };
      var goBackwards = function (component, simulatedEvent, tabbingConfig) {
        var navigate = tabbingConfig.cyclic ? cyclePrev : tryPrev;
        return go(component, simulatedEvent, tabbingConfig, navigate);
      };
      var goForwards = function (component, simulatedEvent, tabbingConfig) {
        var navigate = tabbingConfig.cyclic ? cycleNext : tryNext;
        return go(component, simulatedEvent, tabbingConfig, navigate);
      };
      var execute = function (component, simulatedEvent, tabbingConfig) {
        return tabbingConfig.onEnter.bind(function (f) {
          return f(component, simulatedEvent);
        });
      };
      var exit = function (component, simulatedEvent, tabbingConfig) {
        return tabbingConfig.onEscape.bind(function (f) {
          return f(component, simulatedEvent);
        });
      };
      var getKeydownRules = constant$1([
        rule(and([
          isShift,
          inSet(TAB)
        ]), goBackwards),
        rule(inSet(TAB), goForwards),
        rule(inSet(ESCAPE), exit),
        rule(and([
          isNotShift,
          inSet(ENTER)
        ]), execute)
      ]);
      var getKeyupRules = constant$1([]);
      return typical(schema, NoState.init, getKeydownRules, getKeyupRules, function () {
        return Optional.some(focusIn);
      });
    };

    var AcyclicType = create$4(customField('cyclic', never));

    var CyclicType = create$4(customField('cyclic', always));

    var inside = function (target) {
      return name$1(target) === 'input' && get$b(target, 'type') !== 'radio' || name$1(target) === 'textarea';
    };

    var doDefaultExecute = function (component, _simulatedEvent, focused) {
      dispatch(component, focused, execute$5());
      return Optional.some(true);
    };
    var defaultExecute = function (component, simulatedEvent, focused) {
      var isComplex = inside(focused) && inSet(SPACE)(simulatedEvent.event);
      return isComplex ? Optional.none() : doDefaultExecute(component, simulatedEvent, focused);
    };
    var stopEventForFirefox = function (_component, _simulatedEvent) {
      return Optional.some(true);
    };

    var schema$f = [
      defaulted('execute', defaultExecute),
      defaulted('useSpace', false),
      defaulted('useEnter', true),
      defaulted('useControlEnter', false),
      defaulted('useDown', false)
    ];
    var execute$4 = function (component, simulatedEvent, executeConfig) {
      return executeConfig.execute(component, simulatedEvent, component.element);
    };
    var getKeydownRules$5 = function (component, _simulatedEvent, executeConfig, _executeState) {
      var spaceExec = executeConfig.useSpace && !inside(component.element) ? SPACE : [];
      var enterExec = executeConfig.useEnter ? ENTER : [];
      var downExec = executeConfig.useDown ? DOWN : [];
      var execKeys = spaceExec.concat(enterExec).concat(downExec);
      return [rule(inSet(execKeys), execute$4)].concat(executeConfig.useControlEnter ? [rule(and([
          isControl,
          inSet(ENTER)
        ]), execute$4)] : []);
    };
    var getKeyupRules$5 = function (component, _simulatedEvent, executeConfig, _executeState) {
      return executeConfig.useSpace && !inside(component.element) ? [rule(inSet(SPACE), stopEventForFirefox)] : [];
    };
    var ExecutionType = typical(schema$f, NoState.init, getKeydownRules$5, getKeyupRules$5, function () {
      return Optional.none();
    });

    var singleton$1 = function (doRevoke) {
      var subject = Cell(Optional.none());
      var revoke = function () {
        return subject.get().each(doRevoke);
      };
      var clear = function () {
        revoke();
        subject.set(Optional.none());
      };
      var isSet = function () {
        return subject.get().isSome();
      };
      var get = function () {
        return subject.get();
      };
      var set = function (s) {
        revoke();
        subject.set(Optional.some(s));
      };
      return {
        clear: clear,
        isSet: isSet,
        get: get,
        set: set
      };
    };
    var destroyable = function () {
      return singleton$1(function (s) {
        return s.destroy();
      });
    };
    var api$2 = function () {
      var subject = destroyable();
      var run = function (f) {
        return subject.get().each(f);
      };
      return __assign(__assign({}, subject), { run: run });
    };
    var value = function () {
      var subject = singleton$1(noop);
      var on = function (f) {
        return subject.get().each(f);
      };
      return __assign(__assign({}, subject), { on: on });
    };

    var flatgrid$1 = function () {
      var dimensions = value();
      var setGridSize = function (numRows, numColumns) {
        dimensions.set({
          numRows: numRows,
          numColumns: numColumns
        });
      };
      var getNumRows = function () {
        return dimensions.get().map(function (d) {
          return d.numRows;
        });
      };
      var getNumColumns = function () {
        return dimensions.get().map(function (d) {
          return d.numColumns;
        });
      };
      return nu$2({
        readState: function () {
          return dimensions.get().map(function (d) {
            return {
              numRows: String(d.numRows),
              numColumns: String(d.numColumns)
            };
          }).getOr({
            numRows: '?',
            numColumns: '?'
          });
        },
        setGridSize: setGridSize,
        getNumRows: getNumRows,
        getNumColumns: getNumColumns
      });
    };
    var init$5 = function (spec) {
      return spec.state(spec);
    };

    var KeyingState = /*#__PURE__*/Object.freeze({
        __proto__: null,
        flatgrid: flatgrid$1,
        init: init$5
    });

    var onDirection = function (isLtr, isRtl) {
      return function (element) {
        return getDirection(element) === 'rtl' ? isRtl : isLtr;
      };
    };
    var getDirection = function (element) {
      return get$8(element, 'direction') === 'rtl' ? 'rtl' : 'ltr';
    };

    var useH = function (movement) {
      return function (component, simulatedEvent, config, state) {
        var move = movement(component.element);
        return use(move, component, simulatedEvent, config, state);
      };
    };
    var west = function (moveLeft, moveRight) {
      var movement = onDirection(moveLeft, moveRight);
      return useH(movement);
    };
    var east = function (moveLeft, moveRight) {
      var movement = onDirection(moveRight, moveLeft);
      return useH(movement);
    };
    var useV = function (move) {
      return function (component, simulatedEvent, config, state) {
        return use(move, component, simulatedEvent, config, state);
      };
    };
    var use = function (move, component, simulatedEvent, config, state) {
      var outcome = config.focusManager.get(component).bind(function (focused) {
        return move(component.element, focused, config, state);
      });
      return outcome.map(function (newFocus) {
        config.focusManager.set(component, newFocus);
        return true;
      });
    };
    var north = useV;
    var south = useV;
    var move$1 = useV;

    var isHidden = function (dom) {
      return dom.offsetWidth <= 0 && dom.offsetHeight <= 0;
    };
    var isVisible = function (element) {
      return !isHidden(element.dom);
    };

    var locate = function (candidates, predicate) {
      return findIndex$1(candidates, predicate).map(function (index) {
        return {
          index: index,
          candidates: candidates
        };
      });
    };

    var locateVisible = function (container, current, selector) {
      var predicate = function (x) {
        return eq(x, current);
      };
      var candidates = descendants(container, selector);
      var visible = filter$2(candidates, isVisible);
      return locate(visible, predicate);
    };
    var findIndex = function (elements, target) {
      return findIndex$1(elements, function (elem) {
        return eq(target, elem);
      });
    };

    var withGrid = function (values, index, numCols, f) {
      var oldRow = Math.floor(index / numCols);
      var oldColumn = index % numCols;
      return f(oldRow, oldColumn).bind(function (address) {
        var newIndex = address.row * numCols + address.column;
        return newIndex >= 0 && newIndex < values.length ? Optional.some(values[newIndex]) : Optional.none();
      });
    };
    var cycleHorizontal$1 = function (values, index, numRows, numCols, delta) {
      return withGrid(values, index, numCols, function (oldRow, oldColumn) {
        var onLastRow = oldRow === numRows - 1;
        var colsInRow = onLastRow ? values.length - oldRow * numCols : numCols;
        var newColumn = cycleBy(oldColumn, delta, 0, colsInRow - 1);
        return Optional.some({
          row: oldRow,
          column: newColumn
        });
      });
    };
    var cycleVertical$1 = function (values, index, numRows, numCols, delta) {
      return withGrid(values, index, numCols, function (oldRow, oldColumn) {
        var newRow = cycleBy(oldRow, delta, 0, numRows - 1);
        var onLastRow = newRow === numRows - 1;
        var colsInRow = onLastRow ? values.length - newRow * numCols : numCols;
        var newCol = clamp(oldColumn, 0, colsInRow - 1);
        return Optional.some({
          row: newRow,
          column: newCol
        });
      });
    };
    var cycleRight$1 = function (values, index, numRows, numCols) {
      return cycleHorizontal$1(values, index, numRows, numCols, +1);
    };
    var cycleLeft$1 = function (values, index, numRows, numCols) {
      return cycleHorizontal$1(values, index, numRows, numCols, -1);
    };
    var cycleUp$1 = function (values, index, numRows, numCols) {
      return cycleVertical$1(values, index, numRows, numCols, -1);
    };
    var cycleDown$1 = function (values, index, numRows, numCols) {
      return cycleVertical$1(values, index, numRows, numCols, +1);
    };

    var schema$e = [
      required$1('selector'),
      defaulted('execute', defaultExecute),
      onKeyboardHandler('onEscape'),
      defaulted('captureTab', false),
      initSize()
    ];
    var focusIn$3 = function (component, gridConfig, _gridState) {
      descendant(component.element, gridConfig.selector).each(function (first) {
        gridConfig.focusManager.set(component, first);
      });
    };
    var findCurrent$1 = function (component, gridConfig) {
      return gridConfig.focusManager.get(component).bind(function (elem) {
        return closest$1(elem, gridConfig.selector);
      });
    };
    var execute$3 = function (component, simulatedEvent, gridConfig, _gridState) {
      return findCurrent$1(component, gridConfig).bind(function (focused) {
        return gridConfig.execute(component, simulatedEvent, focused);
      });
    };
    var doMove$2 = function (cycle) {
      return function (element, focused, gridConfig, gridState) {
        return locateVisible(element, focused, gridConfig.selector).bind(function (identified) {
          return cycle(identified.candidates, identified.index, gridState.getNumRows().getOr(gridConfig.initSize.numRows), gridState.getNumColumns().getOr(gridConfig.initSize.numColumns));
        });
      };
    };
    var handleTab = function (_component, _simulatedEvent, gridConfig) {
      return gridConfig.captureTab ? Optional.some(true) : Optional.none();
    };
    var doEscape$1 = function (component, simulatedEvent, gridConfig) {
      return gridConfig.onEscape(component, simulatedEvent);
    };
    var moveLeft$3 = doMove$2(cycleLeft$1);
    var moveRight$3 = doMove$2(cycleRight$1);
    var moveNorth$1 = doMove$2(cycleUp$1);
    var moveSouth$1 = doMove$2(cycleDown$1);
    var getKeydownRules$4 = constant$1([
      rule(inSet(LEFT), west(moveLeft$3, moveRight$3)),
      rule(inSet(RIGHT), east(moveLeft$3, moveRight$3)),
      rule(inSet(UP), north(moveNorth$1)),
      rule(inSet(DOWN), south(moveSouth$1)),
      rule(and([
        isShift,
        inSet(TAB)
      ]), handleTab),
      rule(and([
        isNotShift,
        inSet(TAB)
      ]), handleTab),
      rule(inSet(ESCAPE), doEscape$1),
      rule(inSet(SPACE.concat(ENTER)), execute$3)
    ]);
    var getKeyupRules$4 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
    var FlatgridType = typical(schema$e, flatgrid$1, getKeydownRules$4, getKeyupRules$4, function () {
      return Optional.some(focusIn$3);
    });

    var horizontal = function (container, selector, current, delta) {
      var isDisabledButton = function (candidate) {
        return name$1(candidate) === 'button' && get$b(candidate, 'disabled') === 'disabled';
      };
      var tryCycle = function (initial, index, candidates) {
        var newIndex = cycleBy(index, delta, 0, candidates.length - 1);
        if (newIndex === initial) {
          return Optional.none();
        } else {
          return isDisabledButton(candidates[newIndex]) ? tryCycle(initial, newIndex, candidates) : Optional.from(candidates[newIndex]);
        }
      };
      return locateVisible(container, current, selector).bind(function (identified) {
        var index = identified.index;
        var candidates = identified.candidates;
        return tryCycle(index, index, candidates);
      });
    };

    var schema$d = [
      required$1('selector'),
      defaulted('getInitial', Optional.none),
      defaulted('execute', defaultExecute),
      onKeyboardHandler('onEscape'),
      defaulted('executeOnMove', false),
      defaulted('allowVertical', true)
    ];
    var findCurrent = function (component, flowConfig) {
      return flowConfig.focusManager.get(component).bind(function (elem) {
        return closest$1(elem, flowConfig.selector);
      });
    };
    var execute$2 = function (component, simulatedEvent, flowConfig) {
      return findCurrent(component, flowConfig).bind(function (focused) {
        return flowConfig.execute(component, simulatedEvent, focused);
      });
    };
    var focusIn$2 = function (component, flowConfig, _state) {
      flowConfig.getInitial(component).orThunk(function () {
        return descendant(component.element, flowConfig.selector);
      }).each(function (first) {
        flowConfig.focusManager.set(component, first);
      });
    };
    var moveLeft$2 = function (element, focused, info) {
      return horizontal(element, info.selector, focused, -1);
    };
    var moveRight$2 = function (element, focused, info) {
      return horizontal(element, info.selector, focused, +1);
    };
    var doMove$1 = function (movement) {
      return function (component, simulatedEvent, flowConfig, flowState) {
        return movement(component, simulatedEvent, flowConfig, flowState).bind(function () {
          return flowConfig.executeOnMove ? execute$2(component, simulatedEvent, flowConfig) : Optional.some(true);
        });
      };
    };
    var doEscape = function (component, simulatedEvent, flowConfig) {
      return flowConfig.onEscape(component, simulatedEvent);
    };
    var getKeydownRules$3 = function (_component, _se, flowConfig, _flowState) {
      var westMovers = LEFT.concat(flowConfig.allowVertical ? UP : []);
      var eastMovers = RIGHT.concat(flowConfig.allowVertical ? DOWN : []);
      return [
        rule(inSet(westMovers), doMove$1(west(moveLeft$2, moveRight$2))),
        rule(inSet(eastMovers), doMove$1(east(moveLeft$2, moveRight$2))),
        rule(inSet(ENTER), execute$2),
        rule(inSet(SPACE), execute$2),
        rule(inSet(ESCAPE), doEscape)
      ];
    };
    var getKeyupRules$3 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
    var FlowType = typical(schema$d, NoState.init, getKeydownRules$3, getKeyupRules$3, function () {
      return Optional.some(focusIn$2);
    });

    var toCell = function (matrix, rowIndex, columnIndex) {
      return Optional.from(matrix[rowIndex]).bind(function (row) {
        return Optional.from(row[columnIndex]).map(function (cell) {
          return {
            rowIndex: rowIndex,
            columnIndex: columnIndex,
            cell: cell
          };
        });
      });
    };
    var cycleHorizontal = function (matrix, rowIndex, startCol, deltaCol) {
      var row = matrix[rowIndex];
      var colsInRow = row.length;
      var newColIndex = cycleBy(startCol, deltaCol, 0, colsInRow - 1);
      return toCell(matrix, rowIndex, newColIndex);
    };
    var cycleVertical = function (matrix, colIndex, startRow, deltaRow) {
      var nextRowIndex = cycleBy(startRow, deltaRow, 0, matrix.length - 1);
      var colsInNextRow = matrix[nextRowIndex].length;
      var nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
      return toCell(matrix, nextRowIndex, nextColIndex);
    };
    var moveHorizontal = function (matrix, rowIndex, startCol, deltaCol) {
      var row = matrix[rowIndex];
      var colsInRow = row.length;
      var newColIndex = clamp(startCol + deltaCol, 0, colsInRow - 1);
      return toCell(matrix, rowIndex, newColIndex);
    };
    var moveVertical = function (matrix, colIndex, startRow, deltaRow) {
      var nextRowIndex = clamp(startRow + deltaRow, 0, matrix.length - 1);
      var colsInNextRow = matrix[nextRowIndex].length;
      var nextColIndex = clamp(colIndex, 0, colsInNextRow - 1);
      return toCell(matrix, nextRowIndex, nextColIndex);
    };
    var cycleRight = function (matrix, startRow, startCol) {
      return cycleHorizontal(matrix, startRow, startCol, +1);
    };
    var cycleLeft = function (matrix, startRow, startCol) {
      return cycleHorizontal(matrix, startRow, startCol, -1);
    };
    var cycleUp = function (matrix, startRow, startCol) {
      return cycleVertical(matrix, startCol, startRow, -1);
    };
    var cycleDown = function (matrix, startRow, startCol) {
      return cycleVertical(matrix, startCol, startRow, +1);
    };
    var moveLeft$1 = function (matrix, startRow, startCol) {
      return moveHorizontal(matrix, startRow, startCol, -1);
    };
    var moveRight$1 = function (matrix, startRow, startCol) {
      return moveHorizontal(matrix, startRow, startCol, +1);
    };
    var moveUp$1 = function (matrix, startRow, startCol) {
      return moveVertical(matrix, startCol, startRow, -1);
    };
    var moveDown$1 = function (matrix, startRow, startCol) {
      return moveVertical(matrix, startCol, startRow, +1);
    };

    var schema$c = [
      requiredObjOf('selectors', [
        required$1('row'),
        required$1('cell')
      ]),
      defaulted('cycles', true),
      defaulted('previousSelector', Optional.none),
      defaulted('execute', defaultExecute)
    ];
    var focusIn$1 = function (component, matrixConfig, _state) {
      var focused = matrixConfig.previousSelector(component).orThunk(function () {
        var selectors = matrixConfig.selectors;
        return descendant(component.element, selectors.cell);
      });
      focused.each(function (cell) {
        matrixConfig.focusManager.set(component, cell);
      });
    };
    var execute$1 = function (component, simulatedEvent, matrixConfig) {
      return search(component.element).bind(function (focused) {
        return matrixConfig.execute(component, simulatedEvent, focused);
      });
    };
    var toMatrix = function (rows, matrixConfig) {
      return map$2(rows, function (row) {
        return descendants(row, matrixConfig.selectors.cell);
      });
    };
    var doMove = function (ifCycle, ifMove) {
      return function (element, focused, matrixConfig) {
        var move = matrixConfig.cycles ? ifCycle : ifMove;
        return closest$1(focused, matrixConfig.selectors.row).bind(function (inRow) {
          var cellsInRow = descendants(inRow, matrixConfig.selectors.cell);
          return findIndex(cellsInRow, focused).bind(function (colIndex) {
            var allRows = descendants(element, matrixConfig.selectors.row);
            return findIndex(allRows, inRow).bind(function (rowIndex) {
              var matrix = toMatrix(allRows, matrixConfig);
              return move(matrix, rowIndex, colIndex).map(function (next) {
                return next.cell;
              });
            });
          });
        });
      };
    };
    var moveLeft = doMove(cycleLeft, moveLeft$1);
    var moveRight = doMove(cycleRight, moveRight$1);
    var moveNorth = doMove(cycleUp, moveUp$1);
    var moveSouth = doMove(cycleDown, moveDown$1);
    var getKeydownRules$2 = constant$1([
      rule(inSet(LEFT), west(moveLeft, moveRight)),
      rule(inSet(RIGHT), east(moveLeft, moveRight)),
      rule(inSet(UP), north(moveNorth)),
      rule(inSet(DOWN), south(moveSouth)),
      rule(inSet(SPACE.concat(ENTER)), execute$1)
    ]);
    var getKeyupRules$2 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
    var MatrixType = typical(schema$c, NoState.init, getKeydownRules$2, getKeyupRules$2, function () {
      return Optional.some(focusIn$1);
    });

    var schema$b = [
      required$1('selector'),
      defaulted('execute', defaultExecute),
      defaulted('moveOnTab', false)
    ];
    var execute = function (component, simulatedEvent, menuConfig) {
      return menuConfig.focusManager.get(component).bind(function (focused) {
        return menuConfig.execute(component, simulatedEvent, focused);
      });
    };
    var focusIn = function (component, menuConfig, _state) {
      descendant(component.element, menuConfig.selector).each(function (first) {
        menuConfig.focusManager.set(component, first);
      });
    };
    var moveUp = function (element, focused, info) {
      return horizontal(element, info.selector, focused, -1);
    };
    var moveDown = function (element, focused, info) {
      return horizontal(element, info.selector, focused, +1);
    };
    var fireShiftTab = function (component, simulatedEvent, menuConfig, menuState) {
      return menuConfig.moveOnTab ? move$1(moveUp)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
    };
    var fireTab = function (component, simulatedEvent, menuConfig, menuState) {
      return menuConfig.moveOnTab ? move$1(moveDown)(component, simulatedEvent, menuConfig, menuState) : Optional.none();
    };
    var getKeydownRules$1 = constant$1([
      rule(inSet(UP), move$1(moveUp)),
      rule(inSet(DOWN), move$1(moveDown)),
      rule(and([
        isShift,
        inSet(TAB)
      ]), fireShiftTab),
      rule(and([
        isNotShift,
        inSet(TAB)
      ]), fireTab),
      rule(inSet(ENTER), execute),
      rule(inSet(SPACE), execute)
    ]);
    var getKeyupRules$1 = constant$1([rule(inSet(SPACE), stopEventForFirefox)]);
    var MenuType = typical(schema$b, NoState.init, getKeydownRules$1, getKeyupRules$1, function () {
      return Optional.some(focusIn);
    });

    var schema$a = [
      onKeyboardHandler('onSpace'),
      onKeyboardHandler('onEnter'),
      onKeyboardHandler('onShiftEnter'),
      onKeyboardHandler('onLeft'),
      onKeyboardHandler('onRight'),
      onKeyboardHandler('onTab'),
      onKeyboardHandler('onShiftTab'),
      onKeyboardHandler('onUp'),
      onKeyboardHandler('onDown'),
      onKeyboardHandler('onEscape'),
      defaulted('stopSpaceKeyup', false),
      option('focusIn')
    ];
    var getKeydownRules = function (component, simulatedEvent, specialInfo) {
      return [
        rule(inSet(SPACE), specialInfo.onSpace),
        rule(and([
          isNotShift,
          inSet(ENTER)
        ]), specialInfo.onEnter),
        rule(and([
          isShift,
          inSet(ENTER)
        ]), specialInfo.onShiftEnter),
        rule(and([
          isShift,
          inSet(TAB)
        ]), specialInfo.onShiftTab),
        rule(and([
          isNotShift,
          inSet(TAB)
        ]), specialInfo.onTab),
        rule(inSet(UP), specialInfo.onUp),
        rule(inSet(DOWN), specialInfo.onDown),
        rule(inSet(LEFT), specialInfo.onLeft),
        rule(inSet(RIGHT), specialInfo.onRight),
        rule(inSet(SPACE), specialInfo.onSpace),
        rule(inSet(ESCAPE), specialInfo.onEscape)
      ];
    };
    var getKeyupRules = function (component, simulatedEvent, specialInfo) {
      return specialInfo.stopSpaceKeyup ? [rule(inSet(SPACE), stopEventForFirefox)] : [];
    };
    var SpecialType = typical(schema$a, NoState.init, getKeydownRules, getKeyupRules, function (specialInfo) {
      return specialInfo.focusIn;
    });

    var acyclic = AcyclicType.schema();
    var cyclic = CyclicType.schema();
    var flow = FlowType.schema();
    var flatgrid = FlatgridType.schema();
    var matrix = MatrixType.schema();
    var execution = ExecutionType.schema();
    var menu = MenuType.schema();
    var special = SpecialType.schema();

    var KeyboardBranches = /*#__PURE__*/Object.freeze({
        __proto__: null,
        acyclic: acyclic,
        cyclic: cyclic,
        flow: flow,
        flatgrid: flatgrid,
        matrix: matrix,
        execution: execution,
        menu: menu,
        special: special
    });

    var isFlatgridState = function (keyState) {
      return hasNonNullableKey(keyState, 'setGridSize');
    };
    var Keying = createModes({
      branchKey: 'mode',
      branches: KeyboardBranches,
      name: 'keying',
      active: {
        events: function (keyingConfig, keyingState) {
          var handler = keyingConfig.handler;
          return handler.toEvents(keyingConfig, keyingState);
        }
      },
      apis: {
        focusIn: function (component, keyConfig, keyState) {
          keyConfig.sendFocusIn(keyConfig).fold(function () {
            component.getSystem().triggerFocus(component.element, component.element);
          }, function (sendFocusIn) {
            sendFocusIn(component, keyConfig, keyState);
          });
        },
        setGridSize: function (component, keyConfig, keyState, numRows, numColumns) {
          if (!isFlatgridState(keyState)) {
            console.error('Layout does not support setGridSize');
          } else {
            keyState.setGridSize(numRows, numColumns);
          }
        }
      },
      state: KeyingState
    });

    var field$1 = function (name, forbidden) {
      return defaultedObjOf(name, {}, map$2(forbidden, function (f) {
        return forbid(f.name(), 'Cannot configure ' + f.name() + ' for ' + name);
      }).concat([customField('dump', identity)]));
    };
    var get$6 = function (data) {
      return data.dump;
    };
    var augment = function (data, original) {
      return __assign(__assign({}, data.dump), derive$2(original));
    };
    var SketchBehaviours = {
      field: field$1,
      augment: augment,
      get: get$6
    };

    var _placeholder = 'placeholder';
    var adt$5 = Adt.generate([
      {
        single: [
          'required',
          'valueThunk'
        ]
      },
      {
        multiple: [
          'required',
          'valueThunks'
        ]
      }
    ]);
    var isSubstituted = function (spec) {
      return has$2(spec, 'uiType');
    };
    var subPlaceholder = function (owner, detail, compSpec, placeholders) {
      if (owner.exists(function (o) {
          return o !== compSpec.owner;
        })) {
        return adt$5.single(true, constant$1(compSpec));
      }
      return get$c(placeholders, compSpec.name).fold(function () {
        throw new Error('Unknown placeholder component: ' + compSpec.name + '\nKnown: [' + keys(placeholders) + ']\nNamespace: ' + owner.getOr('none') + '\nSpec: ' + JSON.stringify(compSpec, null, 2));
      }, function (newSpec) {
        return newSpec.replace();
      });
    };
    var scan = function (owner, detail, compSpec, placeholders) {
      if (isSubstituted(compSpec) && compSpec.uiType === _placeholder) {
        return subPlaceholder(owner, detail, compSpec, placeholders);
      } else {
        return adt$5.single(false, constant$1(compSpec));
      }
    };
    var substitute = function (owner, detail, compSpec, placeholders) {
      var base = scan(owner, detail, compSpec, placeholders);
      return base.fold(function (req, valueThunk) {
        var value = isSubstituted(compSpec) ? valueThunk(detail, compSpec.config, compSpec.validated) : valueThunk(detail);
        var childSpecs = get$c(value, 'components').getOr([]);
        var substituted = bind$3(childSpecs, function (c) {
          return substitute(owner, detail, c, placeholders);
        });
        return [__assign(__assign({}, value), { components: substituted })];
      }, function (req, valuesThunk) {
        if (isSubstituted(compSpec)) {
          var values = valuesThunk(detail, compSpec.config, compSpec.validated);
          var preprocessor = compSpec.validated.preprocess.getOr(identity);
          return preprocessor(values);
        } else {
          return valuesThunk(detail);
        }
      });
    };
    var substituteAll = function (owner, detail, components, placeholders) {
      return bind$3(components, function (c) {
        return substitute(owner, detail, c, placeholders);
      });
    };
    var oneReplace = function (label, replacements) {
      var called = false;
      var used = function () {
        return called;
      };
      var replace = function () {
        if (called) {
          throw new Error('Trying to use the same placeholder more than once: ' + label);
        }
        called = true;
        return replacements;
      };
      var required = function () {
        return replacements.fold(function (req, _) {
          return req;
        }, function (req, _) {
          return req;
        });
      };
      return {
        name: constant$1(label),
        required: required,
        used: used,
        replace: replace
      };
    };
    var substitutePlaces = function (owner, detail, components, placeholders) {
      var ps = map$1(placeholders, function (ph, name) {
        return oneReplace(name, ph);
      });
      var outcome = substituteAll(owner, detail, components, ps);
      each(ps, function (p) {
        if (p.used() === false && p.required()) {
          throw new Error('Placeholder: ' + p.name() + ' was not found in components list\nNamespace: ' + owner.getOr('none') + '\nComponents: ' + JSON.stringify(detail.components, null, 2));
        }
      });
      return outcome;
    };
    var single$2 = adt$5.single;
    var multiple = adt$5.multiple;
    var placeholder = constant$1(_placeholder);

    var unique = 0;
    var generate$4 = function (prefix) {
      var date = new Date();
      var time = date.getTime();
      var random = Math.floor(Math.random() * 1000000000);
      unique++;
      return prefix + '_' + random + unique + String(time);
    };

    var adt$4 = Adt.generate([
      { required: ['data'] },
      { external: ['data'] },
      { optional: ['data'] },
      { group: ['data'] }
    ]);
    var fFactory = defaulted('factory', { sketch: identity });
    var fSchema = defaulted('schema', []);
    var fName = required$1('name');
    var fPname = field$2('pname', 'pname', defaultedThunk(function (typeSpec) {
      return '<alloy.' + generate$4(typeSpec.name) + '>';
    }), anyValue());
    var fGroupSchema = customField('schema', function () {
      return [option('preprocess')];
    });
    var fDefaults = defaulted('defaults', constant$1({}));
    var fOverrides = defaulted('overrides', constant$1({}));
    var requiredSpec = objOf([
      fFactory,
      fSchema,
      fName,
      fPname,
      fDefaults,
      fOverrides
    ]);
    var externalSpec = objOf([
      fFactory,
      fSchema,
      fName,
      fDefaults,
      fOverrides
    ]);
    var optionalSpec = objOf([
      fFactory,
      fSchema,
      fName,
      fPname,
      fDefaults,
      fOverrides
    ]);
    var groupSpec = objOf([
      fFactory,
      fGroupSchema,
      fName,
      required$1('unit'),
      fPname,
      fDefaults,
      fOverrides
    ]);
    var asNamedPart = function (part) {
      return part.fold(Optional.some, Optional.none, Optional.some, Optional.some);
    };
    var name = function (part) {
      var get = function (data) {
        return data.name;
      };
      return part.fold(get, get, get, get);
    };
    var convert$1 = function (adtConstructor, partSchema) {
      return function (spec) {
        var data = asRawOrDie$1('Converting part type', partSchema, spec);
        return adtConstructor(data);
      };
    };
    var required = convert$1(adt$4.required, requiredSpec);
    convert$1(adt$4.external, externalSpec);
    var optional = convert$1(adt$4.optional, optionalSpec);
    var group = convert$1(adt$4.group, groupSpec);
    var original = constant$1('entirety');

    var combine$2 = function (detail, data, partSpec, partValidated) {
      return deepMerge(data.defaults(detail, partSpec, partValidated), partSpec, { uid: detail.partUids[data.name] }, data.overrides(detail, partSpec, partValidated));
    };
    var subs = function (owner, detail, parts) {
      var internals = {};
      var externals = {};
      each$1(parts, function (part) {
        part.fold(function (data) {
          internals[data.pname] = single$2(true, function (detail, partSpec, partValidated) {
            return data.factory.sketch(combine$2(detail, data, partSpec, partValidated));
          });
        }, function (data) {
          var partSpec = detail.parts[data.name];
          externals[data.name] = constant$1(data.factory.sketch(combine$2(detail, data, partSpec[original()]), partSpec));
        }, function (data) {
          internals[data.pname] = single$2(false, function (detail, partSpec, partValidated) {
            return data.factory.sketch(combine$2(detail, data, partSpec, partValidated));
          });
        }, function (data) {
          internals[data.pname] = multiple(true, function (detail, _partSpec, _partValidated) {
            var units = detail[data.name];
            return map$2(units, function (u) {
              return data.factory.sketch(deepMerge(data.defaults(detail, u, _partValidated), u, data.overrides(detail, u)));
            });
          });
        });
      });
      return {
        internals: constant$1(internals),
        externals: constant$1(externals)
      };
    };

    var generate$3 = function (owner, parts) {
      var r = {};
      each$1(parts, function (part) {
        asNamedPart(part).each(function (np) {
          var g = doGenerateOne(owner, np.pname);
          r[np.name] = function (config) {
            var validated = asRawOrDie$1('Part: ' + np.name + ' in ' + owner, objOf(np.schema), config);
            return __assign(__assign({}, g), {
              config: config,
              validated: validated
            });
          };
        });
      });
      return r;
    };
    var doGenerateOne = function (owner, pname) {
      return {
        uiType: placeholder(),
        owner: owner,
        name: pname
      };
    };
    var generateOne = function (owner, pname, config) {
      return {
        uiType: placeholder(),
        owner: owner,
        name: pname,
        config: config,
        validated: {}
      };
    };
    var schemas = function (parts) {
      return bind$3(parts, function (part) {
        return part.fold(Optional.none, Optional.some, Optional.none, Optional.none).map(function (data) {
          return requiredObjOf(data.name, data.schema.concat([snapshot(original())]));
        }).toArray();
      });
    };
    var names = function (parts) {
      return map$2(parts, name);
    };
    var substitutes = function (owner, detail, parts) {
      return subs(owner, detail, parts);
    };
    var components = function (owner, detail, internals) {
      return substitutePlaces(Optional.some(owner), detail, detail.components, internals);
    };
    var getPart = function (component, detail, partKey) {
      var uid = detail.partUids[partKey];
      return component.getSystem().getByUid(uid).toOptional();
    };
    var getPartOrDie = function (component, detail, partKey) {
      return getPart(component, detail, partKey).getOrDie('Could not find part: ' + partKey);
    };
    var getAllParts = function (component, detail) {
      var system = component.getSystem();
      return map$1(detail.partUids, function (pUid, _k) {
        return constant$1(system.getByUid(pUid));
      });
    };
    var defaultUids = function (baseUid, partTypes) {
      var partNames = names(partTypes);
      return wrapAll(map$2(partNames, function (pn) {
        return {
          key: pn,
          value: baseUid + '-' + pn
        };
      }));
    };
    var defaultUidsSchema = function (partTypes) {
      return field$2('partUids', 'partUids', mergeWithThunk(function (spec) {
        return defaultUids(spec.uid, partTypes);
      }), anyValue());
    };

    var premadeTag = generate$4('alloy-premade');
    var premade$1 = function (comp) {
      return wrap(premadeTag, comp);
    };
    var getPremade = function (spec) {
      return get$c(spec, premadeTag);
    };
    var makeApi = function (f) {
      return markAsSketchApi(function (component) {
        var rest = [];
        for (var _i = 1; _i < arguments.length; _i++) {
          rest[_i - 1] = arguments[_i];
        }
        return f.apply(void 0, __spreadArray([
          component.getApis(),
          component
        ], rest));
      }, f);
    };

    var prefix$1 = constant$1('alloy-id-');
    var idAttr$1 = constant$1('data-alloy-id');

    var prefix = prefix$1();
    var idAttr = idAttr$1();
    var write = function (label, elem) {
      var id = generate$4(prefix + label);
      writeOnly(elem, id);
      return id;
    };
    var writeOnly = function (elem, uid) {
      Object.defineProperty(elem.dom, idAttr, {
        value: uid,
        writable: true
      });
    };
    var read = function (elem) {
      var id = isElement(elem) ? elem.dom[idAttr] : null;
      return Optional.from(id);
    };
    var generate$2 = function (prefix) {
      return generate$4(prefix);
    };

    var base = function (partSchemas, partUidsSchemas) {
      var ps = partSchemas.length > 0 ? [requiredObjOf('parts', partSchemas)] : [];
      return ps.concat([
        required$1('uid'),
        defaulted('dom', {}),
        defaulted('components', []),
        snapshot('originalSpec'),
        defaulted('debug.sketcher', {})
      ]).concat(partUidsSchemas);
    };
    var asRawOrDie = function (label, schema, spec, partSchemas, partUidsSchemas) {
      var baseS = base(partSchemas, partUidsSchemas);
      return asRawOrDie$1(label + ' [SpecSchema]', objOfOnly(baseS.concat(schema)), spec);
    };

    var single$1 = function (owner, schema, factory, spec) {
      var specWithUid = supplyUid(spec);
      var detail = asRawOrDie(owner, schema, specWithUid, [], []);
      return factory(detail, specWithUid);
    };
    var composite$1 = function (owner, schema, partTypes, factory, spec) {
      var specWithUid = supplyUid(spec);
      var partSchemas = schemas(partTypes);
      var partUidsSchema = defaultUidsSchema(partTypes);
      var detail = asRawOrDie(owner, schema, specWithUid, partSchemas, [partUidsSchema]);
      var subs = substitutes(owner, detail, partTypes);
      var components$1 = components(owner, detail, subs.internals());
      return factory(detail, components$1, specWithUid, subs.externals());
    };
    var hasUid = function (spec) {
      return has$2(spec, 'uid');
    };
    var supplyUid = function (spec) {
      return hasUid(spec) ? spec : __assign(__assign({}, spec), { uid: generate$2('uid') });
    };

    var isSketchSpec$1 = function (spec) {
      return spec.uid !== undefined;
    };
    var singleSchema = objOfOnly([
      required$1('name'),
      required$1('factory'),
      required$1('configFields'),
      defaulted('apis', {}),
      defaulted('extraApis', {})
    ]);
    var compositeSchema = objOfOnly([
      required$1('name'),
      required$1('factory'),
      required$1('configFields'),
      required$1('partFields'),
      defaulted('apis', {}),
      defaulted('extraApis', {})
    ]);
    var single = function (rawConfig) {
      var config = asRawOrDie$1('Sketcher for ' + rawConfig.name, singleSchema, rawConfig);
      var sketch = function (spec) {
        return single$1(config.name, config.configFields, config.factory, spec);
      };
      var apis = map$1(config.apis, makeApi);
      var extraApis = map$1(config.extraApis, function (f, k) {
        return markAsExtraApi(f, k);
      });
      return __assign(__assign({
        name: config.name,
        configFields: config.configFields,
        sketch: sketch
      }, apis), extraApis);
    };
    var composite = function (rawConfig) {
      var config = asRawOrDie$1('Sketcher for ' + rawConfig.name, compositeSchema, rawConfig);
      var sketch = function (spec) {
        return composite$1(config.name, config.configFields, config.partFields, config.factory, spec);
      };
      var parts = generate$3(config.name, config.partFields);
      var apis = map$1(config.apis, makeApi);
      var extraApis = map$1(config.extraApis, function (f, k) {
        return markAsExtraApi(f, k);
      });
      return __assign(__assign({
        name: config.name,
        partFields: config.partFields,
        configFields: config.configFields,
        sketch: sketch,
        parts: parts
      }, apis), extraApis);
    };

    var factory$5 = function (detail) {
      var events = events$8(detail.action);
      var tag = detail.dom.tag;
      var lookupAttr = function (attr) {
        return get$c(detail.dom, 'attributes').bind(function (attrs) {
          return get$c(attrs, attr);
        });
      };
      var getModAttributes = function () {
        if (tag === 'button') {
          var type = lookupAttr('type').getOr('button');
          var roleAttrs = lookupAttr('role').map(function (role) {
            return { role: role };
          }).getOr({});
          return __assign({ type: type }, roleAttrs);
        } else {
          var role = lookupAttr('role').getOr('button');
          return { role: role };
        }
      };
      return {
        uid: detail.uid,
        dom: detail.dom,
        components: detail.components,
        events: events,
        behaviours: SketchBehaviours.augment(detail.buttonBehaviours, [
          Focusing.config({}),
          Keying.config({
            mode: 'execution',
            useSpace: true,
            useEnter: true
          })
        ]),
        domModification: { attributes: getModAttributes() },
        eventOrder: detail.eventOrder
      };
    };
    var Button = single({
      name: 'Button',
      factory: factory$5,
      configFields: [
        defaulted('uid', undefined),
        required$1('dom'),
        defaulted('components', []),
        SketchBehaviours.field('buttonBehaviours', [
          Focusing,
          Keying
        ]),
        option('action'),
        option('role'),
        defaulted('eventOrder', {})
      ]
    });

    var exhibit$3 = function () {
      return nu$3({
        styles: {
          '-webkit-user-select': 'none',
          'user-select': 'none',
          '-ms-user-select': 'none',
          '-moz-user-select': '-moz-none'
        },
        attributes: { unselectable: 'on' }
      });
    };
    var events$6 = function () {
      return derive$3([abort(selectstart(), always)]);
    };

    var ActiveUnselecting = /*#__PURE__*/Object.freeze({
        __proto__: null,
        events: events$6,
        exhibit: exhibit$3
    });

    var Unselecting = create$5({
      fields: [],
      name: 'unselecting',
      active: ActiveUnselecting
    });

    var getAttrs$1 = function (elem) {
      var attributes = elem.dom.attributes !== undefined ? elem.dom.attributes : [];
      return foldl(attributes, function (b, attr) {
        var _a;
        if (attr.name === 'class') {
          return b;
        } else {
          return __assign(__assign({}, b), (_a = {}, _a[attr.name] = attr.value, _a));
        }
      }, {});
    };
    var getClasses = function (elem) {
      return Array.prototype.slice.call(elem.dom.classList, 0);
    };
    var fromHtml = function (html) {
      var elem = SugarElement.fromHtml(html);
      var children$1 = children(elem);
      var attrs = getAttrs$1(elem);
      var classes = getClasses(elem);
      var contents = children$1.length === 0 ? {} : { innerHtml: get$9(elem) };
      return __assign({
        tag: name$1(elem),
        classes: classes,
        attributes: attrs
      }, contents);
    };

    var dom$1 = function (rawHtml) {
      var html = supplant(rawHtml, { prefix: prefix$2 });
      return fromHtml(html);
    };
    var spec = function (rawHtml) {
      return { dom: dom$1(rawHtml) };
    };

    var forToolbarCommand = function (editor, command) {
      return forToolbar(command, function () {
        editor.execCommand(command);
      }, {}, editor);
    };
    var getToggleBehaviours = function (command) {
      return derive$2([
        Toggling.config({
          toggleClass: resolve('toolbar-button-selected'),
          toggleOnExecute: false,
          aria: { mode: 'pressed' }
        }),
        format(command, function (button, status) {
          var toggle = status ? Toggling.on : Toggling.off;
          toggle(button);
        })
      ]);
    };
    var forToolbarStateCommand = function (editor, command) {
      var extraBehaviours = getToggleBehaviours(command);
      return forToolbar(command, function () {
        editor.execCommand(command);
      }, extraBehaviours, editor);
    };
    var forToolbarStateAction = function (editor, clazz, command, action) {
      var extraBehaviours = getToggleBehaviours(command);
      return forToolbar(clazz, action, extraBehaviours, editor);
    };
    var getToolbarIconButton = function (clazz, editor) {
      var icons = editor.ui.registry.getAll().icons;
      var optOxideIcon = Optional.from(icons[clazz]);
      return optOxideIcon.fold(function () {
        return dom$1('<span class="${prefix}-toolbar-button ${prefix}-toolbar-group-item ${prefix}-icon-' + clazz + ' ${prefix}-icon"></span>');
      }, function (icon) {
        return dom$1('<span class="${prefix}-toolbar-button ${prefix}-toolbar-group-item">' + icon + '</span>');
      });
    };
    var forToolbar = function (clazz, action, extraBehaviours, editor) {
      return Button.sketch({
        dom: getToolbarIconButton(clazz, editor),
        action: action,
        buttonBehaviours: deepMerge(derive$2([Unselecting.config({})]), extraBehaviours)
      });
    };

    var labelPart = optional({
      schema: [required$1('dom')],
      name: 'label'
    });
    var edgePart = function (name) {
      return optional({
        name: '' + name + '-edge',
        overrides: function (detail) {
          var action = detail.model.manager.edgeActions[name];
          return action.fold(function () {
            return {};
          }, function (a) {
            return {
              events: derive$3([
                runActionExtra(touchstart(), function (comp, se, d) {
                  return a(comp, d);
                }, [detail]),
                runActionExtra(mousedown(), function (comp, se, d) {
                  return a(comp, d);
                }, [detail]),
                runActionExtra(mousemove(), function (comp, se, det) {
                  if (det.mouseIsDown.get()) {
                    a(comp, det);
                  }
                }, [detail])
              ])
            };
          });
        }
      });
    };
    var tlEdgePart = edgePart('top-left');
    var tedgePart = edgePart('top');
    var trEdgePart = edgePart('top-right');
    var redgePart = edgePart('right');
    var brEdgePart = edgePart('bottom-right');
    var bedgePart = edgePart('bottom');
    var blEdgePart = edgePart('bottom-left');
    var ledgePart = edgePart('left');
    var thumbPart = required({
      name: 'thumb',
      defaults: constant$1({ dom: { styles: { position: 'absolute' } } }),
      overrides: function (detail) {
        return {
          events: derive$3([
            redirectToPart(touchstart(), detail, 'spectrum'),
            redirectToPart(touchmove(), detail, 'spectrum'),
            redirectToPart(touchend(), detail, 'spectrum'),
            redirectToPart(mousedown(), detail, 'spectrum'),
            redirectToPart(mousemove(), detail, 'spectrum'),
            redirectToPart(mouseup(), detail, 'spectrum')
          ])
        };
      }
    });
    var spectrumPart = required({
      schema: [customField('mouseIsDown', function () {
          return Cell(false);
        })],
      name: 'spectrum',
      overrides: function (detail) {
        var modelDetail = detail.model;
        var model = modelDetail.manager;
        var setValueFrom = function (component, simulatedEvent) {
          return model.getValueFromEvent(simulatedEvent).map(function (value) {
            return model.setValueFrom(component, detail, value);
          });
        };
        return {
          behaviours: derive$2([
            Keying.config({
              mode: 'special',
              onLeft: function (spectrum) {
                return model.onLeft(spectrum, detail);
              },
              onRight: function (spectrum) {
                return model.onRight(spectrum, detail);
              },
              onUp: function (spectrum) {
                return model.onUp(spectrum, detail);
              },
              onDown: function (spectrum) {
                return model.onDown(spectrum, detail);
              }
            }),
            Focusing.config({})
          ]),
          events: derive$3([
            run(touchstart(), setValueFrom),
            run(touchmove(), setValueFrom),
            run(mousedown(), setValueFrom),
            run(mousemove(), function (spectrum, se) {
              if (detail.mouseIsDown.get()) {
                setValueFrom(spectrum, se);
              }
            })
          ])
        };
      }
    });
    var SliderParts = [
      labelPart,
      ledgePart,
      redgePart,
      tedgePart,
      bedgePart,
      tlEdgePart,
      trEdgePart,
      blEdgePart,
      brEdgePart,
      thumbPart,
      spectrumPart
    ];

    var onLoad$4 = function (component, repConfig, repState) {
      repConfig.store.manager.onLoad(component, repConfig, repState);
    };
    var onUnload$2 = function (component, repConfig, repState) {
      repConfig.store.manager.onUnload(component, repConfig, repState);
    };
    var setValue$3 = function (component, repConfig, repState, data) {
      repConfig.store.manager.setValue(component, repConfig, repState, data);
    };
    var getValue$4 = function (component, repConfig, repState) {
      return repConfig.store.manager.getValue(component, repConfig, repState);
    };
    var getState$1 = function (component, repConfig, repState) {
      return repState;
    };

    var RepresentApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        onLoad: onLoad$4,
        onUnload: onUnload$2,
        setValue: setValue$3,
        getValue: getValue$4,
        getState: getState$1
    });

    var events$5 = function (repConfig, repState) {
      var es = repConfig.resetOnDom ? [
        runOnAttached(function (comp, _se) {
          onLoad$4(comp, repConfig, repState);
        }),
        runOnDetached(function (comp, _se) {
          onUnload$2(comp, repConfig, repState);
        })
      ] : [loadEvent(repConfig, repState, onLoad$4)];
      return derive$3(es);
    };

    var ActiveRepresenting = /*#__PURE__*/Object.freeze({
        __proto__: null,
        events: events$5
    });

    var memory = function () {
      var data = Cell(null);
      var readState = function () {
        return {
          mode: 'memory',
          value: data.get()
        };
      };
      var isNotSet = function () {
        return data.get() === null;
      };
      var clear = function () {
        data.set(null);
      };
      return nu$2({
        set: data.set,
        get: data.get,
        isNotSet: isNotSet,
        clear: clear,
        readState: readState
      });
    };
    var manual = function () {
      var readState = noop;
      return nu$2({ readState: readState });
    };
    var dataset = function () {
      var dataByValue = Cell({});
      var dataByText = Cell({});
      var readState = function () {
        return {
          mode: 'dataset',
          dataByValue: dataByValue.get(),
          dataByText: dataByText.get()
        };
      };
      var clear = function () {
        dataByValue.set({});
        dataByText.set({});
      };
      var lookup = function (itemString) {
        return get$c(dataByValue.get(), itemString).orThunk(function () {
          return get$c(dataByText.get(), itemString);
        });
      };
      var update = function (items) {
        var currentDataByValue = dataByValue.get();
        var currentDataByText = dataByText.get();
        var newDataByValue = {};
        var newDataByText = {};
        each$1(items, function (item) {
          newDataByValue[item.value] = item;
          get$c(item, 'meta').each(function (meta) {
            get$c(meta, 'text').each(function (text) {
              newDataByText[text] = item;
            });
          });
        });
        dataByValue.set(__assign(__assign({}, currentDataByValue), newDataByValue));
        dataByText.set(__assign(__assign({}, currentDataByText), newDataByText));
      };
      return nu$2({
        readState: readState,
        lookup: lookup,
        update: update,
        clear: clear
      });
    };
    var init$4 = function (spec) {
      return spec.store.manager.state(spec);
    };

    var RepresentState = /*#__PURE__*/Object.freeze({
        __proto__: null,
        memory: memory,
        dataset: dataset,
        manual: manual,
        init: init$4
    });

    var setValue$2 = function (component, repConfig, repState, data) {
      var store = repConfig.store;
      repState.update([data]);
      store.setValue(component, data);
      repConfig.onSetValue(component, data);
    };
    var getValue$3 = function (component, repConfig, repState) {
      var store = repConfig.store;
      var key = store.getDataKey(component);
      return repState.lookup(key).getOrThunk(function () {
        return store.getFallbackEntry(key);
      });
    };
    var onLoad$3 = function (component, repConfig, repState) {
      var store = repConfig.store;
      store.initialValue.each(function (data) {
        setValue$2(component, repConfig, repState, data);
      });
    };
    var onUnload$1 = function (component, repConfig, repState) {
      repState.clear();
    };
    var DatasetStore = [
      option('initialValue'),
      required$1('getFallbackEntry'),
      required$1('getDataKey'),
      required$1('setValue'),
      output('manager', {
        setValue: setValue$2,
        getValue: getValue$3,
        onLoad: onLoad$3,
        onUnload: onUnload$1,
        state: dataset
      })
    ];

    var getValue$2 = function (component, repConfig, _repState) {
      return repConfig.store.getValue(component);
    };
    var setValue$1 = function (component, repConfig, _repState, data) {
      repConfig.store.setValue(component, data);
      repConfig.onSetValue(component, data);
    };
    var onLoad$2 = function (component, repConfig, _repState) {
      repConfig.store.initialValue.each(function (data) {
        repConfig.store.setValue(component, data);
      });
    };
    var ManualStore = [
      required$1('getValue'),
      defaulted('setValue', noop),
      option('initialValue'),
      output('manager', {
        setValue: setValue$1,
        getValue: getValue$2,
        onLoad: onLoad$2,
        onUnload: noop,
        state: NoState.init
      })
    ];

    var setValue = function (component, repConfig, repState, data) {
      repState.set(data);
      repConfig.onSetValue(component, data);
    };
    var getValue$1 = function (component, repConfig, repState) {
      return repState.get();
    };
    var onLoad$1 = function (component, repConfig, repState) {
      repConfig.store.initialValue.each(function (initVal) {
        if (repState.isNotSet()) {
          repState.set(initVal);
        }
      });
    };
    var onUnload = function (component, repConfig, repState) {
      repState.clear();
    };
    var MemoryStore = [
      option('initialValue'),
      output('manager', {
        setValue: setValue,
        getValue: getValue$1,
        onLoad: onLoad$1,
        onUnload: onUnload,
        state: memory
      })
    ];

    var RepresentSchema = [
      defaultedOf('store', { mode: 'memory' }, choose$1('mode', {
        memory: MemoryStore,
        manual: ManualStore,
        dataset: DatasetStore
      })),
      onHandler('onSetValue'),
      defaulted('resetOnDom', false)
    ];

    var Representing = create$5({
      fields: RepresentSchema,
      name: 'representing',
      active: ActiveRepresenting,
      apis: RepresentApis,
      extra: {
        setValueFrom: function (component, source) {
          var value = Representing.getValue(source);
          Representing.setValue(component, value);
        }
      },
      state: RepresentState
    });

    var api$1 = Dimension('width', function (element) {
      return element.dom.offsetWidth;
    });
    var set$4 = function (element, h) {
      return api$1.set(element, h);
    };
    var get$5 = function (element) {
      return api$1.get(element);
    };

    var r$1 = function (left, top) {
      var translate = function (x, y) {
        return r$1(left + x, top + y);
      };
      return {
        left: left,
        top: top,
        translate: translate
      };
    };
    var SugarPosition = r$1;

    var _sliderChangeEvent = 'slider.change.value';
    var sliderChangeEvent = constant$1(_sliderChangeEvent);
    var isTouchEvent = function (evt) {
      return evt.type.indexOf('touch') !== -1;
    };
    var getEventSource = function (simulatedEvent) {
      var evt = simulatedEvent.event.raw;
      if (isTouchEvent(evt)) {
        var touchEvent = evt;
        return touchEvent.touches !== undefined && touchEvent.touches.length === 1 ? Optional.some(touchEvent.touches[0]).map(function (t) {
          return SugarPosition(t.clientX, t.clientY);
        }) : Optional.none();
      } else {
        var mouseEvent = evt;
        return mouseEvent.clientX !== undefined ? Optional.some(mouseEvent).map(function (me) {
          return SugarPosition(me.clientX, me.clientY);
        }) : Optional.none();
      }
    };

    var t = 'top', r = 'right', b = 'bottom', l = 'left';
    var minX = function (detail) {
      return detail.model.minX;
    };
    var minY = function (detail) {
      return detail.model.minY;
    };
    var min1X = function (detail) {
      return detail.model.minX - 1;
    };
    var min1Y = function (detail) {
      return detail.model.minY - 1;
    };
    var maxX = function (detail) {
      return detail.model.maxX;
    };
    var maxY = function (detail) {
      return detail.model.maxY;
    };
    var max1X = function (detail) {
      return detail.model.maxX + 1;
    };
    var max1Y = function (detail) {
      return detail.model.maxY + 1;
    };
    var range$1 = function (detail, max, min) {
      return max(detail) - min(detail);
    };
    var xRange = function (detail) {
      return range$1(detail, maxX, minX);
    };
    var yRange = function (detail) {
      return range$1(detail, maxY, minY);
    };
    var halfX = function (detail) {
      return xRange(detail) / 2;
    };
    var halfY = function (detail) {
      return yRange(detail) / 2;
    };
    var step = function (detail) {
      return detail.stepSize;
    };
    var snap = function (detail) {
      return detail.snapToGrid;
    };
    var snapStart = function (detail) {
      return detail.snapStart;
    };
    var rounded = function (detail) {
      return detail.rounded;
    };
    var hasEdge = function (detail, edgeName) {
      return detail[edgeName + '-edge'] !== undefined;
    };
    var hasLEdge = function (detail) {
      return hasEdge(detail, l);
    };
    var hasREdge = function (detail) {
      return hasEdge(detail, r);
    };
    var hasTEdge = function (detail) {
      return hasEdge(detail, t);
    };
    var hasBEdge = function (detail) {
      return hasEdge(detail, b);
    };
    var currentValue = function (detail) {
      return detail.model.value.get();
    };

    var xValue = function (x) {
      return { x: x };
    };
    var yValue = function (y) {
      return { y: y };
    };
    var xyValue = function (x, y) {
      return {
        x: x,
        y: y
      };
    };
    var fireSliderChange$3 = function (component, value) {
      emitWith(component, sliderChangeEvent(), { value: value });
    };
    var setToTLEdgeXY = function (edge, detail) {
      fireSliderChange$3(edge, xyValue(min1X(detail), min1Y(detail)));
    };
    var setToTEdge = function (edge, detail) {
      fireSliderChange$3(edge, yValue(min1Y(detail)));
    };
    var setToTEdgeXY = function (edge, detail) {
      fireSliderChange$3(edge, xyValue(halfX(detail), min1Y(detail)));
    };
    var setToTREdgeXY = function (edge, detail) {
      fireSliderChange$3(edge, xyValue(max1X(detail), min1Y(detail)));
    };
    var setToREdge = function (edge, detail) {
      fireSliderChange$3(edge, xValue(max1X(detail)));
    };
    var setToREdgeXY = function (edge, detail) {
      fireSliderChange$3(edge, xyValue(max1X(detail), halfY(detail)));
    };
    var setToBREdgeXY = function (edge, detail) {
      fireSliderChange$3(edge, xyValue(max1X(detail), max1Y(detail)));
    };
    var setToBEdge = function (edge, detail) {
      fireSliderChange$3(edge, yValue(max1Y(detail)));
    };
    var setToBEdgeXY = function (edge, detail) {
      fireSliderChange$3(edge, xyValue(halfX(detail), max1Y(detail)));
    };
    var setToBLEdgeXY = function (edge, detail) {
      fireSliderChange$3(edge, xyValue(min1X(detail), max1Y(detail)));
    };
    var setToLEdge = function (edge, detail) {
      fireSliderChange$3(edge, xValue(min1X(detail)));
    };
    var setToLEdgeXY = function (edge, detail) {
      fireSliderChange$3(edge, xyValue(min1X(detail), halfY(detail)));
    };

    var reduceBy = function (value, min, max, step) {
      if (value < min) {
        return value;
      } else if (value > max) {
        return max;
      } else if (value === min) {
        return min - 1;
      } else {
        return Math.max(min, value - step);
      }
    };
    var increaseBy = function (value, min, max, step) {
      if (value > max) {
        return value;
      } else if (value < min) {
        return min;
      } else if (value === max) {
        return max + 1;
      } else {
        return Math.min(max, value + step);
      }
    };
    var capValue = function (value, min, max) {
      return Math.max(min, Math.min(max, value));
    };
    var snapValueOf = function (value, min, max, step, snapStart) {
      return snapStart.fold(function () {
        var initValue = value - min;
        var extraValue = Math.round(initValue / step) * step;
        return capValue(min + extraValue, min - 1, max + 1);
      }, function (start) {
        var remainder = (value - start) % step;
        var adjustment = Math.round(remainder / step);
        var rawSteps = Math.floor((value - start) / step);
        var maxSteps = Math.floor((max - start) / step);
        var numSteps = Math.min(maxSteps, rawSteps + adjustment);
        var r = start + numSteps * step;
        return Math.max(start, r);
      });
    };
    var findOffsetOf = function (value, min, max) {
      return Math.min(max, Math.max(value, min)) - min;
    };
    var findValueOf = function (args) {
      var min = args.min, max = args.max, range = args.range, value = args.value, step = args.step, snap = args.snap, snapStart = args.snapStart, rounded = args.rounded, hasMinEdge = args.hasMinEdge, hasMaxEdge = args.hasMaxEdge, minBound = args.minBound, maxBound = args.maxBound, screenRange = args.screenRange;
      var capMin = hasMinEdge ? min - 1 : min;
      var capMax = hasMaxEdge ? max + 1 : max;
      if (value < minBound) {
        return capMin;
      } else if (value > maxBound) {
        return capMax;
      } else {
        var offset = findOffsetOf(value, minBound, maxBound);
        var newValue = capValue(offset / screenRange * range + min, capMin, capMax);
        if (snap && newValue >= min && newValue <= max) {
          return snapValueOf(newValue, min, max, step, snapStart);
        } else if (rounded) {
          return Math.round(newValue);
        } else {
          return newValue;
        }
      }
    };
    var findOffsetOfValue$2 = function (args) {
      var min = args.min, max = args.max, range = args.range, value = args.value, hasMinEdge = args.hasMinEdge, hasMaxEdge = args.hasMaxEdge, maxBound = args.maxBound, maxOffset = args.maxOffset, centerMinEdge = args.centerMinEdge, centerMaxEdge = args.centerMaxEdge;
      if (value < min) {
        return hasMinEdge ? 0 : centerMinEdge;
      } else if (value > max) {
        return hasMaxEdge ? maxBound : centerMaxEdge;
      } else {
        return (value - min) / range * maxOffset;
      }
    };

    var top = 'top', right = 'right', bottom = 'bottom', left = 'left', width = 'width', height = 'height';
    var getBounds$1 = function (component) {
      return component.element.dom.getBoundingClientRect();
    };
    var getBoundsProperty = function (bounds, property) {
      return bounds[property];
    };
    var getMinXBounds = function (component) {
      var bounds = getBounds$1(component);
      return getBoundsProperty(bounds, left);
    };
    var getMaxXBounds = function (component) {
      var bounds = getBounds$1(component);
      return getBoundsProperty(bounds, right);
    };
    var getMinYBounds = function (component) {
      var bounds = getBounds$1(component);
      return getBoundsProperty(bounds, top);
    };
    var getMaxYBounds = function (component) {
      var bounds = getBounds$1(component);
      return getBoundsProperty(bounds, bottom);
    };
    var getXScreenRange = function (component) {
      var bounds = getBounds$1(component);
      return getBoundsProperty(bounds, width);
    };
    var getYScreenRange = function (component) {
      var bounds = getBounds$1(component);
      return getBoundsProperty(bounds, height);
    };
    var getCenterOffsetOf = function (componentMinEdge, componentMaxEdge, spectrumMinEdge) {
      return (componentMinEdge + componentMaxEdge) / 2 - spectrumMinEdge;
    };
    var getXCenterOffSetOf = function (component, spectrum) {
      var componentBounds = getBounds$1(component);
      var spectrumBounds = getBounds$1(spectrum);
      var componentMinEdge = getBoundsProperty(componentBounds, left);
      var componentMaxEdge = getBoundsProperty(componentBounds, right);
      var spectrumMinEdge = getBoundsProperty(spectrumBounds, left);
      return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
    };
    var getYCenterOffSetOf = function (component, spectrum) {
      var componentBounds = getBounds$1(component);
      var spectrumBounds = getBounds$1(spectrum);
      var componentMinEdge = getBoundsProperty(componentBounds, top);
      var componentMaxEdge = getBoundsProperty(componentBounds, bottom);
      var spectrumMinEdge = getBoundsProperty(spectrumBounds, top);
      return getCenterOffsetOf(componentMinEdge, componentMaxEdge, spectrumMinEdge);
    };

    var fireSliderChange$2 = function (spectrum, value) {
      emitWith(spectrum, sliderChangeEvent(), { value: value });
    };
    var sliderValue$2 = function (x) {
      return { x: x };
    };
    var findValueOfOffset$1 = function (spectrum, detail, left) {
      var args = {
        min: minX(detail),
        max: maxX(detail),
        range: xRange(detail),
        value: left,
        step: step(detail),
        snap: snap(detail),
        snapStart: snapStart(detail),
        rounded: rounded(detail),
        hasMinEdge: hasLEdge(detail),
        hasMaxEdge: hasREdge(detail),
        minBound: getMinXBounds(spectrum),
        maxBound: getMaxXBounds(spectrum),
        screenRange: getXScreenRange(spectrum)
      };
      return findValueOf(args);
    };
    var setValueFrom$2 = function (spectrum, detail, value) {
      var xValue = findValueOfOffset$1(spectrum, detail, value);
      var sliderVal = sliderValue$2(xValue);
      fireSliderChange$2(spectrum, sliderVal);
      return xValue;
    };
    var setToMin$2 = function (spectrum, detail) {
      var min = minX(detail);
      fireSliderChange$2(spectrum, sliderValue$2(min));
    };
    var setToMax$2 = function (spectrum, detail) {
      var max = maxX(detail);
      fireSliderChange$2(spectrum, sliderValue$2(max));
    };
    var moveBy$2 = function (direction, spectrum, detail) {
      var f = direction > 0 ? increaseBy : reduceBy;
      var xValue = f(currentValue(detail).x, minX(detail), maxX(detail), step(detail));
      fireSliderChange$2(spectrum, sliderValue$2(xValue));
      return Optional.some(xValue);
    };
    var handleMovement$2 = function (direction) {
      return function (spectrum, detail) {
        return moveBy$2(direction, spectrum, detail).map(always);
      };
    };
    var getValueFromEvent$2 = function (simulatedEvent) {
      var pos = getEventSource(simulatedEvent);
      return pos.map(function (p) {
        return p.left;
      });
    };
    var findOffsetOfValue$1 = function (spectrum, detail, value, minEdge, maxEdge) {
      var minOffset = 0;
      var maxOffset = getXScreenRange(spectrum);
      var centerMinEdge = minEdge.bind(function (edge) {
        return Optional.some(getXCenterOffSetOf(edge, spectrum));
      }).getOr(minOffset);
      var centerMaxEdge = maxEdge.bind(function (edge) {
        return Optional.some(getXCenterOffSetOf(edge, spectrum));
      }).getOr(maxOffset);
      var args = {
        min: minX(detail),
        max: maxX(detail),
        range: xRange(detail),
        value: value,
        hasMinEdge: hasLEdge(detail),
        hasMaxEdge: hasREdge(detail),
        minBound: getMinXBounds(spectrum),
        minOffset: minOffset,
        maxBound: getMaxXBounds(spectrum),
        maxOffset: maxOffset,
        centerMinEdge: centerMinEdge,
        centerMaxEdge: centerMaxEdge
      };
      return findOffsetOfValue$2(args);
    };
    var findPositionOfValue$1 = function (slider, spectrum, value, minEdge, maxEdge, detail) {
      var offset = findOffsetOfValue$1(spectrum, detail, value, minEdge, maxEdge);
      return getMinXBounds(spectrum) - getMinXBounds(slider) + offset;
    };
    var setPositionFromValue$2 = function (slider, thumb, detail, edges) {
      var value = currentValue(detail);
      var pos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value.x, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
      var thumbRadius = get$5(thumb.element) / 2;
      set$5(thumb.element, 'left', pos - thumbRadius + 'px');
    };
    var onLeft$2 = handleMovement$2(-1);
    var onRight$2 = handleMovement$2(1);
    var onUp$2 = Optional.none;
    var onDown$2 = Optional.none;
    var edgeActions$2 = {
      'top-left': Optional.none(),
      'top': Optional.none(),
      'top-right': Optional.none(),
      'right': Optional.some(setToREdge),
      'bottom-right': Optional.none(),
      'bottom': Optional.none(),
      'bottom-left': Optional.none(),
      'left': Optional.some(setToLEdge)
    };

    var HorizontalModel = /*#__PURE__*/Object.freeze({
        __proto__: null,
        setValueFrom: setValueFrom$2,
        setToMin: setToMin$2,
        setToMax: setToMax$2,
        findValueOfOffset: findValueOfOffset$1,
        getValueFromEvent: getValueFromEvent$2,
        findPositionOfValue: findPositionOfValue$1,
        setPositionFromValue: setPositionFromValue$2,
        onLeft: onLeft$2,
        onRight: onRight$2,
        onUp: onUp$2,
        onDown: onDown$2,
        edgeActions: edgeActions$2
    });

    var fireSliderChange$1 = function (spectrum, value) {
      emitWith(spectrum, sliderChangeEvent(), { value: value });
    };
    var sliderValue$1 = function (y) {
      return { y: y };
    };
    var findValueOfOffset = function (spectrum, detail, top) {
      var args = {
        min: minY(detail),
        max: maxY(detail),
        range: yRange(detail),
        value: top,
        step: step(detail),
        snap: snap(detail),
        snapStart: snapStart(detail),
        rounded: rounded(detail),
        hasMinEdge: hasTEdge(detail),
        hasMaxEdge: hasBEdge(detail),
        minBound: getMinYBounds(spectrum),
        maxBound: getMaxYBounds(spectrum),
        screenRange: getYScreenRange(spectrum)
      };
      return findValueOf(args);
    };
    var setValueFrom$1 = function (spectrum, detail, value) {
      var yValue = findValueOfOffset(spectrum, detail, value);
      var sliderVal = sliderValue$1(yValue);
      fireSliderChange$1(spectrum, sliderVal);
      return yValue;
    };
    var setToMin$1 = function (spectrum, detail) {
      var min = minY(detail);
      fireSliderChange$1(spectrum, sliderValue$1(min));
    };
    var setToMax$1 = function (spectrum, detail) {
      var max = maxY(detail);
      fireSliderChange$1(spectrum, sliderValue$1(max));
    };
    var moveBy$1 = function (direction, spectrum, detail) {
      var f = direction > 0 ? increaseBy : reduceBy;
      var yValue = f(currentValue(detail).y, minY(detail), maxY(detail), step(detail));
      fireSliderChange$1(spectrum, sliderValue$1(yValue));
      return Optional.some(yValue);
    };
    var handleMovement$1 = function (direction) {
      return function (spectrum, detail) {
        return moveBy$1(direction, spectrum, detail).map(always);
      };
    };
    var getValueFromEvent$1 = function (simulatedEvent) {
      var pos = getEventSource(simulatedEvent);
      return pos.map(function (p) {
        return p.top;
      });
    };
    var findOffsetOfValue = function (spectrum, detail, value, minEdge, maxEdge) {
      var minOffset = 0;
      var maxOffset = getYScreenRange(spectrum);
      var centerMinEdge = minEdge.bind(function (edge) {
        return Optional.some(getYCenterOffSetOf(edge, spectrum));
      }).getOr(minOffset);
      var centerMaxEdge = maxEdge.bind(function (edge) {
        return Optional.some(getYCenterOffSetOf(edge, spectrum));
      }).getOr(maxOffset);
      var args = {
        min: minY(detail),
        max: maxY(detail),
        range: yRange(detail),
        value: value,
        hasMinEdge: hasTEdge(detail),
        hasMaxEdge: hasBEdge(detail),
        minBound: getMinYBounds(spectrum),
        minOffset: minOffset,
        maxBound: getMaxYBounds(spectrum),
        maxOffset: maxOffset,
        centerMinEdge: centerMinEdge,
        centerMaxEdge: centerMaxEdge
      };
      return findOffsetOfValue$2(args);
    };
    var findPositionOfValue = function (slider, spectrum, value, minEdge, maxEdge, detail) {
      var offset = findOffsetOfValue(spectrum, detail, value, minEdge, maxEdge);
      return getMinYBounds(spectrum) - getMinYBounds(slider) + offset;
    };
    var setPositionFromValue$1 = function (slider, thumb, detail, edges) {
      var value = currentValue(detail);
      var pos = findPositionOfValue(slider, edges.getSpectrum(slider), value.y, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
      var thumbRadius = get$7(thumb.element) / 2;
      set$5(thumb.element, 'top', pos - thumbRadius + 'px');
    };
    var onLeft$1 = Optional.none;
    var onRight$1 = Optional.none;
    var onUp$1 = handleMovement$1(-1);
    var onDown$1 = handleMovement$1(1);
    var edgeActions$1 = {
      'top-left': Optional.none(),
      'top': Optional.some(setToTEdge),
      'top-right': Optional.none(),
      'right': Optional.none(),
      'bottom-right': Optional.none(),
      'bottom': Optional.some(setToBEdge),
      'bottom-left': Optional.none(),
      'left': Optional.none()
    };

    var VerticalModel = /*#__PURE__*/Object.freeze({
        __proto__: null,
        setValueFrom: setValueFrom$1,
        setToMin: setToMin$1,
        setToMax: setToMax$1,
        findValueOfOffset: findValueOfOffset,
        getValueFromEvent: getValueFromEvent$1,
        findPositionOfValue: findPositionOfValue,
        setPositionFromValue: setPositionFromValue$1,
        onLeft: onLeft$1,
        onRight: onRight$1,
        onUp: onUp$1,
        onDown: onDown$1,
        edgeActions: edgeActions$1
    });

    var fireSliderChange = function (spectrum, value) {
      emitWith(spectrum, sliderChangeEvent(), { value: value });
    };
    var sliderValue = function (x, y) {
      return {
        x: x,
        y: y
      };
    };
    var setValueFrom = function (spectrum, detail, value) {
      var xValue = findValueOfOffset$1(spectrum, detail, value.left);
      var yValue = findValueOfOffset(spectrum, detail, value.top);
      var val = sliderValue(xValue, yValue);
      fireSliderChange(spectrum, val);
      return val;
    };
    var moveBy = function (direction, isVerticalMovement, spectrum, detail) {
      var f = direction > 0 ? increaseBy : reduceBy;
      var xValue = isVerticalMovement ? currentValue(detail).x : f(currentValue(detail).x, minX(detail), maxX(detail), step(detail));
      var yValue = !isVerticalMovement ? currentValue(detail).y : f(currentValue(detail).y, minY(detail), maxY(detail), step(detail));
      fireSliderChange(spectrum, sliderValue(xValue, yValue));
      return Optional.some(xValue);
    };
    var handleMovement = function (direction, isVerticalMovement) {
      return function (spectrum, detail) {
        return moveBy(direction, isVerticalMovement, spectrum, detail).map(always);
      };
    };
    var setToMin = function (spectrum, detail) {
      var mX = minX(detail);
      var mY = minY(detail);
      fireSliderChange(spectrum, sliderValue(mX, mY));
    };
    var setToMax = function (spectrum, detail) {
      var mX = maxX(detail);
      var mY = maxY(detail);
      fireSliderChange(spectrum, sliderValue(mX, mY));
    };
    var getValueFromEvent = function (simulatedEvent) {
      return getEventSource(simulatedEvent);
    };
    var setPositionFromValue = function (slider, thumb, detail, edges) {
      var value = currentValue(detail);
      var xPos = findPositionOfValue$1(slider, edges.getSpectrum(slider), value.x, edges.getLeftEdge(slider), edges.getRightEdge(slider), detail);
      var yPos = findPositionOfValue(slider, edges.getSpectrum(slider), value.y, edges.getTopEdge(slider), edges.getBottomEdge(slider), detail);
      var thumbXRadius = get$5(thumb.element) / 2;
      var thumbYRadius = get$7(thumb.element) / 2;
      set$5(thumb.element, 'left', xPos - thumbXRadius + 'px');
      set$5(thumb.element, 'top', yPos - thumbYRadius + 'px');
    };
    var onLeft = handleMovement(-1, false);
    var onRight = handleMovement(1, false);
    var onUp = handleMovement(-1, true);
    var onDown = handleMovement(1, true);
    var edgeActions = {
      'top-left': Optional.some(setToTLEdgeXY),
      'top': Optional.some(setToTEdgeXY),
      'top-right': Optional.some(setToTREdgeXY),
      'right': Optional.some(setToREdgeXY),
      'bottom-right': Optional.some(setToBREdgeXY),
      'bottom': Optional.some(setToBEdgeXY),
      'bottom-left': Optional.some(setToBLEdgeXY),
      'left': Optional.some(setToLEdgeXY)
    };

    var TwoDModel = /*#__PURE__*/Object.freeze({
        __proto__: null,
        setValueFrom: setValueFrom,
        setToMin: setToMin,
        setToMax: setToMax,
        getValueFromEvent: getValueFromEvent,
        setPositionFromValue: setPositionFromValue,
        onLeft: onLeft,
        onRight: onRight,
        onUp: onUp,
        onDown: onDown,
        edgeActions: edgeActions
    });

    var SliderSchema = [
      defaulted('stepSize', 1),
      defaulted('onChange', noop),
      defaulted('onChoose', noop),
      defaulted('onInit', noop),
      defaulted('onDragStart', noop),
      defaulted('onDragEnd', noop),
      defaulted('snapToGrid', false),
      defaulted('rounded', true),
      option('snapStart'),
      requiredOf('model', choose$1('mode', {
        x: [
          defaulted('minX', 0),
          defaulted('maxX', 100),
          customField('value', function (spec) {
            return Cell(spec.mode.minX);
          }),
          required$1('getInitialValue'),
          output('manager', HorizontalModel)
        ],
        y: [
          defaulted('minY', 0),
          defaulted('maxY', 100),
          customField('value', function (spec) {
            return Cell(spec.mode.minY);
          }),
          required$1('getInitialValue'),
          output('manager', VerticalModel)
        ],
        xy: [
          defaulted('minX', 0),
          defaulted('maxX', 100),
          defaulted('minY', 0),
          defaulted('maxY', 100),
          customField('value', function (spec) {
            return Cell({
              x: spec.mode.minX,
              y: spec.mode.minY
            });
          }),
          required$1('getInitialValue'),
          output('manager', TwoDModel)
        ]
      })),
      field$1('sliderBehaviours', [
        Keying,
        Representing
      ]),
      customField('mouseIsDown', function () {
        return Cell(false);
      })
    ];

    var mouseReleased = constant$1('mouse.released');

    var sketch$9 = function (detail, components, _spec, _externals) {
      var _a;
      var getThumb = function (component) {
        return getPartOrDie(component, detail, 'thumb');
      };
      var getSpectrum = function (component) {
        return getPartOrDie(component, detail, 'spectrum');
      };
      var getLeftEdge = function (component) {
        return getPart(component, detail, 'left-edge');
      };
      var getRightEdge = function (component) {
        return getPart(component, detail, 'right-edge');
      };
      var getTopEdge = function (component) {
        return getPart(component, detail, 'top-edge');
      };
      var getBottomEdge = function (component) {
        return getPart(component, detail, 'bottom-edge');
      };
      var modelDetail = detail.model;
      var model = modelDetail.manager;
      var refresh = function (slider, thumb) {
        model.setPositionFromValue(slider, thumb, detail, {
          getLeftEdge: getLeftEdge,
          getRightEdge: getRightEdge,
          getTopEdge: getTopEdge,
          getBottomEdge: getBottomEdge,
          getSpectrum: getSpectrum
        });
      };
      var setValue = function (slider, newValue) {
        modelDetail.value.set(newValue);
        var thumb = getThumb(slider);
        refresh(slider, thumb);
      };
      var changeValue = function (slider, newValue) {
        setValue(slider, newValue);
        var thumb = getThumb(slider);
        detail.onChange(slider, thumb, newValue);
        return Optional.some(true);
      };
      var resetToMin = function (slider) {
        model.setToMin(slider, detail);
      };
      var resetToMax = function (slider) {
        model.setToMax(slider, detail);
      };
      var choose = function (slider) {
        var fireOnChoose = function () {
          getPart(slider, detail, 'thumb').each(function (thumb) {
            var value = modelDetail.value.get();
            detail.onChoose(slider, thumb, value);
          });
        };
        var wasDown = detail.mouseIsDown.get();
        detail.mouseIsDown.set(false);
        if (wasDown) {
          fireOnChoose();
        }
      };
      var onDragStart = function (slider, simulatedEvent) {
        simulatedEvent.stop();
        detail.mouseIsDown.set(true);
        detail.onDragStart(slider, getThumb(slider));
      };
      var onDragEnd = function (slider, simulatedEvent) {
        simulatedEvent.stop();
        detail.onDragEnd(slider, getThumb(slider));
        choose(slider);
      };
      return {
        uid: detail.uid,
        dom: detail.dom,
        components: components,
        behaviours: augment(detail.sliderBehaviours, [
          Keying.config({
            mode: 'special',
            focusIn: function (slider) {
              return getPart(slider, detail, 'spectrum').map(Keying.focusIn).map(always);
            }
          }),
          Representing.config({
            store: {
              mode: 'manual',
              getValue: function (_) {
                return modelDetail.value.get();
              }
            }
          }),
          Receiving.config({ channels: (_a = {}, _a[mouseReleased()] = { onReceive: choose }, _a) })
        ]),
        events: derive$3([
          run(sliderChangeEvent(), function (slider, simulatedEvent) {
            changeValue(slider, simulatedEvent.event.value);
          }),
          runOnAttached(function (slider, _simulatedEvent) {
            var getInitial = modelDetail.getInitialValue();
            modelDetail.value.set(getInitial);
            var thumb = getThumb(slider);
            refresh(slider, thumb);
            var spectrum = getSpectrum(slider);
            detail.onInit(slider, thumb, spectrum, modelDetail.value.get());
          }),
          run(touchstart(), onDragStart),
          run(touchend(), onDragEnd),
          run(mousedown(), onDragStart),
          run(mouseup(), onDragEnd)
        ]),
        apis: {
          resetToMin: resetToMin,
          resetToMax: resetToMax,
          setValue: setValue,
          refresh: refresh
        },
        domModification: { styles: { position: 'relative' } }
      };
    };

    var Slider = composite({
      name: 'Slider',
      configFields: SliderSchema,
      partFields: SliderParts,
      factory: sketch$9,
      apis: {
        setValue: function (apis, slider, value) {
          apis.setValue(slider, value);
        },
        resetToMin: function (apis, slider) {
          apis.resetToMin(slider);
        },
        resetToMax: function (apis, slider) {
          apis.resetToMax(slider);
        },
        refresh: function (apis, slider) {
          apis.refresh(slider);
        }
      }
    });

    var button = function (realm, clazz, makeItems, editor) {
      return forToolbar(clazz, function () {
        var items = makeItems();
        realm.setContextToolbar([{
            label: clazz + ' group',
            items: items
          }]);
      }, {}, editor);
    };

    var BLACK = -1;
    var makeSlider$1 = function (spec$1) {
      var getColor = function (hue) {
        if (hue < 0) {
          return 'black';
        } else if (hue > 360) {
          return 'white';
        } else {
          return 'hsl(' + hue + ', 100%, 50%)';
        }
      };
      var onInit = function (slider, thumb, spectrum, value) {
        var color = getColor(value.x());
        set$5(thumb.element, 'background-color', color);
      };
      var onChange = function (slider, thumb, value) {
        var color = getColor(value.x());
        set$5(thumb.element, 'background-color', color);
        spec$1.onChange(slider, thumb, color);
      };
      return Slider.sketch({
        dom: dom$1('<div class="${prefix}-slider ${prefix}-hue-slider-container"></div>'),
        components: [
          Slider.parts['left-edge'](spec('<div class="${prefix}-hue-slider-black"></div>')),
          Slider.parts.spectrum({
            dom: dom$1('<div class="${prefix}-slider-gradient-container"></div>'),
            components: [spec('<div class="${prefix}-slider-gradient"></div>')],
            behaviours: derive$2([Toggling.config({ toggleClass: resolve('thumb-active') })])
          }),
          Slider.parts['right-edge'](spec('<div class="${prefix}-hue-slider-white"></div>')),
          Slider.parts.thumb({
            dom: dom$1('<div class="${prefix}-slider-thumb"></div>'),
            behaviours: derive$2([Toggling.config({ toggleClass: resolve('thumb-active') })])
          })
        ],
        onChange: onChange,
        onDragStart: function (slider, thumb) {
          Toggling.on(thumb);
        },
        onDragEnd: function (slider, thumb) {
          Toggling.off(thumb);
        },
        onInit: onInit,
        stepSize: 10,
        model: {
          mode: 'x',
          minX: 0,
          maxX: 360,
          getInitialValue: function () {
            return { x: spec$1.getInitialValue() };
          }
        },
        sliderBehaviours: derive$2([orientation(Slider.refresh)])
      });
    };
    var makeItems$1 = function (spec) {
      return [makeSlider$1(spec)];
    };
    var sketch$8 = function (realm, editor) {
      var spec = {
        onChange: function (slider, thumb, color) {
          editor.undoManager.transact(function () {
            editor.formatter.apply('forecolor', { value: color });
            editor.nodeChanged();
          });
        },
        getInitialValue: constant$1(BLACK)
      };
      return button(realm, 'color-levels', function () {
        return makeItems$1(spec);
      }, editor);
    };

    var candidatesArray = [
      '9px',
      '10px',
      '11px',
      '12px',
      '14px',
      '16px',
      '18px',
      '20px',
      '24px',
      '32px',
      '36px'
    ];
    var defaultSize = 'medium';
    var defaultIndex = 2;
    var indexToSize = function (index) {
      return Optional.from(candidatesArray[index]);
    };
    var sizeToIndex = function (size) {
      return findIndex$1(candidatesArray, function (v) {
        return v === size;
      });
    };
    var getRawOrComputed = function (isRoot, rawStart) {
      var optStart = isElement(rawStart) ? Optional.some(rawStart) : parent(rawStart).filter(isElement);
      return optStart.map(function (start) {
        var inline = closest$2(start, function (elem) {
          return getRaw(elem, 'font-size').isSome();
        }, isRoot).bind(function (elem) {
          return getRaw(elem, 'font-size');
        });
        return inline.getOrThunk(function () {
          return get$8(start, 'font-size');
        });
      }).getOr('');
    };
    var getSize = function (editor) {
      var node = editor.selection.getStart();
      var elem = SugarElement.fromDom(node);
      var root = SugarElement.fromDom(editor.getBody());
      var isRoot = function (e) {
        return eq(root, e);
      };
      var elemSize = getRawOrComputed(isRoot, elem);
      return find$2(candidatesArray, function (size) {
        return elemSize === size;
      }).getOr(defaultSize);
    };
    var applySize = function (editor, value) {
      var currentValue = getSize(editor);
      if (currentValue !== value) {
        editor.execCommand('fontSize', false, value);
      }
    };
    var get$4 = function (editor) {
      var size = getSize(editor);
      return sizeToIndex(size).getOr(defaultIndex);
    };
    var apply = function (editor, index) {
      indexToSize(index).each(function (size) {
        applySize(editor, size);
      });
    };
    var candidates = constant$1(candidatesArray);

    var schema$9 = objOfOnly([
      required$1('getInitialValue'),
      required$1('onChange'),
      required$1('category'),
      required$1('sizes')
    ]);
    var sketch$7 = function (rawSpec) {
      var spec$1 = asRawOrDie$1('SizeSlider', schema$9, rawSpec);
      var isValidValue = function (valueIndex) {
        return valueIndex >= 0 && valueIndex < spec$1.sizes.length;
      };
      var onChange = function (slider, thumb, valueIndex) {
        var index = valueIndex.x();
        if (isValidValue(index)) {
          spec$1.onChange(index);
        }
      };
      return Slider.sketch({
        dom: {
          tag: 'div',
          classes: [
            resolve('slider-' + spec$1.category + '-size-container'),
            resolve('slider'),
            resolve('slider-size-container')
          ]
        },
        onChange: onChange,
        onDragStart: function (slider, thumb) {
          Toggling.on(thumb);
        },
        onDragEnd: function (slider, thumb) {
          Toggling.off(thumb);
        },
        model: {
          mode: 'x',
          minX: 0,
          maxX: spec$1.sizes.length - 1,
          getInitialValue: function () {
            return { x: spec$1.getInitialValue() };
          }
        },
        stepSize: 1,
        snapToGrid: true,
        sliderBehaviours: derive$2([orientation(Slider.refresh)]),
        components: [
          Slider.parts.spectrum({
            dom: dom$1('<div class="${prefix}-slider-size-container"></div>'),
            components: [spec('<div class="${prefix}-slider-size-line"></div>')]
          }),
          Slider.parts.thumb({
            dom: dom$1('<div class="${prefix}-slider-thumb"></div>'),
            behaviours: derive$2([Toggling.config({ toggleClass: resolve('thumb-active') })])
          })
        ]
      });
    };

    var sizes = candidates();
    var makeSlider = function (spec) {
      return sketch$7({
        onChange: spec.onChange,
        sizes: sizes,
        category: 'font',
        getInitialValue: spec.getInitialValue
      });
    };
    var makeItems = function (spec$1) {
      return [
        spec('<span class="${prefix}-toolbar-button ${prefix}-icon-small-font ${prefix}-icon"></span>'),
        makeSlider(spec$1),
        spec('<span class="${prefix}-toolbar-button ${prefix}-icon-large-font ${prefix}-icon"></span>')
      ];
    };
    var sketch$6 = function (realm, editor) {
      var spec = {
        onChange: function (value) {
          apply(editor, value);
        },
        getInitialValue: function () {
          return get$4(editor);
        }
      };
      return button(realm, 'font-size', function () {
        return makeItems(spec);
      }, editor);
    };

    var record = function (spec) {
      var uid = isSketchSpec$1(spec) && hasNonNullableKey(spec, 'uid') ? spec.uid : generate$2('memento');
      var get = function (anyInSystem) {
        return anyInSystem.getSystem().getByUid(uid).getOrDie();
      };
      var getOpt = function (anyInSystem) {
        return anyInSystem.getSystem().getByUid(uid).toOptional();
      };
      var asSpec = function () {
        return __assign(__assign({}, spec), { uid: uid });
      };
      return {
        get: get,
        getOpt: getOpt,
        asSpec: asSpec
      };
    };

    var promise = function () {
      var Promise = function (fn) {
        if (typeof this !== 'object') {
          throw new TypeError('Promises must be constructed via new');
        }
        if (typeof fn !== 'function') {
          throw new TypeError('not a function');
        }
        this._state = null;
        this._value = null;
        this._deferreds = [];
        doResolve(fn, bind(resolve, this), bind(reject, this));
      };
      var anyWindow = window;
      var asap = Promise.immediateFn || typeof anyWindow.setImmediate === 'function' && anyWindow.setImmediate || function (fn) {
        return setTimeout(fn, 1);
      };
      var bind = function (fn, thisArg) {
        return function () {
          var args = [];
          for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
          }
          return fn.apply(thisArg, args);
        };
      };
      var isArray = Array.isArray || function (value) {
        return Object.prototype.toString.call(value) === '[object Array]';
      };
      function handle(deferred) {
        var me = this;
        if (this._state === null) {
          this._deferreds.push(deferred);
          return;
        }
        asap(function () {
          var cb = me._state ? deferred.onFulfilled : deferred.onRejected;
          if (cb === null) {
            (me._state ? deferred.resolve : deferred.reject)(me._value);
            return;
          }
          var ret;
          try {
            ret = cb(me._value);
          } catch (e) {
            deferred.reject(e);
            return;
          }
          deferred.resolve(ret);
        });
      }
      function resolve(newValue) {
        try {
          if (newValue === this) {
            throw new TypeError('A promise cannot be resolved with itself.');
          }
          if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
            var then = newValue.then;
            if (typeof then === 'function') {
              doResolve(bind(then, newValue), bind(resolve, this), bind(reject, this));
              return;
            }
          }
          this._state = true;
          this._value = newValue;
          finale.call(this);
        } catch (e) {
          reject.call(this, e);
        }
      }
      function reject(newValue) {
        this._state = false;
        this._value = newValue;
        finale.call(this);
      }
      function finale() {
        for (var _i = 0, _a = this._deferreds; _i < _a.length; _i++) {
          var deferred = _a[_i];
          handle.call(this, deferred);
        }
        this._deferreds = [];
      }
      function Handler(onFulfilled, onRejected, resolve, reject) {
        this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
        this.onRejected = typeof onRejected === 'function' ? onRejected : null;
        this.resolve = resolve;
        this.reject = reject;
      }
      var doResolve = function (fn, onFulfilled, onRejected) {
        var done = false;
        try {
          fn(function (value) {
            if (done) {
              return;
            }
            done = true;
            onFulfilled(value);
          }, function (reason) {
            if (done) {
              return;
            }
            done = true;
            onRejected(reason);
          });
        } catch (ex) {
          if (done) {
            return;
          }
          done = true;
          onRejected(ex);
        }
      };
      Promise.prototype.catch = function (onRejected) {
        return this.then(null, onRejected);
      };
      Promise.prototype.then = function (onFulfilled, onRejected) {
        var me = this;
        return new Promise(function (resolve, reject) {
          handle.call(me, new Handler(onFulfilled, onRejected, resolve, reject));
        });
      };
      Promise.all = function () {
        var values = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          values[_i] = arguments[_i];
        }
        var args = Array.prototype.slice.call(values.length === 1 && isArray(values[0]) ? values[0] : values);
        return new Promise(function (resolve, reject) {
          if (args.length === 0) {
            return resolve([]);
          }
          var remaining = args.length;
          var res = function (i, val) {
            try {
              if (val && (typeof val === 'object' || typeof val === 'function')) {
                var then = val.then;
                if (typeof then === 'function') {
                  then.call(val, function (val) {
                    res(i, val);
                  }, reject);
                  return;
                }
              }
              args[i] = val;
              if (--remaining === 0) {
                resolve(args);
              }
            } catch (ex) {
              reject(ex);
            }
          };
          for (var i = 0; i < args.length; i++) {
            res(i, args[i]);
          }
        });
      };
      Promise.resolve = function (value) {
        if (value && typeof value === 'object' && value.constructor === Promise) {
          return value;
        }
        return new Promise(function (resolve) {
          resolve(value);
        });
      };
      Promise.reject = function (reason) {
        return new Promise(function (resolve, reject) {
          reject(reason);
        });
      };
      Promise.race = function (values) {
        return new Promise(function (resolve, reject) {
          for (var _i = 0, values_1 = values; _i < values_1.length; _i++) {
            var value = values_1[_i];
            value.then(resolve, reject);
          }
        });
      };
      return Promise;
    };
    var Promise$2 = window.Promise ? window.Promise : promise();

    var blobToDataUri = function (blob) {
      return new Promise$2(function (resolve) {
        var reader = new FileReader();
        reader.onloadend = function () {
          resolve(reader.result);
        };
        reader.readAsDataURL(blob);
      });
    };
    var blobToBase64$1 = function (blob) {
      return blobToDataUri(blob).then(function (dataUri) {
        return dataUri.split(',')[1];
      });
    };

    var blobToBase64 = function (blob) {
      return blobToBase64$1(blob);
    };

    var addImage = function (editor, blob) {
      blobToBase64(blob).then(function (base64) {
        editor.undoManager.transact(function () {
          var cache = editor.editorUpload.blobCache;
          var info = cache.create(generate$4('mceu'), blob, base64);
          cache.add(info);
          var img = editor.dom.createHTML('img', { src: info.blobUri() });
          editor.insertContent(img);
        });
      });
    };
    var extractBlob = function (simulatedEvent) {
      var event = simulatedEvent.event.raw;
      var files = event.target.files || event.dataTransfer.files;
      return Optional.from(files[0]);
    };
    var sketch$5 = function (editor) {
      var pickerDom = {
        tag: 'input',
        attributes: {
          accept: 'image/*',
          type: 'file',
          title: ''
        },
        styles: {
          visibility: 'hidden',
          position: 'absolute'
        }
      };
      var memPicker = record({
        dom: pickerDom,
        events: derive$3([
          cutter(click()),
          run(change(), function (picker, simulatedEvent) {
            extractBlob(simulatedEvent).each(function (blob) {
              addImage(editor, blob);
            });
          })
        ])
      });
      return Button.sketch({
        dom: getToolbarIconButton('image', editor),
        components: [memPicker.asSpec()],
        action: function (button) {
          var picker = memPicker.get(button);
          picker.element.dom.click();
        }
      });
    };

    var get$3 = function (element) {
      return element.dom.textContent;
    };
    var set$3 = function (element, value) {
      element.dom.textContent = value;
    };

    var isNotEmpty = function (val) {
      return val.length > 0;
    };
    var defaultToEmpty = function (str) {
      return str === undefined || str === null ? '' : str;
    };
    var noLink = function (editor) {
      var text = editor.selection.getContent({ format: 'text' });
      return {
        url: '',
        text: text,
        title: '',
        target: '',
        link: Optional.none()
      };
    };
    var fromLink = function (link) {
      var text = get$3(link);
      var url = get$b(link, 'href');
      var title = get$b(link, 'title');
      var target = get$b(link, 'target');
      return {
        url: defaultToEmpty(url),
        text: text !== url ? defaultToEmpty(text) : '',
        title: defaultToEmpty(title),
        target: defaultToEmpty(target),
        link: Optional.some(link)
      };
    };
    var getInfo = function (editor) {
      return query(editor).fold(function () {
        return noLink(editor);
      }, function (link) {
        return fromLink(link);
      });
    };
    var wasSimple = function (link) {
      var prevHref = get$b(link, 'href');
      var prevText = get$3(link);
      return prevHref === prevText;
    };
    var getTextToApply = function (link, url, info) {
      return info.text.toOptional().filter(isNotEmpty).fold(function () {
        return wasSimple(link) ? Optional.some(url) : Optional.none();
      }, Optional.some);
    };
    var unlinkIfRequired = function (editor, info) {
      var activeLink = info.link.bind(identity);
      activeLink.each(function (_link) {
        editor.execCommand('unlink');
      });
    };
    var getAttrs = function (url, info) {
      var attrs = {};
      attrs.href = url;
      info.title.toOptional().filter(isNotEmpty).each(function (title) {
        attrs.title = title;
      });
      info.target.toOptional().filter(isNotEmpty).each(function (target) {
        attrs.target = target;
      });
      return attrs;
    };
    var applyInfo = function (editor, info) {
      info.url.toOptional().filter(isNotEmpty).fold(function () {
        unlinkIfRequired(editor, info);
      }, function (url) {
        var attrs = getAttrs(url, info);
        var activeLink = info.link.bind(identity);
        activeLink.fold(function () {
          var text = info.text.toOptional().filter(isNotEmpty).getOr(url);
          editor.insertContent(editor.dom.createHTML('a', attrs, editor.dom.encode(text)));
        }, function (link) {
          var text = getTextToApply(link, url, info);
          setAll$1(link, attrs);
          text.each(function (newText) {
            set$3(link, newText);
          });
        });
      });
    };
    var query = function (editor) {
      var start = SugarElement.fromDom(editor.selection.getStart());
      return closest$1(start, 'a');
    };

    var platform = detect$1();
    var preserve$1 = function (f, editor) {
      var rng = editor.selection.getRng();
      f();
      editor.selection.setRng(rng);
    };
    var forAndroid = function (editor, f) {
      var wrapper = platform.os.isAndroid() ? preserve$1 : apply$1;
      wrapper(f, editor);
    };

    var events$4 = function (name, eventHandlers) {
      var events = derive$3(eventHandlers);
      return create$5({
        fields: [required$1('enabled')],
        name: name,
        active: { events: constant$1(events) }
      });
    };
    var config = function (name, eventHandlers) {
      var me = events$4(name, eventHandlers);
      return {
        key: name,
        value: {
          config: {},
          me: me,
          configAsRaw: constant$1({}),
          initialConfig: {},
          state: NoState
        }
      };
    };

    var getCurrent = function (component, composeConfig, _composeState) {
      return composeConfig.find(component);
    };

    var ComposeApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        getCurrent: getCurrent
    });

    var ComposeSchema = [required$1('find')];

    var Composing = create$5({
      fields: ComposeSchema,
      name: 'composing',
      apis: ComposeApis
    });

    var factory$4 = function (detail) {
      var _a = detail.dom, attributes = _a.attributes, domWithoutAttributes = __rest(_a, ['attributes']);
      return {
        uid: detail.uid,
        dom: __assign({
          tag: 'div',
          attributes: __assign({ role: 'presentation' }, attributes)
        }, domWithoutAttributes),
        components: detail.components,
        behaviours: get$6(detail.containerBehaviours),
        events: detail.events,
        domModification: detail.domModification,
        eventOrder: detail.eventOrder
      };
    };
    var Container = single({
      name: 'Container',
      factory: factory$4,
      configFields: [
        defaulted('components', []),
        field$1('containerBehaviours', []),
        defaulted('events', {}),
        defaulted('domModification', {}),
        defaulted('eventOrder', {})
      ]
    });

    var factory$3 = function (detail) {
      return {
        uid: detail.uid,
        dom: detail.dom,
        behaviours: SketchBehaviours.augment(detail.dataBehaviours, [
          Representing.config({
            store: {
              mode: 'memory',
              initialValue: detail.getInitialValue()
            }
          }),
          Composing.config({ find: Optional.some })
        ]),
        events: derive$3([runOnAttached(function (component, _simulatedEvent) {
            Representing.setValue(component, detail.getInitialValue());
          })])
      };
    };
    var DataField = single({
      name: 'DataField',
      factory: factory$3,
      configFields: [
        required$1('uid'),
        required$1('dom'),
        required$1('getInitialValue'),
        SketchBehaviours.field('dataBehaviours', [
          Representing,
          Composing
        ])
      ]
    });

    var get$2 = function (element) {
      return element.dom.value;
    };
    var set$2 = function (element, value) {
      if (value === undefined) {
        throw new Error('Value.set was undefined');
      }
      element.dom.value = value;
    };

    var schema$8 = constant$1([
      option('data'),
      defaulted('inputAttributes', {}),
      defaulted('inputStyles', {}),
      defaulted('tag', 'input'),
      defaulted('inputClasses', []),
      onHandler('onSetValue'),
      defaulted('styles', {}),
      defaulted('eventOrder', {}),
      field$1('inputBehaviours', [
        Representing,
        Focusing
      ]),
      defaulted('selectOnFocus', true)
    ]);
    var focusBehaviours = function (detail) {
      return derive$2([Focusing.config({
          onFocus: !detail.selectOnFocus ? noop : function (component) {
            var input = component.element;
            var value = get$2(input);
            input.dom.setSelectionRange(0, value.length);
          }
        })]);
    };
    var behaviours = function (detail) {
      return __assign(__assign({}, focusBehaviours(detail)), augment(detail.inputBehaviours, [Representing.config({
          store: __assign(__assign({ mode: 'manual' }, detail.data.map(function (data) {
            return { initialValue: data };
          }).getOr({})), {
            getValue: function (input) {
              return get$2(input.element);
            },
            setValue: function (input, data) {
              var current = get$2(input.element);
              if (current !== data) {
                set$2(input.element, data);
              }
            }
          }),
          onSetValue: detail.onSetValue
        })]));
    };
    var dom = function (detail) {
      return {
        tag: detail.tag,
        attributes: __assign({ type: 'text' }, detail.inputAttributes),
        styles: detail.inputStyles,
        classes: detail.inputClasses
      };
    };

    var factory$2 = function (detail, _spec) {
      return {
        uid: detail.uid,
        dom: dom(detail),
        components: [],
        behaviours: behaviours(detail),
        eventOrder: detail.eventOrder
      };
    };
    var Input = single({
      name: 'Input',
      configFields: schema$8(),
      factory: factory$2
    });

    var exhibit$2 = function (base, tabConfig) {
      return nu$3({
        attributes: wrapAll([{
            key: tabConfig.tabAttr,
            value: 'true'
          }])
      });
    };

    var ActiveTabstopping = /*#__PURE__*/Object.freeze({
        __proto__: null,
        exhibit: exhibit$2
    });

    var TabstopSchema = [defaulted('tabAttr', 'data-alloy-tabstop')];

    var Tabstopping = create$5({
      fields: TabstopSchema,
      name: 'tabstopping',
      active: ActiveTabstopping
    });

    var global$3 = tinymce.util.Tools.resolve('tinymce.util.I18n');

    var clearInputBehaviour = 'input-clearing';
    var field = function (name, placeholder) {
      var inputSpec = record(Input.sketch({
        inputAttributes: { placeholder: global$3.translate(placeholder) },
        onSetValue: function (input, _data) {
          emit(input, input$1());
        },
        inputBehaviours: derive$2([
          Composing.config({ find: Optional.some }),
          Tabstopping.config({}),
          Keying.config({ mode: 'execution' })
        ]),
        selectOnFocus: false
      }));
      var buttonSpec = record(Button.sketch({
        dom: dom$1('<button class="${prefix}-input-container-x ${prefix}-icon-cancel-circle ${prefix}-icon"></button>'),
        action: function (button) {
          var input = inputSpec.get(button);
          Representing.setValue(input, '');
        }
      }));
      return {
        name: name,
        spec: Container.sketch({
          dom: dom$1('<div class="${prefix}-input-container"></div>'),
          components: [
            inputSpec.asSpec(),
            buttonSpec.asSpec()
          ],
          containerBehaviours: derive$2([
            Toggling.config({ toggleClass: resolve('input-container-empty') }),
            Composing.config({
              find: function (comp) {
                return Optional.some(inputSpec.get(comp));
              }
            }),
            config(clearInputBehaviour, [run(input$1(), function (iContainer) {
                var input = inputSpec.get(iContainer);
                var val = Representing.getValue(input);
                var f = val.length > 0 ? Toggling.off : Toggling.on;
                f(iContainer);
              })])
          ])
        })
      };
    };
    var hidden = function (name) {
      return {
        name: name,
        spec: DataField.sketch({
          dom: {
            tag: 'span',
            styles: { display: 'none' }
          },
          getInitialValue: function () {
            return Optional.none();
          }
        })
      };
    };

    var nativeDisabled = [
      'input',
      'button',
      'textarea',
      'select'
    ];
    var onLoad = function (component, disableConfig, disableState) {
      var f = disableConfig.disabled() ? disable : enable;
      f(component, disableConfig);
    };
    var hasNative = function (component, config) {
      return config.useNative === true && contains$1(nativeDisabled, name$1(component.element));
    };
    var nativeIsDisabled = function (component) {
      return has$1(component.element, 'disabled');
    };
    var nativeDisable = function (component) {
      set$8(component.element, 'disabled', 'disabled');
    };
    var nativeEnable = function (component) {
      remove$6(component.element, 'disabled');
    };
    var ariaIsDisabled = function (component) {
      return get$b(component.element, 'aria-disabled') === 'true';
    };
    var ariaDisable = function (component) {
      set$8(component.element, 'aria-disabled', 'true');
    };
    var ariaEnable = function (component) {
      set$8(component.element, 'aria-disabled', 'false');
    };
    var disable = function (component, disableConfig, _disableState) {
      disableConfig.disableClass.each(function (disableClass) {
        add$1(component.element, disableClass);
      });
      var f = hasNative(component, disableConfig) ? nativeDisable : ariaDisable;
      f(component);
      disableConfig.onDisabled(component);
    };
    var enable = function (component, disableConfig, _disableState) {
      disableConfig.disableClass.each(function (disableClass) {
        remove$3(component.element, disableClass);
      });
      var f = hasNative(component, disableConfig) ? nativeEnable : ariaEnable;
      f(component);
      disableConfig.onEnabled(component);
    };
    var isDisabled = function (component, disableConfig) {
      return hasNative(component, disableConfig) ? nativeIsDisabled(component) : ariaIsDisabled(component);
    };
    var set$1 = function (component, disableConfig, disableState, disabled) {
      var f = disabled ? disable : enable;
      f(component, disableConfig);
    };

    var DisableApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        enable: enable,
        disable: disable,
        isDisabled: isDisabled,
        onLoad: onLoad,
        set: set$1
    });

    var exhibit$1 = function (base, disableConfig) {
      return nu$3({ classes: disableConfig.disabled() ? disableConfig.disableClass.toArray() : [] });
    };
    var events$3 = function (disableConfig, disableState) {
      return derive$3([
        abort(execute$5(), function (component, _simulatedEvent) {
          return isDisabled(component, disableConfig);
        }),
        loadEvent(disableConfig, disableState, onLoad)
      ]);
    };

    var ActiveDisable = /*#__PURE__*/Object.freeze({
        __proto__: null,
        exhibit: exhibit$1,
        events: events$3
    });

    var DisableSchema = [
      defaultedFunction('disabled', never),
      defaulted('useNative', true),
      option('disableClass'),
      onHandler('onDisabled'),
      onHandler('onEnabled')
    ];

    var Disabling = create$5({
      fields: DisableSchema,
      name: 'disabling',
      active: ActiveDisable,
      apis: DisableApis
    });

    var owner$1 = 'form';
    var schema$7 = [field$1('formBehaviours', [Representing])];
    var getPartName = function (name) {
      return '<alloy.field.' + name + '>';
    };
    var sketch$4 = function (fSpec) {
      var parts = function () {
        var record = [];
        var field = function (name, config) {
          record.push(name);
          return generateOne(owner$1, getPartName(name), config);
        };
        return {
          field: field,
          record: constant$1(record)
        };
      }();
      var spec = fSpec(parts);
      var partNames = parts.record();
      var fieldParts = map$2(partNames, function (n) {
        return required({
          name: n,
          pname: getPartName(n)
        });
      });
      return composite$1(owner$1, schema$7, fieldParts, make$4, spec);
    };
    var toResult = function (o, e) {
      return o.fold(function () {
        return Result.error(e);
      }, Result.value);
    };
    var make$4 = function (detail, components) {
      return {
        uid: detail.uid,
        dom: detail.dom,
        components: components,
        behaviours: augment(detail.formBehaviours, [Representing.config({
            store: {
              mode: 'manual',
              getValue: function (form) {
                var resPs = getAllParts(form, detail);
                return map$1(resPs, function (resPThunk, pName) {
                  return resPThunk().bind(function (v) {
                    var opt = Composing.getCurrent(v);
                    return toResult(opt, new Error('Cannot find a current component to extract the value from for form part \'' + pName + '\': ' + element(v.element)));
                  }).map(Representing.getValue);
                });
              },
              setValue: function (form, values) {
                each(values, function (newValue, key) {
                  getPart(form, detail, key).each(function (wrapper) {
                    Composing.getCurrent(wrapper).each(function (field) {
                      Representing.setValue(field, newValue);
                    });
                  });
                });
              }
            }
          })]),
        apis: {
          getField: function (form, key) {
            return getPart(form, detail, key).bind(Composing.getCurrent);
          }
        }
      };
    };
    var Form = {
      getField: makeApi(function (apis, component, key) {
        return apis.getField(component, key);
      }),
      sketch: sketch$4
    };

    var SWIPING_LEFT = 1;
    var SWIPING_RIGHT = -1;
    var SWIPING_NONE = 0;
    var init$3 = function (xValue) {
      return {
        xValue: xValue,
        points: []
      };
    };
    var move = function (model, xValue) {
      if (xValue === model.xValue) {
        return model;
      }
      var currentDirection = xValue - model.xValue > 0 ? SWIPING_LEFT : SWIPING_RIGHT;
      var newPoint = {
        direction: currentDirection,
        xValue: xValue
      };
      var priorPoints = function () {
        if (model.points.length === 0) {
          return [];
        } else {
          var prev = model.points[model.points.length - 1];
          return prev.direction === currentDirection ? model.points.slice(0, model.points.length - 1) : model.points;
        }
      }();
      return {
        xValue: xValue,
        points: priorPoints.concat([newPoint])
      };
    };
    var complete = function (model) {
      if (model.points.length === 0) {
        return SWIPING_NONE;
      } else {
        var firstDirection = model.points[0].direction;
        var lastDirection = model.points[model.points.length - 1].direction;
        return firstDirection === SWIPING_RIGHT && lastDirection === SWIPING_RIGHT ? SWIPING_RIGHT : firstDirection === SWIPING_LEFT && lastDirection === SWIPING_LEFT ? SWIPING_LEFT : SWIPING_NONE;
      }
    };

    var sketch$3 = function (rawSpec) {
      var navigateEvent = 'navigateEvent';
      var wrapperAdhocEvents = 'serializer-wrapper-events';
      var formAdhocEvents = 'form-events';
      var schema = objOf([
        required$1('fields'),
        defaulted('maxFieldIndex', rawSpec.fields.length - 1),
        required$1('onExecute'),
        required$1('getInitialValue'),
        customField('state', function () {
          return {
            dialogSwipeState: value(),
            currentScreen: Cell(0)
          };
        })
      ]);
      var spec$1 = asRawOrDie$1('SerialisedDialog', schema, rawSpec);
      var navigationButton = function (direction, directionName, enabled) {
        return Button.sketch({
          dom: dom$1('<span class="${prefix}-icon-' + directionName + ' ${prefix}-icon"></span>'),
          action: function (button) {
            emitWith(button, navigateEvent, { direction: direction });
          },
          buttonBehaviours: derive$2([Disabling.config({
              disableClass: resolve('toolbar-navigation-disabled'),
              disabled: function () {
                return !enabled;
              }
            })])
        });
      };
      var reposition = function (dialog, message) {
        descendant(dialog.element, '.' + resolve('serialised-dialog-chain')).each(function (parent) {
          set$5(parent, 'left', -spec$1.state.currentScreen.get() * message.width + 'px');
        });
      };
      var navigate = function (dialog, direction) {
        var screens = descendants(dialog.element, '.' + resolve('serialised-dialog-screen'));
        descendant(dialog.element, '.' + resolve('serialised-dialog-chain')).each(function (parent) {
          if (spec$1.state.currentScreen.get() + direction >= 0 && spec$1.state.currentScreen.get() + direction < screens.length) {
            getRaw(parent, 'left').each(function (left) {
              var currentLeft = parseInt(left, 10);
              var w = get$5(screens[0]);
              set$5(parent, 'left', currentLeft - direction * w + 'px');
            });
            spec$1.state.currentScreen.set(spec$1.state.currentScreen.get() + direction);
          }
        });
      };
      var focusInput = function (dialog) {
        var inputs = descendants(dialog.element, 'input');
        var optInput = Optional.from(inputs[spec$1.state.currentScreen.get()]);
        optInput.each(function (input) {
          dialog.getSystem().getByDom(input).each(function (inputComp) {
            dispatchFocus(dialog, inputComp.element);
          });
        });
        var dotitems = memDots.get(dialog);
        Highlighting.highlightAt(dotitems, spec$1.state.currentScreen.get());
      };
      var resetState = function () {
        spec$1.state.currentScreen.set(0);
        spec$1.state.dialogSwipeState.clear();
      };
      var memForm = record(Form.sketch(function (parts) {
        return {
          dom: dom$1('<div class="${prefix}-serialised-dialog"></div>'),
          components: [Container.sketch({
              dom: dom$1('<div class="${prefix}-serialised-dialog-chain" style="left: 0px; position: absolute;"></div>'),
              components: map$2(spec$1.fields, function (field, i) {
                return i <= spec$1.maxFieldIndex ? Container.sketch({
                  dom: dom$1('<div class="${prefix}-serialised-dialog-screen"></div>'),
                  components: [
                    navigationButton(-1, 'previous', i > 0),
                    parts.field(field.name, field.spec),
                    navigationButton(+1, 'next', i < spec$1.maxFieldIndex)
                  ]
                }) : parts.field(field.name, field.spec);
              })
            })],
          formBehaviours: derive$2([
            orientation(function (dialog, message) {
              reposition(dialog, message);
            }),
            Keying.config({
              mode: 'special',
              focusIn: function (dialog, _specialInfo) {
                focusInput(dialog);
              },
              onTab: function (dialog, _specialInfo) {
                navigate(dialog, +1);
                return Optional.some(true);
              },
              onShiftTab: function (dialog, _specialInfo) {
                navigate(dialog, -1);
                return Optional.some(true);
              }
            }),
            config(formAdhocEvents, [
              runOnAttached(function (dialog, _simulatedEvent) {
                resetState();
                var dotitems = memDots.get(dialog);
                Highlighting.highlightFirst(dotitems);
                spec$1.getInitialValue(dialog).each(function (v) {
                  Representing.setValue(dialog, v);
                });
              }),
              runOnExecute(spec$1.onExecute),
              run(transitionend(), function (dialog, simulatedEvent) {
                var event = simulatedEvent.event;
                if (event.raw.propertyName === 'left') {
                  focusInput(dialog);
                }
              }),
              run(navigateEvent, function (dialog, simulatedEvent) {
                var event = simulatedEvent.event;
                var direction = event.direction;
                navigate(dialog, direction);
              })
            ])
          ])
        };
      }));
      var memDots = record({
        dom: dom$1('<div class="${prefix}-dot-container"></div>'),
        behaviours: derive$2([Highlighting.config({
            highlightClass: resolve('dot-active'),
            itemClass: resolve('dot-item')
          })]),
        components: bind$3(spec$1.fields, function (_f, i) {
          return i <= spec$1.maxFieldIndex ? [spec('<div class="${prefix}-dot-item ${prefix}-icon-full-dot ${prefix}-icon"></div>')] : [];
        })
      });
      return {
        dom: dom$1('<div class="${prefix}-serializer-wrapper"></div>'),
        components: [
          memForm.asSpec(),
          memDots.asSpec()
        ],
        behaviours: derive$2([
          Keying.config({
            mode: 'special',
            focusIn: function (wrapper) {
              var form = memForm.get(wrapper);
              Keying.focusIn(form);
            }
          }),
          config(wrapperAdhocEvents, [
            run(touchstart(), function (_wrapper, simulatedEvent) {
              var event = simulatedEvent.event;
              spec$1.state.dialogSwipeState.set(init$3(event.raw.touches[0].clientX));
            }),
            run(touchmove(), function (_wrapper, simulatedEvent) {
              var event = simulatedEvent.event;
              spec$1.state.dialogSwipeState.on(function (state) {
                simulatedEvent.event.prevent();
                spec$1.state.dialogSwipeState.set(move(state, event.raw.touches[0].clientX));
              });
            }),
            run(touchend(), function (wrapper, _simulatedEvent) {
              spec$1.state.dialogSwipeState.on(function (state) {
                var dialog = memForm.get(wrapper);
                var direction = -1 * complete(state);
                navigate(dialog, direction);
              });
            })
          ])
        ])
      };
    };

    var getGroups = cached(function (realm, editor) {
      return [{
          label: 'the link group',
          items: [sketch$3({
              fields: [
                field('url', 'Type or paste URL'),
                field('text', 'Link text'),
                field('title', 'Link title'),
                field('target', 'Link target'),
                hidden('link')
              ],
              maxFieldIndex: [
                'url',
                'text',
                'title',
                'target'
              ].length - 1,
              getInitialValue: function () {
                return Optional.some(getInfo(editor));
              },
              onExecute: function (dialog, _simulatedEvent) {
                var info = Representing.getValue(dialog);
                applyInfo(editor, info);
                realm.restoreToolbar();
                editor.focus();
              }
            })]
        }];
    });
    var sketch$2 = function (realm, editor) {
      return forToolbarStateAction(editor, 'link', 'link', function () {
        var groups = getGroups(realm, editor);
        realm.setContextToolbar(groups);
        forAndroid(editor, function () {
          realm.focusToolbar();
        });
        query(editor).each(function (link) {
          editor.selection.select(link.dom);
        });
      });
    };

    var isRecursive = function (component, originator, target) {
      return eq(originator, component.element) && !eq(originator, target);
    };
    var events$2 = derive$3([can(focus$4(), function (component, simulatedEvent) {
        var event = simulatedEvent.event;
        var originator = event.originator;
        var target = event.target;
        if (isRecursive(component, originator, target)) {
          console.warn(focus$4() + ' did not get interpreted by the desired target. ' + '\nOriginator: ' + element(originator) + '\nTarget: ' + element(target) + '\nCheck the ' + focus$4() + ' event handlers');
          return false;
        } else {
          return true;
        }
      })]);

    var DefaultEvents = /*#__PURE__*/Object.freeze({
        __proto__: null,
        events: events$2
    });

    var make$3 = identity;

    var NoContextApi = function (getComp) {
      var getMessage = function (event) {
        return 'The component must be in a context to execute: ' + event + (getComp ? '\n' + element(getComp().element) + ' is not in context.' : '');
      };
      var fail = function (event) {
        return function () {
          throw new Error(getMessage(event));
        };
      };
      var warn = function (event) {
        return function () {
          console.warn(getMessage(event));
        };
      };
      return {
        debugInfo: constant$1('fake'),
        triggerEvent: warn('triggerEvent'),
        triggerFocus: warn('triggerFocus'),
        triggerEscape: warn('triggerEscape'),
        broadcast: warn('broadcast'),
        broadcastOn: warn('broadcastOn'),
        broadcastEvent: warn('broadcastEvent'),
        build: fail('build'),
        addToWorld: fail('addToWorld'),
        removeFromWorld: fail('removeFromWorld'),
        addToGui: fail('addToGui'),
        removeFromGui: fail('removeFromGui'),
        getByUid: fail('getByUid'),
        getByDom: fail('getByDom'),
        isConnected: never
      };
    };
    var singleton = NoContextApi();

    var generateFrom$1 = function (spec, all) {
      var schema = map$2(all, function (a) {
        return optionObjOf(a.name(), [
          required$1('config'),
          defaulted('state', NoState)
        ]);
      });
      var validated = asRaw('component.behaviours', objOf(schema), spec.behaviours).fold(function (errInfo) {
        throw new Error(formatError(errInfo) + '\nComplete spec:\n' + JSON.stringify(spec, null, 2));
      }, identity);
      return {
        list: all,
        data: map$1(validated, function (optBlobThunk) {
          var output = optBlobThunk.map(function (blob) {
            return {
              config: blob.config,
              state: blob.state.init(blob.config)
            };
          });
          return constant$1(output);
        })
      };
    };
    var getBehaviours$1 = function (bData) {
      return bData.list;
    };
    var getData = function (bData) {
      return bData.data;
    };

    var byInnerKey = function (data, tuple) {
      var r = {};
      each(data, function (detail, key) {
        each(detail, function (value, indexKey) {
          var chain = get$c(r, indexKey).getOr([]);
          r[indexKey] = chain.concat([tuple(key, value)]);
        });
      });
      return r;
    };

    var combine$1 = function (info, baseMod, behaviours, base) {
      var modsByBehaviour = __assign({}, baseMod);
      each$1(behaviours, function (behaviour) {
        modsByBehaviour[behaviour.name()] = behaviour.exhibit(info, base);
      });
      var byAspect = byInnerKey(modsByBehaviour, function (name, modification) {
        return {
          name: name,
          modification: modification
        };
      });
      var combineObjects = function (objects) {
        return foldr(objects, function (b, a) {
          return __assign(__assign({}, a.modification), b);
        }, {});
      };
      var combinedClasses = foldr(byAspect.classes, function (b, a) {
        return a.modification.concat(b);
      }, []);
      var combinedAttributes = combineObjects(byAspect.attributes);
      var combinedStyles = combineObjects(byAspect.styles);
      return nu$3({
        classes: combinedClasses,
        attributes: combinedAttributes,
        styles: combinedStyles
      });
    };

    var sortKeys = function (label, keyName, array, order) {
      try {
        var sorted = sort(array, function (a, b) {
          var aKey = a[keyName];
          var bKey = b[keyName];
          var aIndex = order.indexOf(aKey);
          var bIndex = order.indexOf(bKey);
          if (aIndex === -1) {
            throw new Error('The ordering for ' + label + ' does not have an entry for ' + aKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
          }
          if (bIndex === -1) {
            throw new Error('The ordering for ' + label + ' does not have an entry for ' + bKey + '.\nOrder specified: ' + JSON.stringify(order, null, 2));
          }
          if (aIndex < bIndex) {
            return -1;
          } else if (bIndex < aIndex) {
            return 1;
          } else {
            return 0;
          }
        });
        return Result.value(sorted);
      } catch (err) {
        return Result.error([err]);
      }
    };

    var uncurried = function (handler, purpose) {
      return {
        handler: handler,
        purpose: purpose
      };
    };
    var curried = function (handler, purpose) {
      return {
        cHandler: handler,
        purpose: purpose
      };
    };
    var curryArgs = function (descHandler, extraArgs) {
      return curried(curry.apply(undefined, [descHandler.handler].concat(extraArgs)), descHandler.purpose);
    };
    var getCurried = function (descHandler) {
      return descHandler.cHandler;
    };

    var behaviourTuple = function (name, handler) {
      return {
        name: name,
        handler: handler
      };
    };
    var nameToHandlers = function (behaviours, info) {
      var r = {};
      each$1(behaviours, function (behaviour) {
        r[behaviour.name()] = behaviour.handlers(info);
      });
      return r;
    };
    var groupByEvents = function (info, behaviours, base) {
      var behaviourEvents = __assign(__assign({}, base), nameToHandlers(behaviours, info));
      return byInnerKey(behaviourEvents, behaviourTuple);
    };
    var combine = function (info, eventOrder, behaviours, base) {
      var byEventName = groupByEvents(info, behaviours, base);
      return combineGroups(byEventName, eventOrder);
    };
    var assemble = function (rawHandler) {
      var handler = read$1(rawHandler);
      return function (component, simulatedEvent) {
        var rest = [];
        for (var _i = 2; _i < arguments.length; _i++) {
          rest[_i - 2] = arguments[_i];
        }
        var args = [
          component,
          simulatedEvent
        ].concat(rest);
        if (handler.abort.apply(undefined, args)) {
          simulatedEvent.stop();
        } else if (handler.can.apply(undefined, args)) {
          handler.run.apply(undefined, args);
        }
      };
    };
    var missingOrderError = function (eventName, tuples) {
      return Result.error(['The event (' + eventName + ') has more than one behaviour that listens to it.\nWhen this occurs, you must ' + 'specify an event ordering for the behaviours in your spec (e.g. [ "listing", "toggling" ]).\nThe behaviours that ' + 'can trigger it are: ' + JSON.stringify(map$2(tuples, function (c) {
          return c.name;
        }), null, 2)]);
    };
    var fuse = function (tuples, eventOrder, eventName) {
      var order = eventOrder[eventName];
      if (!order) {
        return missingOrderError(eventName, tuples);
      } else {
        return sortKeys('Event: ' + eventName, 'name', tuples, order).map(function (sortedTuples) {
          var handlers = map$2(sortedTuples, function (tuple) {
            return tuple.handler;
          });
          return fuse$1(handlers);
        });
      }
    };
    var combineGroups = function (byEventName, eventOrder) {
      var r = mapToArray(byEventName, function (tuples, eventName) {
        var combined = tuples.length === 1 ? Result.value(tuples[0].handler) : fuse(tuples, eventOrder, eventName);
        return combined.map(function (handler) {
          var assembled = assemble(handler);
          var purpose = tuples.length > 1 ? filter$2(eventOrder[eventName], function (o) {
            return exists(tuples, function (t) {
              return t.name === o;
            });
          }).join(' > ') : tuples[0].name;
          return wrap(eventName, uncurried(assembled, purpose));
        });
      });
      return consolidate(r, {});
    };

    var _a;
    var baseBehaviour = 'alloy.base.behaviour';
    var schema$6 = objOf([
      field$2('dom', 'dom', required$2(), objOf([
        required$1('tag'),
        defaulted('styles', {}),
        defaulted('classes', []),
        defaulted('attributes', {}),
        option('value'),
        option('innerHtml')
      ])),
      required$1('components'),
      required$1('uid'),
      defaulted('events', {}),
      defaulted('apis', {}),
      field$2('eventOrder', 'eventOrder', mergeWith((_a = {}, _a[execute$5()] = [
        'disabling',
        baseBehaviour,
        'toggling',
        'typeaheadevents'
      ], _a[focus$4()] = [
        baseBehaviour,
        'focusing',
        'keying'
      ], _a[systemInit()] = [
        baseBehaviour,
        'disabling',
        'toggling',
        'representing'
      ], _a[input$1()] = [
        baseBehaviour,
        'representing',
        'streaming',
        'invalidating'
      ], _a[detachedFromDom()] = [
        baseBehaviour,
        'representing',
        'item-events',
        'tooltipping'
      ], _a[mousedown()] = [
        'focusing',
        baseBehaviour,
        'item-type-events'
      ], _a[touchstart()] = [
        'focusing',
        baseBehaviour,
        'item-type-events'
      ], _a[mouseover()] = [
        'item-type-events',
        'tooltipping'
      ], _a[receive$1()] = [
        'receiving',
        'reflecting',
        'tooltipping'
      ], _a)), anyValue()),
      option('domModification')
    ]);
    var toInfo = function (spec) {
      return asRaw('custom.definition', schema$6, spec);
    };
    var toDefinition = function (detail) {
      return __assign(__assign({}, detail.dom), {
        uid: detail.uid,
        domChildren: map$2(detail.components, function (comp) {
          return comp.element;
        })
      });
    };
    var toModification = function (detail) {
      return detail.domModification.fold(function () {
        return nu$3({});
      }, nu$3);
    };
    var toEvents = function (info) {
      return info.events;
    };

    var add = function (element, classes) {
      each$1(classes, function (x) {
        add$1(element, x);
      });
    };
    var remove$1 = function (element, classes) {
      each$1(classes, function (x) {
        remove$3(element, x);
      });
    };

    var renderToDom = function (definition) {
      var subject = SugarElement.fromTag(definition.tag);
      setAll$1(subject, definition.attributes);
      add(subject, definition.classes);
      setAll(subject, definition.styles);
      definition.innerHtml.each(function (html) {
        return set$7(subject, html);
      });
      var children = definition.domChildren;
      append$1(subject, children);
      definition.value.each(function (value) {
        set$2(subject, value);
      });
      if (!definition.uid) {
        debugger;
      }
      writeOnly(subject, definition.uid);
      return subject;
    };

    var getBehaviours = function (spec) {
      var behaviours = get$c(spec, 'behaviours').getOr({});
      var keys$1 = filter$2(keys(behaviours), function (k) {
        return behaviours[k] !== undefined;
      });
      return map$2(keys$1, function (k) {
        return behaviours[k].me;
      });
    };
    var generateFrom = function (spec, all) {
      return generateFrom$1(spec, all);
    };
    var generate$1 = function (spec) {
      var all = getBehaviours(spec);
      return generateFrom(spec, all);
    };

    var getDomDefinition = function (info, bList, bData) {
      var definition = toDefinition(info);
      var infoModification = toModification(info);
      var baseModification = { 'alloy.base.modification': infoModification };
      var modification = bList.length > 0 ? combine$1(bData, baseModification, bList, definition) : infoModification;
      return merge(definition, modification);
    };
    var getEvents = function (info, bList, bData) {
      var baseEvents = { 'alloy.base.behaviour': toEvents(info) };
      return combine(bData, info.eventOrder, bList, baseEvents).getOrDie();
    };
    var build$2 = function (spec) {
      var getMe = function () {
        return me;
      };
      var systemApi = Cell(singleton);
      var info = getOrDie(toInfo(spec));
      var bBlob = generate$1(spec);
      var bList = getBehaviours$1(bBlob);
      var bData = getData(bBlob);
      var modDefinition = getDomDefinition(info, bList, bData);
      var item = renderToDom(modDefinition);
      var events = getEvents(info, bList, bData);
      var subcomponents = Cell(info.components);
      var connect = function (newApi) {
        systemApi.set(newApi);
      };
      var disconnect = function () {
        systemApi.set(NoContextApi(getMe));
      };
      var syncComponents = function () {
        var children$1 = children(item);
        var subs = bind$3(children$1, function (child) {
          return systemApi.get().getByDom(child).fold(function () {
            return [];
          }, pure$2);
        });
        subcomponents.set(subs);
      };
      var config = function (behaviour) {
        var b = bData;
        var f = isFunction(b[behaviour.name()]) ? b[behaviour.name()] : function () {
          throw new Error('Could not find ' + behaviour.name() + ' in ' + JSON.stringify(spec, null, 2));
        };
        return f();
      };
      var hasConfigured = function (behaviour) {
        return isFunction(bData[behaviour.name()]);
      };
      var getApis = function () {
        return info.apis;
      };
      var readState = function (behaviourName) {
        return bData[behaviourName]().map(function (b) {
          return b.state.readState();
        }).getOr('not enabled');
      };
      var me = {
        uid: spec.uid,
        getSystem: systemApi.get,
        config: config,
        hasConfigured: hasConfigured,
        spec: spec,
        readState: readState,
        getApis: getApis,
        connect: connect,
        disconnect: disconnect,
        element: item,
        syncComponents: syncComponents,
        components: subcomponents.get,
        events: events
      };
      return me;
    };

    var buildSubcomponents = function (spec) {
      var components = get$c(spec, 'components').getOr([]);
      return map$2(components, build$1);
    };
    var buildFromSpec = function (userSpec) {
      var _a = make$3(userSpec), specEvents = _a.events, spec = __rest(_a, ['events']);
      var components = buildSubcomponents(spec);
      var completeSpec = __assign(__assign({}, spec), {
        events: __assign(__assign({}, DefaultEvents), specEvents),
        components: components
      });
      return Result.value(build$2(completeSpec));
    };
    var text = function (textContent) {
      var element = SugarElement.fromText(textContent);
      return external({ element: element });
    };
    var external = function (spec) {
      var extSpec = asRawOrDie$1('external.component', objOfOnly([
        required$1('element'),
        option('uid')
      ]), spec);
      var systemApi = Cell(NoContextApi());
      var connect = function (newApi) {
        systemApi.set(newApi);
      };
      var disconnect = function () {
        systemApi.set(NoContextApi(function () {
          return me;
        }));
      };
      var uid = extSpec.uid.getOrThunk(function () {
        return generate$2('external');
      });
      writeOnly(extSpec.element, uid);
      var me = {
        uid: uid,
        getSystem: systemApi.get,
        config: Optional.none,
        hasConfigured: never,
        connect: connect,
        disconnect: disconnect,
        getApis: function () {
          return {};
        },
        element: extSpec.element,
        spec: spec,
        readState: constant$1('No state'),
        syncComponents: noop,
        components: constant$1([]),
        events: {}
      };
      return premade$1(me);
    };
    var uids = generate$2;
    var isSketchSpec = function (spec) {
      return has$2(spec, 'uid');
    };
    var build$1 = function (spec) {
      return getPremade(spec).getOrThunk(function () {
        var userSpecWithUid = isSketchSpec(spec) ? spec : __assign({ uid: uids('') }, spec);
        return buildFromSpec(userSpecWithUid).getOrDie();
      });
    };
    var premade = premade$1;

    var hoverEvent = 'alloy.item-hover';
    var focusEvent = 'alloy.item-focus';
    var onHover = function (item) {
      if (search(item.element).isNone() || Focusing.isFocused(item)) {
        if (!Focusing.isFocused(item)) {
          Focusing.focus(item);
        }
        emitWith(item, hoverEvent, { item: item });
      }
    };
    var onFocus = function (item) {
      emitWith(item, focusEvent, { item: item });
    };
    var hover = constant$1(hoverEvent);
    var focus$1 = constant$1(focusEvent);

    var builder$2 = function (detail) {
      return {
        dom: detail.dom,
        domModification: __assign(__assign({}, detail.domModification), { attributes: __assign(__assign(__assign({ 'role': detail.toggling.isSome() ? 'menuitemcheckbox' : 'menuitem' }, detail.domModification.attributes), { 'aria-haspopup': detail.hasSubmenu }), detail.hasSubmenu ? { 'aria-expanded': false } : {}) }),
        behaviours: SketchBehaviours.augment(detail.itemBehaviours, [
          detail.toggling.fold(Toggling.revoke, function (tConfig) {
            return Toggling.config(__assign({ aria: { mode: 'checked' } }, tConfig));
          }),
          Focusing.config({
            ignore: detail.ignoreFocus,
            stopMousedown: detail.ignoreFocus,
            onFocus: function (component) {
              onFocus(component);
            }
          }),
          Keying.config({ mode: 'execution' }),
          Representing.config({
            store: {
              mode: 'memory',
              initialValue: detail.data
            }
          }),
          config('item-type-events', __spreadArray(__spreadArray([], pointerEvents()), [
            run(mouseover(), onHover),
            run(focusItem(), Focusing.focus)
          ]))
        ]),
        components: detail.components,
        eventOrder: detail.eventOrder
      };
    };
    var schema$5 = [
      required$1('data'),
      required$1('components'),
      required$1('dom'),
      defaulted('hasSubmenu', false),
      option('toggling'),
      SketchBehaviours.field('itemBehaviours', [
        Toggling,
        Focusing,
        Keying,
        Representing
      ]),
      defaulted('ignoreFocus', false),
      defaulted('domModification', {}),
      output('builder', builder$2),
      defaulted('eventOrder', {})
    ];

    var builder$1 = function (detail) {
      return {
        dom: detail.dom,
        components: detail.components,
        events: derive$3([stopper(focusItem())])
      };
    };
    var schema$4 = [
      required$1('dom'),
      required$1('components'),
      output('builder', builder$1)
    ];

    var owner = constant$1('item-widget');
    var parts$3 = constant$1([required({
        name: 'widget',
        overrides: function (detail) {
          return {
            behaviours: derive$2([Representing.config({
                store: {
                  mode: 'manual',
                  getValue: function (_component) {
                    return detail.data;
                  },
                  setValue: noop
                }
              })])
          };
        }
      })]);

    var builder = function (detail) {
      var subs = substitutes(owner(), detail, parts$3());
      var components$1 = components(owner(), detail, subs.internals());
      var focusWidget = function (component) {
        return getPart(component, detail, 'widget').map(function (widget) {
          Keying.focusIn(widget);
          return widget;
        });
      };
      var onHorizontalArrow = function (component, simulatedEvent) {
        return inside(simulatedEvent.event.target) ? Optional.none() : function () {
          if (detail.autofocus) {
            simulatedEvent.setSource(component.element);
            return Optional.none();
          } else {
            return Optional.none();
          }
        }();
      };
      return {
        dom: detail.dom,
        components: components$1,
        domModification: detail.domModification,
        events: derive$3([
          runOnExecute(function (component, simulatedEvent) {
            focusWidget(component).each(function (_widget) {
              simulatedEvent.stop();
            });
          }),
          run(mouseover(), onHover),
          run(focusItem(), function (component, _simulatedEvent) {
            if (detail.autofocus) {
              focusWidget(component);
            } else {
              Focusing.focus(component);
            }
          })
        ]),
        behaviours: SketchBehaviours.augment(detail.widgetBehaviours, [
          Representing.config({
            store: {
              mode: 'memory',
              initialValue: detail.data
            }
          }),
          Focusing.config({
            ignore: detail.ignoreFocus,
            onFocus: function (component) {
              onFocus(component);
            }
          }),
          Keying.config({
            mode: 'special',
            focusIn: detail.autofocus ? function (component) {
              focusWidget(component);
            } : revoke(),
            onLeft: onHorizontalArrow,
            onRight: onHorizontalArrow,
            onEscape: function (component, simulatedEvent) {
              if (!Focusing.isFocused(component) && !detail.autofocus) {
                Focusing.focus(component);
                return Optional.some(true);
              } else if (detail.autofocus) {
                simulatedEvent.setSource(component.element);
                return Optional.none();
              } else {
                return Optional.none();
              }
            }
          })
        ])
      };
    };
    var schema$3 = [
      required$1('uid'),
      required$1('data'),
      required$1('components'),
      required$1('dom'),
      defaulted('autofocus', false),
      defaulted('ignoreFocus', false),
      SketchBehaviours.field('widgetBehaviours', [
        Representing,
        Focusing,
        Keying
      ]),
      defaulted('domModification', {}),
      defaultUidsSchema(parts$3()),
      output('builder', builder)
    ];

    var itemSchema = choose$1('type', {
      widget: schema$3,
      item: schema$5,
      separator: schema$4
    });
    var configureGrid = function (detail, movementInfo) {
      return {
        mode: 'flatgrid',
        selector: '.' + detail.markers.item,
        initSize: {
          numColumns: movementInfo.initSize.numColumns,
          numRows: movementInfo.initSize.numRows
        },
        focusManager: detail.focusManager
      };
    };
    var configureMatrix = function (detail, movementInfo) {
      return {
        mode: 'matrix',
        selectors: {
          row: movementInfo.rowSelector,
          cell: '.' + detail.markers.item
        },
        focusManager: detail.focusManager
      };
    };
    var configureMenu = function (detail, movementInfo) {
      return {
        mode: 'menu',
        selector: '.' + detail.markers.item,
        moveOnTab: movementInfo.moveOnTab,
        focusManager: detail.focusManager
      };
    };
    var parts$2 = constant$1([group({
        factory: {
          sketch: function (spec) {
            var itemInfo = asRawOrDie$1('menu.spec item', itemSchema, spec);
            return itemInfo.builder(itemInfo);
          }
        },
        name: 'items',
        unit: 'item',
        defaults: function (detail, u) {
          return has$2(u, 'uid') ? u : __assign(__assign({}, u), { uid: generate$2('item') });
        },
        overrides: function (detail, u) {
          return {
            type: u.type,
            ignoreFocus: detail.fakeFocus,
            domModification: { classes: [detail.markers.item] }
          };
        }
      })]);
    var schema$2 = constant$1([
      required$1('value'),
      required$1('items'),
      required$1('dom'),
      required$1('components'),
      defaulted('eventOrder', {}),
      field$1('menuBehaviours', [
        Highlighting,
        Representing,
        Composing,
        Keying
      ]),
      defaultedOf('movement', {
        mode: 'menu',
        moveOnTab: true
      }, choose$1('mode', {
        grid: [
          initSize(),
          output('config', configureGrid)
        ],
        matrix: [
          output('config', configureMatrix),
          required$1('rowSelector')
        ],
        menu: [
          defaulted('moveOnTab', true),
          output('config', configureMenu)
        ]
      })),
      itemMarkers(),
      defaulted('fakeFocus', false),
      defaulted('focusManager', dom$2()),
      onHandler('onHighlight')
    ]);

    var focus = constant$1('alloy.menu-focus');

    var make$2 = function (detail, components, _spec, _externals) {
      return {
        uid: detail.uid,
        dom: detail.dom,
        markers: detail.markers,
        behaviours: augment(detail.menuBehaviours, [
          Highlighting.config({
            highlightClass: detail.markers.selectedItem,
            itemClass: detail.markers.item,
            onHighlight: detail.onHighlight
          }),
          Representing.config({
            store: {
              mode: 'memory',
              initialValue: detail.value
            }
          }),
          Composing.config({ find: Optional.some }),
          Keying.config(detail.movement.config(detail, detail.movement))
        ]),
        events: derive$3([
          run(focus$1(), function (menu, simulatedEvent) {
            var event = simulatedEvent.event;
            menu.getSystem().getByDom(event.target).each(function (item) {
              Highlighting.highlight(menu, item);
              simulatedEvent.stop();
              emitWith(menu, focus(), {
                menu: menu,
                item: item
              });
            });
          }),
          run(hover(), function (menu, simulatedEvent) {
            var item = simulatedEvent.event.item;
            Highlighting.highlight(menu, item);
          })
        ]),
        components: components,
        eventOrder: detail.eventOrder,
        domModification: { attributes: { role: 'menu' } }
      };
    };

    var Menu = composite({
      name: 'Menu',
      configFields: schema$2(),
      partFields: parts$2(),
      factory: make$2
    });

    var preserve = function (f, container) {
      var dos = getRootNode(container);
      var refocus = active(dos).bind(function (focused) {
        var hasFocus = function (elem) {
          return eq(focused, elem);
        };
        return hasFocus(container) ? Optional.some(container) : descendant$1(container, hasFocus);
      });
      var result = f(container);
      refocus.each(function (oldFocus) {
        active(dos).filter(function (newFocus) {
          return eq(newFocus, oldFocus);
        }).fold(function () {
          focus$3(oldFocus);
        }, noop);
      });
      return result;
    };

    var set = function (component, replaceConfig, replaceState, data) {
      preserve(function () {
        var newChildren = map$2(data, component.getSystem().build);
        replaceChildren(component, newChildren);
      }, component.element);
    };
    var insert = function (component, replaceConfig, insertion, childSpec) {
      var child = component.getSystem().build(childSpec);
      attachWith(component, child, insertion);
    };
    var append = function (component, replaceConfig, replaceState, appendee) {
      insert(component, replaceConfig, append$2, appendee);
    };
    var prepend = function (component, replaceConfig, replaceState, prependee) {
      insert(component, replaceConfig, prepend$1, prependee);
    };
    var remove = function (component, replaceConfig, replaceState, removee) {
      var children = contents(component);
      var foundChild = find$2(children, function (child) {
        return eq(removee.element, child.element);
      });
      foundChild.each(detach);
    };
    var contents = function (component, _replaceConfig) {
      return component.components();
    };
    var replaceAt = function (component, replaceConfig, replaceState, replaceeIndex, replacer) {
      var children = contents(component);
      return Optional.from(children[replaceeIndex]).map(function (replacee) {
        remove(component, replaceConfig, replaceState, replacee);
        replacer.each(function (r) {
          insert(component, replaceConfig, function (p, c) {
            appendAt(p, c, replaceeIndex);
          }, r);
        });
        return replacee;
      });
    };
    var replaceBy = function (component, replaceConfig, replaceState, replaceePred, replacer) {
      var children = contents(component);
      return findIndex$1(children, replaceePred).bind(function (replaceeIndex) {
        return replaceAt(component, replaceConfig, replaceState, replaceeIndex, replacer);
      });
    };

    var ReplaceApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        append: append,
        prepend: prepend,
        remove: remove,
        replaceAt: replaceAt,
        replaceBy: replaceBy,
        set: set,
        contents: contents
    });

    var Replacing = create$5({
      fields: [],
      name: 'replacing',
      apis: ReplaceApis
    });

    var transpose = function (obj) {
      return tupleMap(obj, function (v, k) {
        return {
          k: v,
          v: k
        };
      });
    };
    var trace = function (items, byItem, byMenu, finish) {
      return get$c(byMenu, finish).bind(function (triggerItem) {
        return get$c(items, triggerItem).bind(function (triggerMenu) {
          var rest = trace(items, byItem, byMenu, triggerMenu);
          return Optional.some([triggerMenu].concat(rest));
        });
      }).getOr([]);
    };
    var generate = function (menus, expansions) {
      var items = {};
      each(menus, function (menuItems, menu) {
        each$1(menuItems, function (item) {
          items[item] = menu;
        });
      });
      var byItem = expansions;
      var byMenu = transpose(expansions);
      var menuPaths = map$1(byMenu, function (_triggerItem, submenu) {
        return [submenu].concat(trace(items, byItem, byMenu, submenu));
      });
      return map$1(items, function (menu) {
        return get$c(menuPaths, menu).getOr([menu]);
      });
    };

    var init$2 = function () {
      var expansions = Cell({});
      var menus = Cell({});
      var paths = Cell({});
      var primary = value();
      var directory = Cell({});
      var clear = function () {
        expansions.set({});
        menus.set({});
        paths.set({});
        primary.clear();
      };
      var isClear = function () {
        return primary.get().isNone();
      };
      var setMenuBuilt = function (menuName, built) {
        var _a;
        menus.set(__assign(__assign({}, menus.get()), (_a = {}, _a[menuName] = {
          type: 'prepared',
          menu: built
        }, _a)));
      };
      var setContents = function (sPrimary, sMenus, sExpansions, dir) {
        primary.set(sPrimary);
        expansions.set(sExpansions);
        menus.set(sMenus);
        directory.set(dir);
        var sPaths = generate(dir, sExpansions);
        paths.set(sPaths);
      };
      var getTriggeringItem = function (menuValue) {
        return find(expansions.get(), function (v, _k) {
          return v === menuValue;
        });
      };
      var getTriggerData = function (menuValue, getItemByValue, path) {
        return getPreparedMenu(menuValue).bind(function (menu) {
          return getTriggeringItem(menuValue).bind(function (triggeringItemValue) {
            return getItemByValue(triggeringItemValue).map(function (triggeredItem) {
              return {
                triggeredMenu: menu,
                triggeringItem: triggeredItem,
                triggeringPath: path
              };
            });
          });
        });
      };
      var getTriggeringPath = function (itemValue, getItemByValue) {
        var extraPath = filter$2(lookupItem(itemValue).toArray(), function (menuValue) {
          return getPreparedMenu(menuValue).isSome();
        });
        return get$c(paths.get(), itemValue).bind(function (path) {
          var revPath = reverse(extraPath.concat(path));
          var triggers = bind$3(revPath, function (menuValue, menuIndex) {
            return getTriggerData(menuValue, getItemByValue, revPath.slice(0, menuIndex + 1)).fold(function () {
              return is(primary.get(), menuValue) ? [] : [Optional.none()];
            }, function (data) {
              return [Optional.some(data)];
            });
          });
          return sequence(triggers);
        });
      };
      var expand = function (itemValue) {
        return get$c(expansions.get(), itemValue).map(function (menu) {
          var current = get$c(paths.get(), itemValue).getOr([]);
          return [menu].concat(current);
        });
      };
      var collapse = function (itemValue) {
        return get$c(paths.get(), itemValue).bind(function (path) {
          return path.length > 1 ? Optional.some(path.slice(1)) : Optional.none();
        });
      };
      var refresh = function (itemValue) {
        return get$c(paths.get(), itemValue);
      };
      var getPreparedMenu = function (menuValue) {
        return lookupMenu(menuValue).bind(extractPreparedMenu);
      };
      var lookupMenu = function (menuValue) {
        return get$c(menus.get(), menuValue);
      };
      var lookupItem = function (itemValue) {
        return get$c(expansions.get(), itemValue);
      };
      var otherMenus = function (path) {
        var menuValues = directory.get();
        return difference(keys(menuValues), path);
      };
      var getPrimary = function () {
        return primary.get().bind(getPreparedMenu);
      };
      var getMenus = function () {
        return menus.get();
      };
      return {
        setMenuBuilt: setMenuBuilt,
        setContents: setContents,
        expand: expand,
        refresh: refresh,
        collapse: collapse,
        lookupMenu: lookupMenu,
        lookupItem: lookupItem,
        otherMenus: otherMenus,
        getPrimary: getPrimary,
        getMenus: getMenus,
        clear: clear,
        isClear: isClear,
        getTriggeringPath: getTriggeringPath
      };
    };
    var extractPreparedMenu = function (prep) {
      return prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none();
    };
    var LayeredState = {
      init: init$2,
      extractPreparedMenu: extractPreparedMenu
    };

    var make$1 = function (detail, _rawUiSpec) {
      var submenuParentItems = value();
      var buildMenus = function (container, primaryName, menus) {
        return map$1(menus, function (spec, name) {
          var makeSketch = function () {
            return Menu.sketch(__assign(__assign({}, spec), {
              value: name,
              markers: detail.markers,
              fakeFocus: detail.fakeFocus,
              onHighlight: detail.onHighlight,
              focusManager: detail.fakeFocus ? highlights() : dom$2()
            }));
          };
          return name === primaryName ? {
            type: 'prepared',
            menu: container.getSystem().build(makeSketch())
          } : {
            type: 'notbuilt',
            nbMenu: makeSketch
          };
        });
      };
      var layeredState = LayeredState.init();
      var setup = function (container) {
        var componentMap = buildMenus(container, detail.data.primary, detail.data.menus);
        var directory = toDirectory();
        layeredState.setContents(detail.data.primary, componentMap, detail.data.expansions, directory);
        return layeredState.getPrimary();
      };
      var getItemValue = function (item) {
        return Representing.getValue(item).value;
      };
      var getItemByValue = function (_container, menus, itemValue) {
        return findMap(menus, function (menu) {
          if (!menu.getSystem().isConnected()) {
            return Optional.none();
          }
          var candidates = Highlighting.getCandidates(menu);
          return find$2(candidates, function (c) {
            return getItemValue(c) === itemValue;
          });
        });
      };
      var toDirectory = function (_container) {
        return map$1(detail.data.menus, function (data, _menuName) {
          return bind$3(data.items, function (item) {
            return item.type === 'separator' ? [] : [item.data.value];
          });
        });
      };
      var setActiveMenu = function (container, menu) {
        Highlighting.highlight(container, menu);
        Highlighting.getHighlighted(menu).orThunk(function () {
          return Highlighting.getFirst(menu);
        }).each(function (item) {
          dispatch(container, item.element, focusItem());
        });
      };
      var getMenus = function (state, menuValues) {
        return cat(map$2(menuValues, function (mv) {
          return state.lookupMenu(mv).bind(function (prep) {
            return prep.type === 'prepared' ? Optional.some(prep.menu) : Optional.none();
          });
        }));
      };
      var closeOthers = function (container, state, path) {
        var others = getMenus(state, state.otherMenus(path));
        each$1(others, function (o) {
          remove$1(o.element, [detail.markers.backgroundMenu]);
          if (!detail.stayInDom) {
            Replacing.remove(container, o);
          }
        });
      };
      var getSubmenuParents = function (container) {
        return submenuParentItems.get().getOrThunk(function () {
          var r = {};
          var items = descendants(container.element, '.' + detail.markers.item);
          var parentItems = filter$2(items, function (i) {
            return get$b(i, 'aria-haspopup') === 'true';
          });
          each$1(parentItems, function (i) {
            container.getSystem().getByDom(i).each(function (itemComp) {
              var key = getItemValue(itemComp);
              r[key] = itemComp;
            });
          });
          submenuParentItems.set(r);
          return r;
        });
      };
      var updateAriaExpansions = function (container, path) {
        var parentItems = getSubmenuParents(container);
        each(parentItems, function (v, k) {
          var expanded = contains$1(path, k);
          set$8(v.element, 'aria-expanded', expanded);
        });
      };
      var updateMenuPath = function (container, state, path) {
        return Optional.from(path[0]).bind(function (latestMenuName) {
          return state.lookupMenu(latestMenuName).bind(function (menuPrep) {
            if (menuPrep.type === 'notbuilt') {
              return Optional.none();
            } else {
              var activeMenu = menuPrep.menu;
              var rest = getMenus(state, path.slice(1));
              each$1(rest, function (r) {
                add$1(r.element, detail.markers.backgroundMenu);
              });
              if (!inBody(activeMenu.element)) {
                Replacing.append(container, premade(activeMenu));
              }
              remove$1(activeMenu.element, [detail.markers.backgroundMenu]);
              setActiveMenu(container, activeMenu);
              closeOthers(container, state, path);
              return Optional.some(activeMenu);
            }
          });
        });
      };
      var ExpandHighlightDecision;
      (function (ExpandHighlightDecision) {
        ExpandHighlightDecision[ExpandHighlightDecision['HighlightSubmenu'] = 0] = 'HighlightSubmenu';
        ExpandHighlightDecision[ExpandHighlightDecision['HighlightParent'] = 1] = 'HighlightParent';
      }(ExpandHighlightDecision || (ExpandHighlightDecision = {})));
      var buildIfRequired = function (container, menuName, menuPrep) {
        if (menuPrep.type === 'notbuilt') {
          var menu = container.getSystem().build(menuPrep.nbMenu());
          layeredState.setMenuBuilt(menuName, menu);
          return menu;
        } else {
          return menuPrep.menu;
        }
      };
      var expandRight = function (container, item, decision) {
        if (decision === void 0) {
          decision = ExpandHighlightDecision.HighlightSubmenu;
        }
        if (item.hasConfigured(Disabling) && Disabling.isDisabled(item)) {
          return Optional.some(item);
        } else {
          var value = getItemValue(item);
          return layeredState.expand(value).bind(function (path) {
            updateAriaExpansions(container, path);
            return Optional.from(path[0]).bind(function (menuName) {
              return layeredState.lookupMenu(menuName).bind(function (activeMenuPrep) {
                var activeMenu = buildIfRequired(container, menuName, activeMenuPrep);
                if (!inBody(activeMenu.element)) {
                  Replacing.append(container, premade(activeMenu));
                }
                detail.onOpenSubmenu(container, item, activeMenu, reverse(path));
                if (decision === ExpandHighlightDecision.HighlightSubmenu) {
                  Highlighting.highlightFirst(activeMenu);
                  return updateMenuPath(container, layeredState, path);
                } else {
                  Highlighting.dehighlightAll(activeMenu);
                  return Optional.some(item);
                }
              });
            });
          });
        }
      };
      var collapseLeft = function (container, item) {
        var value = getItemValue(item);
        return layeredState.collapse(value).bind(function (path) {
          updateAriaExpansions(container, path);
          return updateMenuPath(container, layeredState, path).map(function (activeMenu) {
            detail.onCollapseMenu(container, item, activeMenu);
            return activeMenu;
          });
        });
      };
      var updateView = function (container, item) {
        var value = getItemValue(item);
        return layeredState.refresh(value).bind(function (path) {
          updateAriaExpansions(container, path);
          return updateMenuPath(container, layeredState, path);
        });
      };
      var onRight = function (container, item) {
        return inside(item.element) ? Optional.none() : expandRight(container, item, ExpandHighlightDecision.HighlightSubmenu);
      };
      var onLeft = function (container, item) {
        return inside(item.element) ? Optional.none() : collapseLeft(container, item);
      };
      var onEscape = function (container, item) {
        return collapseLeft(container, item).orThunk(function () {
          return detail.onEscape(container, item).map(function () {
            return container;
          });
        });
      };
      var keyOnItem = function (f) {
        return function (container, simulatedEvent) {
          return closest$1(simulatedEvent.getSource(), '.' + detail.markers.item).bind(function (target) {
            return container.getSystem().getByDom(target).toOptional().bind(function (item) {
              return f(container, item).map(always);
            });
          });
        };
      };
      var events = derive$3([
        run(focus(), function (sandbox, simulatedEvent) {
          var item = simulatedEvent.event.item;
          layeredState.lookupItem(getItemValue(item)).each(function () {
            var menu = simulatedEvent.event.menu;
            Highlighting.highlight(sandbox, menu);
            var value = getItemValue(simulatedEvent.event.item);
            layeredState.refresh(value).each(function (path) {
              return closeOthers(sandbox, layeredState, path);
            });
          });
        }),
        runOnExecute(function (component, simulatedEvent) {
          var target = simulatedEvent.event.target;
          component.getSystem().getByDom(target).each(function (item) {
            var itemValue = getItemValue(item);
            if (itemValue.indexOf('collapse-item') === 0) {
              collapseLeft(component, item);
            }
            expandRight(component, item, ExpandHighlightDecision.HighlightSubmenu).fold(function () {
              detail.onExecute(component, item);
            }, noop);
          });
        }),
        runOnAttached(function (container, _simulatedEvent) {
          setup(container).each(function (primary) {
            Replacing.append(container, premade(primary));
            detail.onOpenMenu(container, primary);
            if (detail.highlightImmediately) {
              setActiveMenu(container, primary);
            }
          });
        })
      ].concat(detail.navigateOnHover ? [run(hover(), function (sandbox, simulatedEvent) {
          var item = simulatedEvent.event.item;
          updateView(sandbox, item);
          expandRight(sandbox, item, ExpandHighlightDecision.HighlightParent);
          detail.onHover(sandbox, item);
        })] : []));
      var getActiveItem = function (container) {
        return Highlighting.getHighlighted(container).bind(Highlighting.getHighlighted);
      };
      var collapseMenuApi = function (container) {
        getActiveItem(container).each(function (currentItem) {
          collapseLeft(container, currentItem);
        });
      };
      var highlightPrimary = function (container) {
        layeredState.getPrimary().each(function (primary) {
          setActiveMenu(container, primary);
        });
      };
      var extractMenuFromContainer = function (container) {
        return Optional.from(container.components()[0]).filter(function (comp) {
          return get$b(comp.element, 'role') === 'menu';
        });
      };
      var repositionMenus = function (container) {
        var maybeActivePrimary = layeredState.getPrimary().bind(function (primary) {
          return getActiveItem(container).bind(function (currentItem) {
            var itemValue = getItemValue(currentItem);
            var allMenus = values(layeredState.getMenus());
            var preparedMenus = cat(map$2(allMenus, LayeredState.extractPreparedMenu));
            return layeredState.getTriggeringPath(itemValue, function (v) {
              return getItemByValue(container, preparedMenus, v);
            });
          }).map(function (triggeringPath) {
            return {
              primary: primary,
              triggeringPath: triggeringPath
            };
          });
        });
        maybeActivePrimary.fold(function () {
          extractMenuFromContainer(container).each(function (primaryMenu) {
            detail.onRepositionMenu(container, primaryMenu, []);
          });
        }, function (_a) {
          var primary = _a.primary, triggeringPath = _a.triggeringPath;
          detail.onRepositionMenu(container, primary, triggeringPath);
        });
      };
      var apis = {
        collapseMenu: collapseMenuApi,
        highlightPrimary: highlightPrimary,
        repositionMenus: repositionMenus
      };
      return {
        uid: detail.uid,
        dom: detail.dom,
        markers: detail.markers,
        behaviours: augment(detail.tmenuBehaviours, [
          Keying.config({
            mode: 'special',
            onRight: keyOnItem(onRight),
            onLeft: keyOnItem(onLeft),
            onEscape: keyOnItem(onEscape),
            focusIn: function (container, _keyInfo) {
              layeredState.getPrimary().each(function (primary) {
                dispatch(container, primary.element, focusItem());
              });
            }
          }),
          Highlighting.config({
            highlightClass: detail.markers.selectedMenu,
            itemClass: detail.markers.menu
          }),
          Composing.config({
            find: function (container) {
              return Highlighting.getHighlighted(container);
            }
          }),
          Replacing.config({})
        ]),
        eventOrder: detail.eventOrder,
        apis: apis,
        events: events
      };
    };
    var collapseItem$1 = constant$1('collapse-item');

    var tieredData = function (primary, menus, expansions) {
      return {
        primary: primary,
        menus: menus,
        expansions: expansions
      };
    };
    var singleData = function (name, menu) {
      return {
        primary: name,
        menus: wrap(name, menu),
        expansions: {}
      };
    };
    var collapseItem = function (text) {
      return {
        value: generate$4(collapseItem$1()),
        meta: { text: text }
      };
    };
    var tieredMenu = single({
      name: 'TieredMenu',
      configFields: [
        onStrictKeyboardHandler('onExecute'),
        onStrictKeyboardHandler('onEscape'),
        onStrictHandler('onOpenMenu'),
        onStrictHandler('onOpenSubmenu'),
        onHandler('onRepositionMenu'),
        onHandler('onCollapseMenu'),
        defaulted('highlightImmediately', true),
        requiredObjOf('data', [
          required$1('primary'),
          required$1('menus'),
          required$1('expansions')
        ]),
        defaulted('fakeFocus', false),
        onHandler('onHighlight'),
        onHandler('onHover'),
        tieredMenuMarkers(),
        required$1('dom'),
        defaulted('navigateOnHover', true),
        defaulted('stayInDom', false),
        field$1('tmenuBehaviours', [
          Keying,
          Highlighting,
          Composing,
          Replacing
        ]),
        defaulted('eventOrder', {})
      ],
      apis: {
        collapseMenu: function (apis, tmenu) {
          apis.collapseMenu(tmenu);
        },
        highlightPrimary: function (apis, tmenu) {
          apis.highlightPrimary(tmenu);
        },
        repositionMenus: function (apis, tmenu) {
          apis.repositionMenus(tmenu);
        }
      },
      factory: make$1,
      extraApis: {
        tieredData: tieredData,
        singleData: singleData,
        collapseItem: collapseItem
      }
    });

    var findRoute = function (component, transConfig, transState, route) {
      return get$c(transConfig.routes, route.start).bind(function (sConfig) {
        return get$c(sConfig, route.destination);
      });
    };
    var getTransition = function (comp, transConfig, transState) {
      var route = getCurrentRoute(comp, transConfig);
      return route.bind(function (r) {
        return getTransitionOf(comp, transConfig, transState, r);
      });
    };
    var getTransitionOf = function (comp, transConfig, transState, route) {
      return findRoute(comp, transConfig, transState, route).bind(function (r) {
        return r.transition.map(function (t) {
          return {
            transition: t,
            route: r
          };
        });
      });
    };
    var disableTransition = function (comp, transConfig, transState) {
      getTransition(comp, transConfig, transState).each(function (routeTransition) {
        var t = routeTransition.transition;
        remove$3(comp.element, t.transitionClass);
        remove$6(comp.element, transConfig.destinationAttr);
      });
    };
    var getNewRoute = function (comp, transConfig, transState, destination) {
      return {
        start: get$b(comp.element, transConfig.stateAttr),
        destination: destination
      };
    };
    var getCurrentRoute = function (comp, transConfig, _transState) {
      var el = comp.element;
      return getOpt(el, transConfig.destinationAttr).map(function (destination) {
        return {
          start: get$b(comp.element, transConfig.stateAttr),
          destination: destination
        };
      });
    };
    var jumpTo = function (comp, transConfig, transState, destination) {
      disableTransition(comp, transConfig, transState);
      if (has$1(comp.element, transConfig.stateAttr) && get$b(comp.element, transConfig.stateAttr) !== destination) {
        transConfig.onFinish(comp, destination);
      }
      set$8(comp.element, transConfig.stateAttr, destination);
    };
    var fasttrack = function (comp, transConfig, _transState, _destination) {
      if (has$1(comp.element, transConfig.destinationAttr)) {
        getOpt(comp.element, transConfig.destinationAttr).each(function (destination) {
          set$8(comp.element, transConfig.stateAttr, destination);
        });
        remove$6(comp.element, transConfig.destinationAttr);
      }
    };
    var progressTo = function (comp, transConfig, transState, destination) {
      fasttrack(comp, transConfig);
      var route = getNewRoute(comp, transConfig, transState, destination);
      getTransitionOf(comp, transConfig, transState, route).fold(function () {
        jumpTo(comp, transConfig, transState, destination);
      }, function (routeTransition) {
        disableTransition(comp, transConfig, transState);
        var t = routeTransition.transition;
        add$1(comp.element, t.transitionClass);
        set$8(comp.element, transConfig.destinationAttr, destination);
      });
    };
    var getState = function (comp, transConfig, _transState) {
      return getOpt(comp.element, transConfig.stateAttr);
    };

    var TransitionApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        findRoute: findRoute,
        disableTransition: disableTransition,
        getCurrentRoute: getCurrentRoute,
        jumpTo: jumpTo,
        progressTo: progressTo,
        getState: getState
    });

    var events$1 = function (transConfig, transState) {
      return derive$3([
        run(transitionend(), function (component, simulatedEvent) {
          var raw = simulatedEvent.event.raw;
          getCurrentRoute(component, transConfig).each(function (route) {
            findRoute(component, transConfig, transState, route).each(function (rInfo) {
              rInfo.transition.each(function (rTransition) {
                if (raw.propertyName === rTransition.property) {
                  jumpTo(component, transConfig, transState, route.destination);
                  transConfig.onTransition(component, route);
                }
              });
            });
          });
        }),
        runOnAttached(function (comp, _se) {
          jumpTo(comp, transConfig, transState, transConfig.initialState);
        })
      ]);
    };

    var ActiveTransitioning = /*#__PURE__*/Object.freeze({
        __proto__: null,
        events: events$1
    });

    var TransitionSchema = [
      defaulted('destinationAttr', 'data-transitioning-destination'),
      defaulted('stateAttr', 'data-transitioning-state'),
      required$1('initialState'),
      onHandler('onTransition'),
      onHandler('onFinish'),
      requiredOf('routes', setOf(Result.value, setOf(Result.value, objOfOnly([optionObjOfOnly('transition', [
          required$1('property'),
          required$1('transitionClass')
        ])]))))
    ];

    var createRoutes = function (routes) {
      var r = {};
      each(routes, function (v, k) {
        var waypoints = k.split('<->');
        r[waypoints[0]] = wrap(waypoints[1], v);
        r[waypoints[1]] = wrap(waypoints[0], v);
      });
      return r;
    };
    var createBistate = function (first, second, transitions) {
      return wrapAll([
        {
          key: first,
          value: wrap(second, transitions)
        },
        {
          key: second,
          value: wrap(first, transitions)
        }
      ]);
    };
    var createTristate = function (first, second, third, transitions) {
      return wrapAll([
        {
          key: first,
          value: wrapAll([
            {
              key: second,
              value: transitions
            },
            {
              key: third,
              value: transitions
            }
          ])
        },
        {
          key: second,
          value: wrapAll([
            {
              key: first,
              value: transitions
            },
            {
              key: third,
              value: transitions
            }
          ])
        },
        {
          key: third,
          value: wrapAll([
            {
              key: first,
              value: transitions
            },
            {
              key: second,
              value: transitions
            }
          ])
        }
      ]);
    };
    var Transitioning = create$5({
      fields: TransitionSchema,
      name: 'transitioning',
      active: ActiveTransitioning,
      apis: TransitionApis,
      extra: {
        createRoutes: createRoutes,
        createBistate: createBistate,
        createTristate: createTristate
      }
    });

    var scrollableStyle = resolve('scrollable');
    var register$2 = function (element) {
      add$1(element, scrollableStyle);
    };
    var deregister = function (element) {
      remove$3(element, scrollableStyle);
    };
    var scrollable = scrollableStyle;

    var getValue = function (item) {
      return get$c(item, 'format').getOr(item.title);
    };
    var convert = function (formats, memMenuThunk) {
      var mainMenu = makeMenu('Styles', [].concat(map$2(formats.items, function (k) {
        return makeItem(getValue(k), k.title, k.isSelected(), k.getPreview(), hasNonNullableKey(formats.expansions, getValue(k)));
      })), memMenuThunk, false);
      var submenus = map$1(formats.menus, function (menuItems, menuName) {
        var items = map$2(menuItems, function (item) {
          return makeItem(getValue(item), item.title, item.isSelected !== undefined ? item.isSelected() : false, item.getPreview !== undefined ? item.getPreview() : '', hasNonNullableKey(formats.expansions, getValue(item)));
        });
        return makeMenu(menuName, items, memMenuThunk, true);
      });
      var menus = deepMerge(submenus, wrap('styles', mainMenu));
      var tmenu = tieredMenu.tieredData('styles', menus, formats.expansions);
      return { tmenu: tmenu };
    };
    var makeItem = function (value, text, selected, preview, isMenu) {
      return {
        data: {
          value: value,
          text: text
        },
        type: 'item',
        dom: {
          tag: 'div',
          classes: isMenu ? [resolve('styles-item-is-menu')] : []
        },
        toggling: {
          toggleOnExecute: false,
          toggleClass: resolve('format-matches'),
          selected: selected
        },
        itemBehaviours: derive$2(isMenu ? [] : [format(value, function (comp, status) {
            var toggle = status ? Toggling.on : Toggling.off;
            toggle(comp);
          })]),
        components: [{
            dom: {
              tag: 'div',
              attributes: { style: preview },
              innerHtml: text
            }
          }]
      };
    };
    var makeMenu = function (value, items, memMenuThunk, collapsable) {
      return {
        value: value,
        dom: { tag: 'div' },
        components: [
          Button.sketch({
            dom: {
              tag: 'div',
              classes: [resolve('styles-collapser')]
            },
            components: collapsable ? [
              {
                dom: {
                  tag: 'span',
                  classes: [resolve('styles-collapse-icon')]
                }
              },
              text(value)
            ] : [text(value)],
            action: function (item) {
              if (collapsable) {
                var comp = memMenuThunk().get(item);
                tieredMenu.collapseMenu(comp);
              }
            }
          }),
          {
            dom: {
              tag: 'div',
              classes: [resolve('styles-menu-items-container')]
            },
            components: [Menu.parts.items({})],
            behaviours: derive$2([config('adhoc-scrollable-menu', [
                runOnAttached(function (component, _simulatedEvent) {
                  set$5(component.element, 'overflow-y', 'auto');
                  set$5(component.element, '-webkit-overflow-scrolling', 'touch');
                  register$2(component.element);
                }),
                runOnDetached(function (component) {
                  remove$2(component.element, 'overflow-y');
                  remove$2(component.element, '-webkit-overflow-scrolling');
                  deregister(component.element);
                })
              ])])
          }
        ],
        items: items,
        menuBehaviours: derive$2([Transitioning.config({
            initialState: 'after',
            routes: Transitioning.createTristate('before', 'current', 'after', {
              transition: {
                property: 'transform',
                transitionClass: 'transitioning'
              }
            })
          })])
      };
    };
    var sketch$1 = function (settings) {
      var dataset = convert(settings.formats, function () {
        return memMenu;
      });
      var memMenu = record(tieredMenu.sketch({
        dom: {
          tag: 'div',
          classes: [resolve('styles-menu')]
        },
        components: [],
        fakeFocus: true,
        stayInDom: true,
        onExecute: function (_tmenu, item) {
          var v = Representing.getValue(item);
          settings.handle(item, v.value);
          return Optional.none();
        },
        onEscape: function () {
          return Optional.none();
        },
        onOpenMenu: function (container, menu) {
          var w = get$5(container.element);
          set$4(menu.element, w);
          Transitioning.jumpTo(menu, 'current');
        },
        onOpenSubmenu: function (container, item, submenu) {
          var w = get$5(container.element);
          var menu = ancestor(item.element, '[role="menu"]').getOrDie('hacky');
          var menuComp = container.getSystem().getByDom(menu).getOrDie();
          set$4(submenu.element, w);
          Transitioning.progressTo(menuComp, 'before');
          Transitioning.jumpTo(submenu, 'after');
          Transitioning.progressTo(submenu, 'current');
        },
        onCollapseMenu: function (container, item, menu) {
          var submenu = ancestor(item.element, '[role="menu"]').getOrDie('hacky');
          var submenuComp = container.getSystem().getByDom(submenu).getOrDie();
          Transitioning.progressTo(submenuComp, 'after');
          Transitioning.progressTo(menu, 'current');
        },
        navigateOnHover: false,
        highlightImmediately: true,
        data: dataset.tmenu,
        markers: {
          backgroundMenu: resolve('styles-background-menu'),
          menu: resolve('styles-menu'),
          selectedMenu: resolve('styles-selected-menu'),
          item: resolve('styles-item'),
          selectedItem: resolve('styles-selected-item')
        }
      }));
      return memMenu.asSpec();
    };

    var getFromExpandingItem = function (item) {
      var newItem = deepMerge(exclude(item, ['items']), { menu: true });
      var rest = expand(item.items);
      var newMenus = deepMerge(rest.menus, wrap(item.title, rest.items));
      var newExpansions = deepMerge(rest.expansions, wrap(item.title, item.title));
      return {
        item: newItem,
        menus: newMenus,
        expansions: newExpansions
      };
    };
    var getFromItem = function (item) {
      return hasNonNullableKey(item, 'items') ? getFromExpandingItem(item) : {
        item: item,
        menus: {},
        expansions: {}
      };
    };
    var expand = function (items) {
      return foldr(items, function (acc, item) {
        var newData = getFromItem(item);
        return {
          menus: deepMerge(acc.menus, newData.menus),
          items: [newData.item].concat(acc.items),
          expansions: deepMerge(acc.expansions, newData.expansions)
        };
      }, {
        menus: {},
        expansions: {},
        items: []
      });
    };

    var register$1 = function (editor) {
      var isSelectedFor = function (format) {
        return function () {
          return editor.formatter.match(format);
        };
      };
      var getPreview = function (format) {
        return function () {
          return editor.formatter.getCssText(format);
        };
      };
      var enrichSupported = function (item) {
        return deepMerge(item, {
          isSelected: isSelectedFor(item.format),
          getPreview: getPreview(item.format)
        });
      };
      var enrichMenu = function (item) {
        return deepMerge(item, {
          isSelected: never,
          getPreview: constant$1('')
        });
      };
      var enrichCustom = function (item) {
        var formatName = generate$4(item.title);
        var newItem = deepMerge(item, {
          format: formatName,
          isSelected: isSelectedFor(formatName),
          getPreview: getPreview(formatName)
        });
        editor.formatter.register(formatName, newItem);
        return newItem;
      };
      var doEnrich = function (items) {
        return map$2(items, function (item) {
          if (hasNonNullableKey(item, 'items')) {
            var newItems = doEnrich(item.items);
            return deepMerge(enrichMenu(item), { items: newItems });
          } else if (hasNonNullableKey(item, 'format')) {
            return enrichSupported(item);
          } else {
            return enrichCustom(item);
          }
        });
      };
      return doEnrich(getStyleFormats(editor));
    };
    var prune = function (editor, formats) {
      var doPrune = function (items) {
        return bind$3(items, function (item) {
          if (item.items !== undefined) {
            var newItems = doPrune(item.items);
            return newItems.length > 0 ? [item] : [];
          } else {
            var keep = hasNonNullableKey(item, 'format') ? editor.formatter.canApply(item.format) : true;
            return keep ? [item] : [];
          }
        });
      };
      var prunedItems = doPrune(formats);
      return expand(prunedItems);
    };
    var ui = function (editor, formats, onDone) {
      var pruned = prune(editor, formats);
      return sketch$1({
        formats: pruned,
        handle: function (item, value) {
          editor.undoManager.transact(function () {
            if (Toggling.isOn(item)) {
              editor.formatter.remove(value);
            } else {
              editor.formatter.apply(value);
            }
          });
          onDone();
        }
      });
    };

    var extract = function (rawToolbar) {
      var toolbar = rawToolbar.replace(/\|/g, ' ').trim();
      return toolbar.length > 0 ? toolbar.split(/\s+/) : [];
    };
    var identifyFromArray = function (toolbar) {
      return bind$3(toolbar, function (item) {
        return isArray(item) ? identifyFromArray(item) : extract(item);
      });
    };
    var identify = function (editor) {
      var toolbar = getToolbar(editor);
      return isArray(toolbar) ? identifyFromArray(toolbar) : extract(toolbar);
    };
    var setup$3 = function (realm, editor) {
      var commandSketch = function (name) {
        return function () {
          return forToolbarCommand(editor, name);
        };
      };
      var stateCommandSketch = function (name) {
        return function () {
          return forToolbarStateCommand(editor, name);
        };
      };
      var actionSketch = function (name, query, action) {
        return function () {
          return forToolbarStateAction(editor, name, query, action);
        };
      };
      var undo = commandSketch('undo');
      var redo = commandSketch('redo');
      var bold = stateCommandSketch('bold');
      var italic = stateCommandSketch('italic');
      var underline = stateCommandSketch('underline');
      var removeformat = commandSketch('removeformat');
      var link = function () {
        return sketch$2(realm, editor);
      };
      var unlink = actionSketch('unlink', 'link', function () {
        editor.execCommand('unlink', null, false);
      });
      var image = function () {
        return sketch$5(editor);
      };
      var bullist = actionSketch('unordered-list', 'ul', function () {
        editor.execCommand('InsertUnorderedList', null, false);
      });
      var numlist = actionSketch('ordered-list', 'ol', function () {
        editor.execCommand('InsertOrderedList', null, false);
      });
      var fontsizeselect = function () {
        return sketch$6(realm, editor);
      };
      var forecolor = function () {
        return sketch$8(realm, editor);
      };
      var styleFormats = register$1(editor);
      var styleFormatsMenu = function () {
        return ui(editor, styleFormats, function () {
          editor.fire('scrollIntoView');
        });
      };
      var styleselect = function () {
        return forToolbar('style-formats', function (button) {
          editor.fire('toReading');
          realm.dropup.appear(styleFormatsMenu, Toggling.on, button);
        }, derive$2([
          Toggling.config({
            toggleClass: resolve('toolbar-button-selected'),
            toggleOnExecute: false,
            aria: { mode: 'pressed' }
          }),
          Receiving.config({
            channels: wrapAll([
              receive(orientationChanged, Toggling.off),
              receive(dropupDismissed, Toggling.off)
            ])
          })
        ]), editor);
      };
      var feature = function (prereq, sketch) {
        return {
          isSupported: function () {
            var buttons = editor.ui.registry.getAll().buttons;
            return prereq.forall(function (p) {
              return hasNonNullableKey(buttons, p);
            });
          },
          sketch: sketch
        };
      };
      return {
        undo: feature(Optional.none(), undo),
        redo: feature(Optional.none(), redo),
        bold: feature(Optional.none(), bold),
        italic: feature(Optional.none(), italic),
        underline: feature(Optional.none(), underline),
        removeformat: feature(Optional.none(), removeformat),
        link: feature(Optional.none(), link),
        unlink: feature(Optional.none(), unlink),
        image: feature(Optional.none(), image),
        bullist: feature(Optional.some('bullist'), bullist),
        numlist: feature(Optional.some('numlist'), numlist),
        fontsizeselect: feature(Optional.none(), fontsizeselect),
        forecolor: feature(Optional.none(), forecolor),
        styleselect: feature(Optional.none(), styleselect)
      };
    };
    var detect = function (editor, features) {
      var itemNames = identify(editor);
      var present = {};
      return bind$3(itemNames, function (iName) {
        var r = !hasNonNullableKey(present, iName) && hasNonNullableKey(features, iName) && features[iName].isSupported() ? [features[iName].sketch()] : [];
        present[iName] = true;
        return r;
      });
    };

    var mkEvent = function (target, x, y, stop, prevent, kill, raw) {
      return {
        target: target,
        x: x,
        y: y,
        stop: stop,
        prevent: prevent,
        kill: kill,
        raw: raw
      };
    };
    var fromRawEvent = function (rawEvent) {
      var target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target));
      var stop = function () {
        return rawEvent.stopPropagation();
      };
      var prevent = function () {
        return rawEvent.preventDefault();
      };
      var kill = compose(prevent, stop);
      return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent);
    };
    var handle = function (filter, handler) {
      return function (rawEvent) {
        if (filter(rawEvent)) {
          handler(fromRawEvent(rawEvent));
        }
      };
    };
    var binder = function (element, event, filter, handler, useCapture) {
      var wrapped = handle(filter, handler);
      element.dom.addEventListener(event, wrapped, useCapture);
      return { unbind: curry(unbind, element, event, wrapped, useCapture) };
    };
    var bind$1 = function (element, event, filter, handler) {
      return binder(element, event, filter, handler, false);
    };
    var capture$1 = function (element, event, filter, handler) {
      return binder(element, event, filter, handler, true);
    };
    var unbind = function (element, event, handler, useCapture) {
      element.dom.removeEventListener(event, handler, useCapture);
    };

    var filter = always;
    var bind = function (element, event, handler) {
      return bind$1(element, event, filter, handler);
    };
    var capture = function (element, event, handler) {
      return capture$1(element, event, filter, handler);
    };

    var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay');

    var INTERVAL = 50;
    var INSURANCE = 1000 / INTERVAL;
    var get$1 = function (outerWindow) {
      var isPortrait = outerWindow.matchMedia('(orientation: portrait)').matches;
      return { isPortrait: constant$1(isPortrait) };
    };
    var getActualWidth = function (outerWindow) {
      var isIos = detect$1().os.isiOS();
      var isPortrait = get$1(outerWindow).isPortrait();
      return isIos && !isPortrait ? outerWindow.screen.height : outerWindow.screen.width;
    };
    var onChange = function (outerWindow, listeners) {
      var win = SugarElement.fromDom(outerWindow);
      var poller = null;
      var change = function () {
        global$2.clearInterval(poller);
        var orientation = get$1(outerWindow);
        listeners.onChange(orientation);
        onAdjustment(function () {
          listeners.onReady(orientation);
        });
      };
      var orientationHandle = bind(win, 'orientationchange', change);
      var onAdjustment = function (f) {
        global$2.clearInterval(poller);
        var flag = outerWindow.innerHeight;
        var insurance = 0;
        poller = global$2.setInterval(function () {
          if (flag !== outerWindow.innerHeight) {
            global$2.clearInterval(poller);
            f(Optional.some(outerWindow.innerHeight));
          } else if (insurance > INSURANCE) {
            global$2.clearInterval(poller);
            f(Optional.none());
          }
          insurance++;
        }, INTERVAL);
      };
      var destroy = function () {
        orientationHandle.unbind();
      };
      return {
        onAdjustment: onAdjustment,
        destroy: destroy
      };
    };

    var setStart = function (rng, situ) {
      situ.fold(function (e) {
        rng.setStartBefore(e.dom);
      }, function (e, o) {
        rng.setStart(e.dom, o);
      }, function (e) {
        rng.setStartAfter(e.dom);
      });
    };
    var setFinish = function (rng, situ) {
      situ.fold(function (e) {
        rng.setEndBefore(e.dom);
      }, function (e, o) {
        rng.setEnd(e.dom, o);
      }, function (e) {
        rng.setEndAfter(e.dom);
      });
    };
    var relativeToNative = function (win, startSitu, finishSitu) {
      var range = win.document.createRange();
      setStart(range, startSitu);
      setFinish(range, finishSitu);
      return range;
    };
    var exactToNative = function (win, start, soffset, finish, foffset) {
      var rng = win.document.createRange();
      rng.setStart(start.dom, soffset);
      rng.setEnd(finish.dom, foffset);
      return rng;
    };
    var toRect$1 = function (rect) {
      return {
        left: rect.left,
        top: rect.top,
        right: rect.right,
        bottom: rect.bottom,
        width: rect.width,
        height: rect.height
      };
    };
    var getFirstRect$1 = function (rng) {
      var rects = rng.getClientRects();
      var rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect();
      return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect$1) : Optional.none();
    };

    var adt$3 = Adt.generate([
      {
        ltr: [
          'start',
          'soffset',
          'finish',
          'foffset'
        ]
      },
      {
        rtl: [
          'start',
          'soffset',
          'finish',
          'foffset'
        ]
      }
    ]);
    var fromRange = function (win, type, range) {
      return type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
    };
    var getRanges = function (win, selection) {
      return selection.match({
        domRange: function (rng) {
          return {
            ltr: constant$1(rng),
            rtl: Optional.none
          };
        },
        relative: function (startSitu, finishSitu) {
          return {
            ltr: cached(function () {
              return relativeToNative(win, startSitu, finishSitu);
            }),
            rtl: cached(function () {
              return Optional.some(relativeToNative(win, finishSitu, startSitu));
            })
          };
        },
        exact: function (start, soffset, finish, foffset) {
          return {
            ltr: cached(function () {
              return exactToNative(win, start, soffset, finish, foffset);
            }),
            rtl: cached(function () {
              return Optional.some(exactToNative(win, finish, foffset, start, soffset));
            })
          };
        }
      });
    };
    var doDiagnose = function (win, ranges) {
      var rng = ranges.ltr();
      if (rng.collapsed) {
        var reversed = ranges.rtl().filter(function (rev) {
          return rev.collapsed === false;
        });
        return reversed.map(function (rev) {
          return adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset);
        }).getOrThunk(function () {
          return fromRange(win, adt$3.ltr, rng);
        });
      } else {
        return fromRange(win, adt$3.ltr, rng);
      }
    };
    var diagnose = function (win, selection) {
      var ranges = getRanges(win, selection);
      return doDiagnose(win, ranges);
    };
    var asLtrRange = function (win, selection) {
      var diagnosis = diagnose(win, selection);
      return diagnosis.match({
        ltr: function (start, soffset, finish, foffset) {
          var rng = win.document.createRange();
          rng.setStart(start.dom, soffset);
          rng.setEnd(finish.dom, foffset);
          return rng;
        },
        rtl: function (start, soffset, finish, foffset) {
          var rng = win.document.createRange();
          rng.setStart(finish.dom, foffset);
          rng.setEnd(start.dom, soffset);
          return rng;
        }
      });
    };
    adt$3.ltr;
    adt$3.rtl;

    var create$3 = function (start, soffset, finish, foffset) {
      return {
        start: start,
        soffset: soffset,
        finish: finish,
        foffset: foffset
      };
    };
    var SimRange = { create: create$3 };

    var NodeValue = function (is, name) {
      var get = function (element) {
        if (!is(element)) {
          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
        }
        return getOption(element).getOr('');
      };
      var getOption = function (element) {
        return is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
      };
      var set = function (element, value) {
        if (!is(element)) {
          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
        }
        element.dom.nodeValue = value;
      };
      return {
        get: get,
        getOption: getOption,
        set: set
      };
    };

    var api = NodeValue(isText, 'text');
    var getOption = function (element) {
      return api.getOption(element);
    };

    var getEnd = function (element) {
      return name$1(element) === 'img' ? 1 : getOption(element).fold(function () {
        return children(element).length;
      }, function (v) {
        return v.length;
      });
    };

    var adt$2 = Adt.generate([
      { before: ['element'] },
      {
        on: [
          'element',
          'offset'
        ]
      },
      { after: ['element'] }
    ]);
    var cata = function (subject, onBefore, onOn, onAfter) {
      return subject.fold(onBefore, onOn, onAfter);
    };
    var getStart$1 = function (situ) {
      return situ.fold(identity, identity, identity);
    };
    var before = adt$2.before;
    var on = adt$2.on;
    var after$1 = adt$2.after;
    var Situ = {
      before: before,
      on: on,
      after: after$1,
      cata: cata,
      getStart: getStart$1
    };

    var adt$1 = Adt.generate([
      { domRange: ['rng'] },
      {
        relative: [
          'startSitu',
          'finishSitu'
        ]
      },
      {
        exact: [
          'start',
          'soffset',
          'finish',
          'foffset'
        ]
      }
    ]);
    var exactFromRange = function (simRange) {
      return adt$1.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
    };
    var getStart = function (selection) {
      return selection.match({
        domRange: function (rng) {
          return SugarElement.fromDom(rng.startContainer);
        },
        relative: function (startSitu, _finishSitu) {
          return Situ.getStart(startSitu);
        },
        exact: function (start, _soffset, _finish, _foffset) {
          return start;
        }
      });
    };
    var domRange = adt$1.domRange;
    var relative = adt$1.relative;
    var exact = adt$1.exact;
    var getWin$1 = function (selection) {
      var start = getStart(selection);
      return defaultView(start);
    };
    var range = SimRange.create;
    var SimSelection = {
      domRange: domRange,
      relative: relative,
      exact: exact,
      exactFromRange: exactFromRange,
      getWin: getWin$1,
      range: range
    };

    var beforeSpecial = function (element, offset) {
      var name = name$1(element);
      if ('input' === name) {
        return Situ.after(element);
      } else if (!contains$1([
          'br',
          'img'
        ], name)) {
        return Situ.on(element, offset);
      } else {
        return offset === 0 ? Situ.before(element) : Situ.after(element);
      }
    };
    var preprocessExact = function (start, soffset, finish, foffset) {
      var startSitu = beforeSpecial(start, soffset);
      var finishSitu = beforeSpecial(finish, foffset);
      return SimSelection.relative(startSitu, finishSitu);
    };

    var makeRange = function (start, soffset, finish, foffset) {
      var doc = owner$2(start);
      var rng = doc.dom.createRange();
      rng.setStart(start.dom, soffset);
      rng.setEnd(finish.dom, foffset);
      return rng;
    };
    var after = function (start, soffset, finish, foffset) {
      var r = makeRange(start, soffset, finish, foffset);
      var same = eq(start, finish) && soffset === foffset;
      return r.collapsed && !same;
    };

    var getNativeSelection = function (win) {
      return Optional.from(win.getSelection());
    };
    var doSetNativeRange = function (win, rng) {
      getNativeSelection(win).each(function (selection) {
        selection.removeAllRanges();
        selection.addRange(rng);
      });
    };
    var doSetRange = function (win, start, soffset, finish, foffset) {
      var rng = exactToNative(win, start, soffset, finish, foffset);
      doSetNativeRange(win, rng);
    };
    var setLegacyRtlRange = function (win, selection, start, soffset, finish, foffset) {
      selection.collapse(start.dom, soffset);
      selection.extend(finish.dom, foffset);
    };
    var setRangeFromRelative = function (win, relative) {
      return diagnose(win, relative).match({
        ltr: function (start, soffset, finish, foffset) {
          doSetRange(win, start, soffset, finish, foffset);
        },
        rtl: function (start, soffset, finish, foffset) {
          getNativeSelection(win).each(function (selection) {
            if (selection.setBaseAndExtent) {
              selection.setBaseAndExtent(start.dom, soffset, finish.dom, foffset);
            } else if (selection.extend) {
              try {
                setLegacyRtlRange(win, selection, start, soffset, finish, foffset);
              } catch (e) {
                doSetRange(win, finish, foffset, start, soffset);
              }
            } else {
              doSetRange(win, finish, foffset, start, soffset);
            }
          });
        }
      });
    };
    var setExact = function (win, start, soffset, finish, foffset) {
      var relative = preprocessExact(start, soffset, finish, foffset);
      setRangeFromRelative(win, relative);
    };
    var readRange = function (selection) {
      if (selection.rangeCount > 0) {
        var firstRng = selection.getRangeAt(0);
        var lastRng = selection.getRangeAt(selection.rangeCount - 1);
        return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset));
      } else {
        return Optional.none();
      }
    };
    var doGetExact = function (selection) {
      if (selection.anchorNode === null || selection.focusNode === null) {
        return readRange(selection);
      } else {
        var anchor = SugarElement.fromDom(selection.anchorNode);
        var focus_1 = SugarElement.fromDom(selection.focusNode);
        return after(anchor, selection.anchorOffset, focus_1, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus_1, selection.focusOffset)) : readRange(selection);
      }
    };
    var getExact = function (win) {
      return getNativeSelection(win).filter(function (sel) {
        return sel.rangeCount > 0;
      }).bind(doGetExact);
    };
    var get = function (win) {
      return getExact(win).map(function (range) {
        return SimSelection.exact(range.start, range.soffset, range.finish, range.foffset);
      });
    };
    var getFirstRect = function (win, selection) {
      var rng = asLtrRange(win, selection);
      return getFirstRect$1(rng);
    };
    var clear = function (win) {
      getNativeSelection(win).each(function (selection) {
        return selection.removeAllRanges();
      });
    };

    var getBodyFromFrame = function (frame) {
      return Optional.some(SugarElement.fromDom(frame.dom.contentWindow.document.body));
    };
    var getDocFromFrame = function (frame) {
      return Optional.some(SugarElement.fromDom(frame.dom.contentWindow.document));
    };
    var getWinFromFrame = function (frame) {
      return Optional.from(frame.dom.contentWindow);
    };
    var getSelectionFromFrame = function (frame) {
      var optWin = getWinFromFrame(frame);
      return optWin.bind(getExact);
    };
    var getFrame = function (editor) {
      return editor.getFrame();
    };
    var getOrDerive = function (name, f) {
      return function (editor) {
        var g = editor[name].getOrThunk(function () {
          var frame = getFrame(editor);
          return function () {
            return f(frame);
          };
        });
        return g();
      };
    };
    var getOrListen = function (editor, doc, name, type) {
      return editor[name].getOrThunk(function () {
        return function (handler) {
          return bind(doc, type, handler);
        };
      });
    };
    var getActiveApi = function (editor) {
      var frame = getFrame(editor);
      var tryFallbackBox = function (win) {
        var isCollapsed = function (sel) {
          return eq(sel.start, sel.finish) && sel.soffset === sel.foffset;
        };
        var toStartRect = function (sel) {
          var rect = sel.start.dom.getBoundingClientRect();
          return rect.width > 0 || rect.height > 0 ? Optional.some(rect) : Optional.none();
        };
        return getExact(win).filter(isCollapsed).bind(toStartRect);
      };
      return getBodyFromFrame(frame).bind(function (body) {
        return getDocFromFrame(frame).bind(function (doc) {
          return getWinFromFrame(frame).map(function (win) {
            var html = SugarElement.fromDom(doc.dom.documentElement);
            var getCursorBox = editor.getCursorBox.getOrThunk(function () {
              return function () {
                return get(win).bind(function (sel) {
                  return getFirstRect(win, sel).orThunk(function () {
                    return tryFallbackBox(win);
                  });
                });
              };
            });
            var setSelection = editor.setSelection.getOrThunk(function () {
              return function (start, soffset, finish, foffset) {
                setExact(win, start, soffset, finish, foffset);
              };
            });
            var clearSelection = editor.clearSelection.getOrThunk(function () {
              return function () {
                clear(win);
              };
            });
            return {
              body: body,
              doc: doc,
              win: win,
              html: html,
              getSelection: curry(getSelectionFromFrame, frame),
              setSelection: setSelection,
              clearSelection: clearSelection,
              frame: frame,
              onKeyup: getOrListen(editor, doc, 'onKeyup', 'keyup'),
              onNodeChanged: getOrListen(editor, doc, 'onNodeChanged', 'SelectionChange'),
              onDomChanged: editor.onDomChanged,
              onScrollToCursor: editor.onScrollToCursor,
              onScrollToElement: editor.onScrollToElement,
              onToReading: editor.onToReading,
              onToEditing: editor.onToEditing,
              onToolbarScrollStart: editor.onToolbarScrollStart,
              onTouchContent: editor.onTouchContent,
              onTapContent: editor.onTapContent,
              onTouchToolstrip: editor.onTouchToolstrip,
              getCursorBox: getCursorBox
            };
          });
        });
      });
    };
    var getWin = getOrDerive('getWin', getWinFromFrame);

    var tag = function () {
      var head = first$1('head').getOrDie();
      var nu = function () {
        var meta = SugarElement.fromTag('meta');
        set$8(meta, 'name', 'viewport');
        append$2(head, meta);
        return meta;
      };
      var element = first$1('meta[name="viewport"]').getOrThunk(nu);
      var backup = get$b(element, 'content');
      var maximize = function () {
        set$8(element, 'content', 'width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0');
      };
      var restore = function () {
        if (backup !== undefined && backup !== null && backup.length > 0) {
          set$8(element, 'content', backup);
        } else {
          set$8(element, 'content', 'user-scalable=yes');
        }
      };
      return {
        maximize: maximize,
        restore: restore
      };
    };

    var attr = 'data-ephox-mobile-fullscreen-style';
    var siblingStyles = 'display:none!important;';
    var ancestorPosition = 'position:absolute!important;';
    var ancestorStyles = 'top:0!important;left:0!important;margin:0!important;padding:0!important;width:100%!important;height:100%!important;overflow:visible!important;';
    var bgFallback = 'background-color:rgb(255,255,255)!important;';
    var isAndroid = detect$1().os.isAndroid();
    var matchColor = function (editorBody) {
      var color = get$8(editorBody, 'background-color');
      return color !== undefined && color !== '' ? 'background-color:' + color + '!important' : bgFallback;
    };
    var clobberStyles = function (container, editorBody) {
      var gatherSiblings = function (element) {
        return siblings(element, '*');
      };
      var clobber = function (clobberStyle) {
        return function (element) {
          var styles = get$b(element, 'style');
          var backup = styles === undefined ? 'no-styles' : styles.trim();
          if (backup === clobberStyle) {
            return;
          } else {
            set$8(element, attr, backup);
            set$8(element, 'style', clobberStyle);
          }
        };
      };
      var ancestors$1 = ancestors(container, '*');
      var siblings$1 = bind$3(ancestors$1, gatherSiblings);
      var bgColor = matchColor(editorBody);
      each$1(siblings$1, clobber(siblingStyles));
      each$1(ancestors$1, clobber(ancestorPosition + ancestorStyles + bgColor));
      var containerStyles = isAndroid === true ? '' : ancestorPosition;
      clobber(containerStyles + ancestorStyles + bgColor)(container);
    };
    var restoreStyles = function () {
      var clobberedEls = all('[' + attr + ']');
      each$1(clobberedEls, function (element) {
        var restore = get$b(element, attr);
        if (restore !== 'no-styles') {
          set$8(element, 'style', restore);
        } else {
          remove$6(element, 'style');
        }
        remove$6(element, attr);
      });
    };

    var DelayedFunction = function (fun, delay) {
      var ref = null;
      var schedule = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        ref = setTimeout(function () {
          fun.apply(null, args);
          ref = null;
        }, delay);
      };
      var cancel = function () {
        if (ref !== null) {
          clearTimeout(ref);
          ref = null;
        }
      };
      return {
        cancel: cancel,
        schedule: schedule
      };
    };

    var SIGNIFICANT_MOVE = 5;
    var LONGPRESS_DELAY = 400;
    var getTouch = function (event) {
      var raw = event.raw;
      if (raw.touches === undefined || raw.touches.length !== 1) {
        return Optional.none();
      }
      return Optional.some(raw.touches[0]);
    };
    var isFarEnough = function (touch, data) {
      var distX = Math.abs(touch.clientX - data.x);
      var distY = Math.abs(touch.clientY - data.y);
      return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
    };
    var monitor$1 = function (settings) {
      var startData = value();
      var longpressFired = Cell(false);
      var longpress$1 = DelayedFunction(function (event) {
        settings.triggerEvent(longpress(), event);
        longpressFired.set(true);
      }, LONGPRESS_DELAY);
      var handleTouchstart = function (event) {
        getTouch(event).each(function (touch) {
          longpress$1.cancel();
          var data = {
            x: touch.clientX,
            y: touch.clientY,
            target: event.target
          };
          longpress$1.schedule(event);
          longpressFired.set(false);
          startData.set(data);
        });
        return Optional.none();
      };
      var handleTouchmove = function (event) {
        longpress$1.cancel();
        getTouch(event).each(function (touch) {
          startData.on(function (data) {
            if (isFarEnough(touch, data)) {
              startData.clear();
            }
          });
        });
        return Optional.none();
      };
      var handleTouchend = function (event) {
        longpress$1.cancel();
        var isSame = function (data) {
          return eq(data.target, event.target);
        };
        return startData.get().filter(isSame).map(function (_data) {
          if (longpressFired.get()) {
            event.prevent();
            return false;
          } else {
            return settings.triggerEvent(tap(), event);
          }
        });
      };
      var handlers = wrapAll([
        {
          key: touchstart(),
          value: handleTouchstart
        },
        {
          key: touchmove(),
          value: handleTouchmove
        },
        {
          key: touchend(),
          value: handleTouchend
        }
      ]);
      var fireIfReady = function (event, type) {
        return get$c(handlers, type).bind(function (handler) {
          return handler(event);
        });
      };
      return { fireIfReady: fireIfReady };
    };

    var monitor = function (editorApi) {
      var tapEvent = monitor$1({
        triggerEvent: function (type, evt) {
          editorApi.onTapContent(evt);
        }
      });
      var onTouchend = function () {
        return bind(editorApi.body, 'touchend', function (evt) {
          tapEvent.fireIfReady(evt, 'touchend');
        });
      };
      var onTouchmove = function () {
        return bind(editorApi.body, 'touchmove', function (evt) {
          tapEvent.fireIfReady(evt, 'touchmove');
        });
      };
      var fireTouchstart = function (evt) {
        tapEvent.fireIfReady(evt, 'touchstart');
      };
      return {
        fireTouchstart: fireTouchstart,
        onTouchend: onTouchend,
        onTouchmove: onTouchmove
      };
    };

    var isAndroid6 = detect$1().os.version.major >= 6;
    var initEvents$1 = function (editorApi, toolstrip, alloy) {
      var tapping = monitor(editorApi);
      var outerDoc = owner$2(toolstrip);
      var isRanged = function (sel) {
        return !eq(sel.start, sel.finish) || sel.soffset !== sel.foffset;
      };
      var hasRangeInUi = function () {
        return active(outerDoc).filter(function (input) {
          return name$1(input) === 'input';
        }).exists(function (input) {
          return input.dom.selectionStart !== input.dom.selectionEnd;
        });
      };
      var updateMargin = function () {
        var rangeInContent = editorApi.doc.dom.hasFocus() && editorApi.getSelection().exists(isRanged);
        alloy.getByDom(toolstrip).each((rangeInContent || hasRangeInUi()) === true ? Toggling.on : Toggling.off);
      };
      var listeners = [
        bind(editorApi.body, 'touchstart', function (evt) {
          editorApi.onTouchContent();
          tapping.fireTouchstart(evt);
        }),
        tapping.onTouchmove(),
        tapping.onTouchend(),
        bind(toolstrip, 'touchstart', function (_evt) {
          editorApi.onTouchToolstrip();
        }),
        editorApi.onToReading(function () {
          blur$1(editorApi.body);
        }),
        editorApi.onToEditing(noop),
        editorApi.onScrollToCursor(function (tinyEvent) {
          tinyEvent.preventDefault();
          editorApi.getCursorBox().each(function (bounds) {
            var cWin = editorApi.win;
            var isOutside = bounds.top > cWin.innerHeight || bounds.bottom > cWin.innerHeight;
            var cScrollBy = isOutside ? bounds.bottom - cWin.innerHeight + 50 : 0;
            if (cScrollBy !== 0) {
              cWin.scrollTo(cWin.pageXOffset, cWin.pageYOffset + cScrollBy);
            }
          });
        })
      ].concat(isAndroid6 === true ? [] : [
        bind(SugarElement.fromDom(editorApi.win), 'blur', function () {
          alloy.getByDom(toolstrip).each(Toggling.off);
        }),
        bind(outerDoc, 'select', updateMargin),
        bind(editorApi.doc, 'selectionchange', updateMargin)
      ]);
      var destroy = function () {
        each$1(listeners, function (l) {
          l.unbind();
        });
      };
      return { destroy: destroy };
    };

    var safeParse = function (element, attribute) {
      var parsed = parseInt(get$b(element, attribute), 10);
      return isNaN(parsed) ? 0 : parsed;
    };

    var COLLAPSED_WIDTH = 2;
    var collapsedRect = function (rect) {
      return __assign(__assign({}, rect), { width: COLLAPSED_WIDTH });
    };
    var toRect = function (rawRect) {
      return {
        left: rawRect.left,
        top: rawRect.top,
        right: rawRect.right,
        bottom: rawRect.bottom,
        width: rawRect.width,
        height: rawRect.height
      };
    };
    var getRectsFromRange = function (range) {
      if (!range.collapsed) {
        return map$2(range.getClientRects(), toRect);
      } else {
        var start_1 = SugarElement.fromDom(range.startContainer);
        return parent(start_1).bind(function (parent) {
          var selection = SimSelection.exact(start_1, range.startOffset, parent, getEnd(parent));
          var optRect = getFirstRect(range.startContainer.ownerDocument.defaultView, selection);
          return optRect.map(collapsedRect).map(pure$2);
        }).getOr([]);
      }
    };
    var getRectangles = function (cWin) {
      var sel = cWin.getSelection();
      return sel !== undefined && sel.rangeCount > 0 ? getRectsFromRange(sel.getRangeAt(0)) : [];
    };

    var autocompleteHack = function () {
      return function (f) {
        global$2.setTimeout(function () {
          f();
        }, 0);
      };
    };
    var resume$1 = function (cWin) {
      cWin.focus();
      var iBody = SugarElement.fromDom(cWin.document.body);
      var inInput = active().exists(function (elem) {
        return contains$1([
          'input',
          'textarea'
        ], name$1(elem));
      });
      var transaction = inInput ? autocompleteHack() : apply$1;
      transaction(function () {
        active().each(blur$1);
        focus$3(iBody);
      });
    };

    var EXTRA_SPACING = 50;
    var data = 'data-' + resolve('last-outer-height');
    var setLastHeight = function (cBody, value) {
      set$8(cBody, data, value);
    };
    var getLastHeight = function (cBody) {
      return safeParse(cBody, data);
    };
    var getBoundsFrom = function (rect) {
      return {
        top: rect.top,
        bottom: rect.top + rect.height
      };
    };
    var getBounds = function (cWin) {
      var rects = getRectangles(cWin);
      return rects.length > 0 ? Optional.some(rects[0]).map(getBoundsFrom) : Optional.none();
    };
    var findDelta = function (outerWindow, cBody) {
      var last = getLastHeight(cBody);
      var current = outerWindow.innerHeight;
      return last > current ? Optional.some(last - current) : Optional.none();
    };
    var calculate = function (cWin, bounds, delta) {
      var isOutside = bounds.top > cWin.innerHeight || bounds.bottom > cWin.innerHeight;
      return isOutside ? Math.min(delta, bounds.bottom - cWin.innerHeight + EXTRA_SPACING) : 0;
    };
    var setup$2 = function (outerWindow, cWin) {
      var cBody = SugarElement.fromDom(cWin.document.body);
      var toEditing = function () {
        resume$1(cWin);
      };
      var onResize = bind(SugarElement.fromDom(outerWindow), 'resize', function () {
        findDelta(outerWindow, cBody).each(function (delta) {
          getBounds(cWin).each(function (bounds) {
            var cScrollBy = calculate(cWin, bounds, delta);
            if (cScrollBy !== 0) {
              cWin.scrollTo(cWin.pageXOffset, cWin.pageYOffset + cScrollBy);
            }
          });
        });
        setLastHeight(cBody, outerWindow.innerHeight);
      });
      setLastHeight(cBody, outerWindow.innerHeight);
      var destroy = function () {
        onResize.unbind();
      };
      return {
        toEditing: toEditing,
        destroy: destroy
      };
    };

    var create$2 = function (platform, mask) {
      var meta = tag();
      var androidApi = api$2();
      var androidEvents = api$2();
      var enter = function () {
        mask.hide();
        add$1(platform.container, resolve('fullscreen-maximized'));
        add$1(platform.container, resolve('android-maximized'));
        meta.maximize();
        add$1(platform.body, resolve('android-scroll-reload'));
        androidApi.set(setup$2(platform.win, getWin(platform.editor).getOrDie('no')));
        getActiveApi(platform.editor).each(function (editorApi) {
          clobberStyles(platform.container, editorApi.body);
          androidEvents.set(initEvents$1(editorApi, platform.toolstrip, platform.alloy));
        });
      };
      var exit = function () {
        meta.restore();
        mask.show();
        remove$3(platform.container, resolve('fullscreen-maximized'));
        remove$3(platform.container, resolve('android-maximized'));
        restoreStyles();
        remove$3(platform.body, resolve('android-scroll-reload'));
        androidEvents.clear();
        androidApi.clear();
      };
      return {
        enter: enter,
        exit: exit
      };
    };

    var first = function (fn, rate) {
      var timer = null;
      var cancel = function () {
        if (!isNull(timer)) {
          clearTimeout(timer);
          timer = null;
        }
      };
      var throttle = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        if (isNull(timer)) {
          timer = setTimeout(function () {
            timer = null;
            fn.apply(null, args);
          }, rate);
        }
      };
      return {
        cancel: cancel,
        throttle: throttle
      };
    };
    var last = function (fn, rate) {
      var timer = null;
      var cancel = function () {
        if (!isNull(timer)) {
          clearTimeout(timer);
          timer = null;
        }
      };
      var throttle = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
        }
        cancel();
        timer = setTimeout(function () {
          timer = null;
          fn.apply(null, args);
        }, rate);
      };
      return {
        cancel: cancel,
        throttle: throttle
      };
    };

    var sketch = function (onView, _translate) {
      var memIcon = record(Container.sketch({
        dom: dom$1('<div aria-hidden="true" class="${prefix}-mask-tap-icon"></div>'),
        containerBehaviours: derive$2([Toggling.config({
            toggleClass: resolve('mask-tap-icon-selected'),
            toggleOnExecute: false
          })])
      }));
      var onViewThrottle = first(onView, 200);
      return Container.sketch({
        dom: dom$1('<div class="${prefix}-disabled-mask"></div>'),
        components: [Container.sketch({
            dom: dom$1('<div class="${prefix}-content-container"></div>'),
            components: [Button.sketch({
                dom: dom$1('<div class="${prefix}-content-tap-section"></div>'),
                components: [memIcon.asSpec()],
                action: function (_button) {
                  onViewThrottle.throttle();
                },
                buttonBehaviours: derive$2([Toggling.config({ toggleClass: resolve('mask-tap-icon-selected') })])
              })]
          })]
      });
    };

    var unbindNoop = constant$1({ unbind: noop });
    var MobileSchema = objOf([
      requiredObjOf('editor', [
        required$1('getFrame'),
        option('getBody'),
        option('getDoc'),
        option('getWin'),
        option('getSelection'),
        option('setSelection'),
        option('clearSelection'),
        option('cursorSaver'),
        option('onKeyup'),
        option('onNodeChanged'),
        option('getCursorBox'),
        required$1('onDomChanged'),
        defaulted('onTouchContent', noop),
        defaulted('onTapContent', noop),
        defaulted('onTouchToolstrip', noop),
        defaulted('onScrollToCursor', unbindNoop),
        defaulted('onScrollToElement', unbindNoop),
        defaulted('onToEditing', unbindNoop),
        defaulted('onToReading', unbindNoop),
        defaulted('onToolbarScrollStart', identity)
      ]),
      required$1('socket'),
      required$1('toolstrip'),
      required$1('dropup'),
      required$1('toolbar'),
      required$1('container'),
      required$1('alloy'),
      customField('win', function (spec) {
        return owner$2(spec.socket).dom.defaultView;
      }),
      customField('body', function (spec) {
        return SugarElement.fromDom(spec.socket.dom.ownerDocument.body);
      }),
      defaulted('translate', identity),
      defaulted('setReadOnly', noop),
      defaulted('readOnlyOnInit', always)
    ]);

    var produce$1 = function (raw) {
      var mobile = asRawOrDie$1('Getting AndroidWebapp schema', MobileSchema, raw);
      set$5(mobile.toolstrip, 'width', '100%');
      var onTap = function () {
        mobile.setReadOnly(mobile.readOnlyOnInit());
        mode.enter();
      };
      var mask = build$1(sketch(onTap, mobile.translate));
      mobile.alloy.add(mask);
      var maskApi = {
        show: function () {
          mobile.alloy.add(mask);
        },
        hide: function () {
          mobile.alloy.remove(mask);
        }
      };
      append$2(mobile.container, mask.element);
      var mode = create$2(mobile, maskApi);
      return {
        setReadOnly: mobile.setReadOnly,
        refreshStructure: noop,
        enter: mode.enter,
        exit: mode.exit,
        destroy: noop
      };
    };

    var schema$1 = constant$1([
      required$1('dom'),
      defaulted('shell', true),
      field$1('toolbarBehaviours', [Replacing])
    ]);
    var enhanceGroups = function () {
      return { behaviours: derive$2([Replacing.config({})]) };
    };
    var parts$1 = constant$1([optional({
        name: 'groups',
        overrides: enhanceGroups
      })]);

    var factory$1 = function (detail, components, _spec, _externals) {
      var setGroups = function (toolbar, groups) {
        getGroupContainer(toolbar).fold(function () {
          console.error('Toolbar was defined to not be a shell, but no groups container was specified in components');
          throw new Error('Toolbar was defined to not be a shell, but no groups container was specified in components');
        }, function (container) {
          Replacing.set(container, groups);
        });
      };
      var getGroupContainer = function (component) {
        return detail.shell ? Optional.some(component) : getPart(component, detail, 'groups');
      };
      var extra = detail.shell ? {
        behaviours: [Replacing.config({})],
        components: []
      } : {
        behaviours: [],
        components: components
      };
      return {
        uid: detail.uid,
        dom: detail.dom,
        components: extra.components,
        behaviours: augment(detail.toolbarBehaviours, extra.behaviours),
        apis: { setGroups: setGroups },
        domModification: { attributes: { role: 'group' } }
      };
    };
    var Toolbar = composite({
      name: 'Toolbar',
      configFields: schema$1(),
      partFields: parts$1(),
      factory: factory$1,
      apis: {
        setGroups: function (apis, toolbar, groups) {
          apis.setGroups(toolbar, groups);
        }
      }
    });

    var schema = constant$1([
      required$1('items'),
      markers(['itemSelector']),
      field$1('tgroupBehaviours', [Keying])
    ]);
    var parts = constant$1([group({
        name: 'items',
        unit: 'item'
      })]);

    var factory = function (detail, components, _spec, _externals) {
      return {
        uid: detail.uid,
        dom: detail.dom,
        components: components,
        behaviours: augment(detail.tgroupBehaviours, [Keying.config({
            mode: 'flow',
            selector: detail.markers.itemSelector
          })]),
        domModification: { attributes: { role: 'toolbar' } }
      };
    };
    var ToolbarGroup = composite({
      name: 'ToolbarGroup',
      configFields: schema(),
      partFields: parts(),
      factory: factory
    });

    var dataHorizontal = 'data-' + resolve('horizontal-scroll');
    var canScrollVertically = function (container) {
      container.dom.scrollTop = 1;
      var result = container.dom.scrollTop !== 0;
      container.dom.scrollTop = 0;
      return result;
    };
    var canScrollHorizontally = function (container) {
      container.dom.scrollLeft = 1;
      var result = container.dom.scrollLeft !== 0;
      container.dom.scrollLeft = 0;
      return result;
    };
    var hasVerticalScroll = function (container) {
      return container.dom.scrollTop > 0 || canScrollVertically(container);
    };
    var hasHorizontalScroll = function (container) {
      return container.dom.scrollLeft > 0 || canScrollHorizontally(container);
    };
    var markAsHorizontal = function (container) {
      set$8(container, dataHorizontal, 'true');
    };
    var hasScroll = function (container) {
      return get$b(container, dataHorizontal) === 'true' ? hasHorizontalScroll(container) : hasVerticalScroll(container);
    };
    var exclusive = function (scope, selector) {
      return bind(scope, 'touchmove', function (event) {
        closest$1(event.target, selector).filter(hasScroll).fold(function () {
          event.prevent();
        }, noop);
      });
    };

    var ScrollingToolbar = function () {
      var makeGroup = function (gSpec) {
        var scrollClass = gSpec.scrollable === true ? '${prefix}-toolbar-scrollable-group' : '';
        return {
          dom: dom$1('<div aria-label="' + gSpec.label + '" class="${prefix}-toolbar-group ' + scrollClass + '"></div>'),
          tgroupBehaviours: derive$2([config('adhoc-scrollable-toolbar', gSpec.scrollable === true ? [runOnInit(function (component, _simulatedEvent) {
                set$5(component.element, 'overflow-x', 'auto');
                markAsHorizontal(component.element);
                register$2(component.element);
              })] : [])]),
          components: [Container.sketch({ components: [ToolbarGroup.parts.items({})] })],
          markers: { itemSelector: '.' + resolve('toolbar-group-item') },
          items: gSpec.items
        };
      };
      var toolbar = build$1(Toolbar.sketch({
        dom: dom$1('<div class="${prefix}-toolbar"></div>'),
        components: [Toolbar.parts.groups({})],
        toolbarBehaviours: derive$2([
          Toggling.config({
            toggleClass: resolve('context-toolbar'),
            toggleOnExecute: false,
            aria: { mode: 'none' }
          }),
          Keying.config({ mode: 'cyclic' })
        ]),
        shell: true
      }));
      var wrapper = build$1(Container.sketch({
        dom: { classes: [resolve('toolstrip')] },
        components: [premade(toolbar)],
        containerBehaviours: derive$2([Toggling.config({
            toggleClass: resolve('android-selection-context-toolbar'),
            toggleOnExecute: false
          })])
      }));
      var resetGroups = function () {
        Toolbar.setGroups(toolbar, initGroups.get());
        Toggling.off(toolbar);
      };
      var initGroups = Cell([]);
      var setGroups = function (gs) {
        initGroups.set(gs);
        resetGroups();
      };
      var createGroups = function (gs) {
        return map$2(gs, compose(ToolbarGroup.sketch, makeGroup));
      };
      var refresh = function () {
      };
      var setContextToolbar = function (gs) {
        Toggling.on(toolbar);
        Toolbar.setGroups(toolbar, gs);
      };
      var restoreToolbar = function () {
        if (Toggling.isOn(toolbar)) {
          resetGroups();
        }
      };
      var focus = function () {
        Keying.focusIn(toolbar);
      };
      return {
        wrapper: wrapper,
        toolbar: toolbar,
        createGroups: createGroups,
        setGroups: setGroups,
        setContextToolbar: setContextToolbar,
        restoreToolbar: restoreToolbar,
        refresh: refresh,
        focus: focus
      };
    };

    var makeEditSwitch = function (webapp) {
      return build$1(Button.sketch({
        dom: dom$1('<div class="${prefix}-mask-edit-icon ${prefix}-icon"></div>'),
        action: function () {
          webapp.run(function (w) {
            w.setReadOnly(false);
          });
        }
      }));
    };
    var makeSocket = function () {
      return build$1(Container.sketch({
        dom: dom$1('<div class="${prefix}-editor-socket"></div>'),
        components: [],
        containerBehaviours: derive$2([Replacing.config({})])
      }));
    };
    var showEdit = function (socket, switchToEdit) {
      Replacing.append(socket, premade(switchToEdit));
    };
    var hideEdit = function (socket, switchToEdit) {
      Replacing.remove(socket, switchToEdit);
    };
    var updateMode = function (socket, switchToEdit, readOnly, root) {
      var swap = readOnly === true ? Swapping.toAlpha : Swapping.toOmega;
      swap(root);
      var f = readOnly ? showEdit : hideEdit;
      f(socket, switchToEdit);
    };

    var getAnimationRoot = function (component, slideConfig) {
      return slideConfig.getAnimationRoot.fold(function () {
        return component.element;
      }, function (get) {
        return get(component);
      });
    };

    var getDimensionProperty = function (slideConfig) {
      return slideConfig.dimension.property;
    };
    var getDimension = function (slideConfig, elem) {
      return slideConfig.dimension.getDimension(elem);
    };
    var disableTransitions = function (component, slideConfig) {
      var root = getAnimationRoot(component, slideConfig);
      remove$1(root, [
        slideConfig.shrinkingClass,
        slideConfig.growingClass
      ]);
    };
    var setShrunk = function (component, slideConfig) {
      remove$3(component.element, slideConfig.openClass);
      add$1(component.element, slideConfig.closedClass);
      set$5(component.element, getDimensionProperty(slideConfig), '0px');
      reflow(component.element);
    };
    var setGrown = function (component, slideConfig) {
      remove$3(component.element, slideConfig.closedClass);
      add$1(component.element, slideConfig.openClass);
      remove$2(component.element, getDimensionProperty(slideConfig));
    };
    var doImmediateShrink = function (component, slideConfig, slideState, _calculatedSize) {
      slideState.setCollapsed();
      set$5(component.element, getDimensionProperty(slideConfig), getDimension(slideConfig, component.element));
      reflow(component.element);
      disableTransitions(component, slideConfig);
      setShrunk(component, slideConfig);
      slideConfig.onStartShrink(component);
      slideConfig.onShrunk(component);
    };
    var doStartShrink = function (component, slideConfig, slideState, calculatedSize) {
      var size = calculatedSize.getOrThunk(function () {
        return getDimension(slideConfig, component.element);
      });
      slideState.setCollapsed();
      set$5(component.element, getDimensionProperty(slideConfig), size);
      reflow(component.element);
      var root = getAnimationRoot(component, slideConfig);
      remove$3(root, slideConfig.growingClass);
      add$1(root, slideConfig.shrinkingClass);
      setShrunk(component, slideConfig);
      slideConfig.onStartShrink(component);
    };
    var doStartSmartShrink = function (component, slideConfig, slideState) {
      var size = getDimension(slideConfig, component.element);
      var shrinker = size === '0px' ? doImmediateShrink : doStartShrink;
      shrinker(component, slideConfig, slideState, Optional.some(size));
    };
    var doStartGrow = function (component, slideConfig, slideState) {
      var root = getAnimationRoot(component, slideConfig);
      var wasShrinking = has(root, slideConfig.shrinkingClass);
      var beforeSize = getDimension(slideConfig, component.element);
      setGrown(component, slideConfig);
      var fullSize = getDimension(slideConfig, component.element);
      var startPartialGrow = function () {
        set$5(component.element, getDimensionProperty(slideConfig), beforeSize);
        reflow(component.element);
      };
      var startCompleteGrow = function () {
        setShrunk(component, slideConfig);
      };
      var setStartSize = wasShrinking ? startPartialGrow : startCompleteGrow;
      setStartSize();
      remove$3(root, slideConfig.shrinkingClass);
      add$1(root, slideConfig.growingClass);
      setGrown(component, slideConfig);
      set$5(component.element, getDimensionProperty(slideConfig), fullSize);
      slideState.setExpanded();
      slideConfig.onStartGrow(component);
    };
    var refresh$1 = function (component, slideConfig, slideState) {
      if (slideState.isExpanded()) {
        remove$2(component.element, getDimensionProperty(slideConfig));
        var fullSize = getDimension(slideConfig, component.element);
        set$5(component.element, getDimensionProperty(slideConfig), fullSize);
      }
    };
    var grow = function (component, slideConfig, slideState) {
      if (!slideState.isExpanded()) {
        doStartGrow(component, slideConfig, slideState);
      }
    };
    var shrink = function (component, slideConfig, slideState) {
      if (slideState.isExpanded()) {
        doStartSmartShrink(component, slideConfig, slideState);
      }
    };
    var immediateShrink = function (component, slideConfig, slideState) {
      if (slideState.isExpanded()) {
        doImmediateShrink(component, slideConfig, slideState);
      }
    };
    var hasGrown = function (component, slideConfig, slideState) {
      return slideState.isExpanded();
    };
    var hasShrunk = function (component, slideConfig, slideState) {
      return slideState.isCollapsed();
    };
    var isGrowing = function (component, slideConfig, _slideState) {
      var root = getAnimationRoot(component, slideConfig);
      return has(root, slideConfig.growingClass) === true;
    };
    var isShrinking = function (component, slideConfig, _slideState) {
      var root = getAnimationRoot(component, slideConfig);
      return has(root, slideConfig.shrinkingClass) === true;
    };
    var isTransitioning = function (component, slideConfig, slideState) {
      return isGrowing(component, slideConfig) || isShrinking(component, slideConfig);
    };
    var toggleGrow = function (component, slideConfig, slideState) {
      var f = slideState.isExpanded() ? doStartSmartShrink : doStartGrow;
      f(component, slideConfig, slideState);
    };

    var SlidingApis = /*#__PURE__*/Object.freeze({
        __proto__: null,
        refresh: refresh$1,
        grow: grow,
        shrink: shrink,
        immediateShrink: immediateShrink,
        hasGrown: hasGrown,
        hasShrunk: hasShrunk,
        isGrowing: isGrowing,
        isShrinking: isShrinking,
        isTransitioning: isTransitioning,
        toggleGrow: toggleGrow,
        disableTransitions: disableTransitions
    });

    var exhibit = function (base, slideConfig, _slideState) {
      var expanded = slideConfig.expanded;
      return expanded ? nu$3({
        classes: [slideConfig.openClass],
        styles: {}
      }) : nu$3({
        classes: [slideConfig.closedClass],
        styles: wrap(slideConfig.dimension.property, '0px')
      });
    };
    var events = function (slideConfig, slideState) {
      return derive$3([runOnSource(transitionend(), function (component, simulatedEvent) {
          var raw = simulatedEvent.event.raw;
          if (raw.propertyName === slideConfig.dimension.property) {
            disableTransitions(component, slideConfig);
            if (slideState.isExpanded()) {
              remove$2(component.element, slideConfig.dimension.property);
            }
            var notify = slideState.isExpanded() ? slideConfig.onGrown : slideConfig.onShrunk;
            notify(component);
          }
        })]);
    };

    var ActiveSliding = /*#__PURE__*/Object.freeze({
        __proto__: null,
        exhibit: exhibit,
        events: events
    });

    var SlidingSchema = [
      required$1('closedClass'),
      required$1('openClass'),
      required$1('shrinkingClass'),
      required$1('growingClass'),
      option('getAnimationRoot'),
      onHandler('onShrunk'),
      onHandler('onStartShrink'),
      onHandler('onGrown'),
      onHandler('onStartGrow'),
      defaulted('expanded', false),
      requiredOf('dimension', choose$1('property', {
        width: [
          output('property', 'width'),
          output('getDimension', function (elem) {
            return get$5(elem) + 'px';
          })
        ],
        height: [
          output('property', 'height'),
          output('getDimension', function (elem) {
            return get$7(elem) + 'px';
          })
        ]
      }))
    ];

    var init$1 = function (spec) {
      var state = Cell(spec.expanded);
      var readState = function () {
        return 'expanded: ' + state.get();
      };
      return nu$2({
        isExpanded: function () {
          return state.get() === true;
        },
        isCollapsed: function () {
          return state.get() === false;
        },
        setCollapsed: curry(state.set, false),
        setExpanded: curry(state.set, true),
        readState: readState
      });
    };

    var SlidingState = /*#__PURE__*/Object.freeze({
        __proto__: null,
        init: init$1
    });

    var Sliding = create$5({
      fields: SlidingSchema,
      name: 'sliding',
      active: ActiveSliding,
      apis: SlidingApis,
      state: SlidingState
    });

    var build = function (refresh, scrollIntoView) {
      var dropup = build$1(Container.sketch({
        dom: {
          tag: 'div',
          classes: [resolve('dropup')]
        },
        components: [],
        containerBehaviours: derive$2([
          Replacing.config({}),
          Sliding.config({
            closedClass: resolve('dropup-closed'),
            openClass: resolve('dropup-open'),
            shrinkingClass: resolve('dropup-shrinking'),
            growingClass: resolve('dropup-growing'),
            dimension: { property: 'height' },
            onShrunk: function (component) {
              refresh();
              scrollIntoView();
              Replacing.set(component, []);
            },
            onGrown: function (_component) {
              refresh();
              scrollIntoView();
            }
          }),
          orientation(function (_component, _data) {
            disappear(noop);
          })
        ])
      }));
      var appear = function (menu, update, component) {
        if (Sliding.hasShrunk(dropup) === true && Sliding.isTransitioning(dropup) === false) {
          window.requestAnimationFrame(function () {
            update(component);
            Replacing.set(dropup, [menu()]);
            Sliding.grow(dropup);
          });
        }
      };
      var disappear = function (onReadyToShrink) {
        window.requestAnimationFrame(function () {
          onReadyToShrink();
          Sliding.shrink(dropup);
        });
      };
      return {
        appear: appear,
        disappear: disappear,
        component: dropup,
        element: dropup.element
      };
    };

    var closest = function (scope, selector, isRoot) {
      return closest$1(scope, selector, isRoot).isSome();
    };

    var isDangerous = function (event) {
      var keyEv = event.raw;
      return keyEv.which === BACKSPACE[0] && !contains$1([
        'input',
        'textarea'
      ], name$1(event.target)) && !closest(event.target, '[contenteditable="true"]');
    };
    var isFirefox = function () {
      return detect$1().browser.isFirefox();
    };
    var settingsSchema = objOfOnly([
      requiredFunction('triggerEvent'),
      defaulted('stopBackspace', true)
    ]);
    var bindFocus = function (container, handler) {
      if (isFirefox()) {
        return capture(container, 'focus', handler);
      } else {
        return bind(container, 'focusin', handler);
      }
    };
    var bindBlur = function (container, handler) {
      if (isFirefox()) {
        return capture(container, 'blur', handler);
      } else {
        return bind(container, 'focusout', handler);
      }
    };
    var setup$1 = function (container, rawSettings) {
      var settings = asRawOrDie$1('Getting GUI events settings', settingsSchema, rawSettings);
      var pointerEvents = [
        'touchstart',
        'touchmove',
        'touchend',
        'touchcancel',
        'gesturestart',
        'mousedown',
        'mouseup',
        'mouseover',
        'mousemove',
        'mouseout',
        'click'
      ];
      var tapEvent = monitor$1(settings);
      var simpleEvents = map$2(pointerEvents.concat([
        'selectstart',
        'input',
        'contextmenu',
        'change',
        'transitionend',
        'transitioncancel',
        'drag',
        'dragstart',
        'dragend',
        'dragenter',
        'dragleave',
        'dragover',
        'drop',
        'keyup'
      ]), function (type) {
        return bind(container, type, function (event) {
          tapEvent.fireIfReady(event, type).each(function (tapStopped) {
            if (tapStopped) {
              event.kill();
            }
          });
          var stopped = settings.triggerEvent(type, event);
          if (stopped) {
            event.kill();
          }
        });
      });
      var pasteTimeout = value();
      var onPaste = bind(container, 'paste', function (event) {
        tapEvent.fireIfReady(event, 'paste').each(function (tapStopped) {
          if (tapStopped) {
            event.kill();
          }
        });
        var stopped = settings.triggerEvent('paste', event);
        if (stopped) {
          event.kill();
        }
        pasteTimeout.set(setTimeout(function () {
          settings.triggerEvent(postPaste(), event);
        }, 0));
      });
      var onKeydown = bind(container, 'keydown', function (event) {
        var stopped = settings.triggerEvent('keydown', event);
        if (stopped) {
          event.kill();
        } else if (settings.stopBackspace === true && isDangerous(event)) {
          event.prevent();
        }
      });
      var onFocusIn = bindFocus(container, function (event) {
        var stopped = settings.triggerEvent('focusin', event);
        if (stopped) {
          event.kill();
        }
      });
      var focusoutTimeout = value();
      var onFocusOut = bindBlur(container, function (event) {
        var stopped = settings.triggerEvent('focusout', event);
        if (stopped) {
          event.kill();
        }
        focusoutTimeout.set(setTimeout(function () {
          settings.triggerEvent(postBlur(), event);
        }, 0));
      });
      var unbind = function () {
        each$1(simpleEvents, function (e) {
          e.unbind();
        });
        onKeydown.unbind();
        onFocusIn.unbind();
        onFocusOut.unbind();
        onPaste.unbind();
        pasteTimeout.on(clearTimeout);
        focusoutTimeout.on(clearTimeout);
      };
      return { unbind: unbind };
    };

    var derive$1 = function (rawEvent, rawTarget) {
      var source = get$c(rawEvent, 'target').getOr(rawTarget);
      return Cell(source);
    };

    var fromSource = function (event, source) {
      var stopper = Cell(false);
      var cutter = Cell(false);
      var stop = function () {
        stopper.set(true);
      };
      var cut = function () {
        cutter.set(true);
      };
      return {
        stop: stop,
        cut: cut,
        isStopped: stopper.get,
        isCut: cutter.get,
        event: event,
        setSource: source.set,
        getSource: source.get
      };
    };
    var fromExternal = function (event) {
      var stopper = Cell(false);
      var stop = function () {
        stopper.set(true);
      };
      return {
        stop: stop,
        cut: noop,
        isStopped: stopper.get,
        isCut: never,
        event: event,
        setSource: die('Cannot set source of a broadcasted event'),
        getSource: die('Cannot get source of a broadcasted event')
      };
    };

    var adt = Adt.generate([
      { stopped: [] },
      { resume: ['element'] },
      { complete: [] }
    ]);
    var doTriggerHandler = function (lookup, eventType, rawEvent, target, source, logger) {
      var handler = lookup(eventType, target);
      var simulatedEvent = fromSource(rawEvent, source);
      return handler.fold(function () {
        logger.logEventNoHandlers(eventType, target);
        return adt.complete();
      }, function (handlerInfo) {
        var descHandler = handlerInfo.descHandler;
        var eventHandler = getCurried(descHandler);
        eventHandler(simulatedEvent);
        if (simulatedEvent.isStopped()) {
          logger.logEventStopped(eventType, handlerInfo.element, descHandler.purpose);
          return adt.stopped();
        } else if (simulatedEvent.isCut()) {
          logger.logEventCut(eventType, handlerInfo.element, descHandler.purpose);
          return adt.complete();
        } else {
          return parent(handlerInfo.element).fold(function () {
            logger.logNoParent(eventType, handlerInfo.element, descHandler.purpose);
            return adt.complete();
          }, function (parent) {
            logger.logEventResponse(eventType, handlerInfo.element, descHandler.purpose);
            return adt.resume(parent);
          });
        }
      });
    };
    var doTriggerOnUntilStopped = function (lookup, eventType, rawEvent, rawTarget, source, logger) {
      return doTriggerHandler(lookup, eventType, rawEvent, rawTarget, source, logger).fold(always, function (parent) {
        return doTriggerOnUntilStopped(lookup, eventType, rawEvent, parent, source, logger);
      }, never);
    };
    var triggerHandler = function (lookup, eventType, rawEvent, target, logger) {
      var source = derive$1(rawEvent, target);
      return doTriggerHandler(lookup, eventType, rawEvent, target, source, logger);
    };
    var broadcast = function (listeners, rawEvent, _logger) {
      var simulatedEvent = fromExternal(rawEvent);
      each$1(listeners, function (listener) {
        var descHandler = listener.descHandler;
        var handler = getCurried(descHandler);
        handler(simulatedEvent);
      });
      return simulatedEvent.isStopped();
    };
    var triggerUntilStopped = function (lookup, eventType, rawEvent, logger) {
      return triggerOnUntilStopped(lookup, eventType, rawEvent, rawEvent.target, logger);
    };
    var triggerOnUntilStopped = function (lookup, eventType, rawEvent, rawTarget, logger) {
      var source = derive$1(rawEvent, rawTarget);
      return doTriggerOnUntilStopped(lookup, eventType, rawEvent, rawTarget, source, logger);
    };

    var eventHandler = function (element, descHandler) {
      return {
        element: element,
        descHandler: descHandler
      };
    };
    var broadcastHandler = function (id, handler) {
      return {
        id: id,
        descHandler: handler
      };
    };
    var EventRegistry = function () {
      var registry = {};
      var registerId = function (extraArgs, id, events) {
        each(events, function (v, k) {
          var handlers = registry[k] !== undefined ? registry[k] : {};
          handlers[id] = curryArgs(v, extraArgs);
          registry[k] = handlers;
        });
      };
      var findHandler = function (handlers, elem) {
        return read(elem).fold(function () {
          return Optional.none();
        }, function (id) {
          return handlers.bind(function (h) {
            return get$c(h, id);
          }).map(function (descHandler) {
            return eventHandler(elem, descHandler);
          });
        });
      };
      var filterByType = function (type) {
        return get$c(registry, type).map(function (handlers) {
          return mapToArray(handlers, function (f, id) {
            return broadcastHandler(id, f);
          });
        }).getOr([]);
      };
      var find = function (isAboveRoot, type, target) {
        var handlers = get$c(registry, type);
        return closest$3(target, function (elem) {
          return findHandler(handlers, elem);
        }, isAboveRoot);
      };
      var unregisterId = function (id) {
        each(registry, function (handlersById, _eventName) {
          if (has$2(handlersById, id)) {
            delete handlersById[id];
          }
        });
      };
      return {
        registerId: registerId,
        unregisterId: unregisterId,
        filterByType: filterByType,
        find: find
      };
    };

    var Registry = function () {
      var events = EventRegistry();
      var components = {};
      var readOrTag = function (component) {
        var elem = component.element;
        return read(elem).getOrThunk(function () {
          return write('uid-', component.element);
        });
      };
      var failOnDuplicate = function (component, tagId) {
        var conflict = components[tagId];
        if (conflict === component) {
          unregister(component);
        } else {
          throw new Error('The tagId "' + tagId + '" is already used by: ' + element(conflict.element) + '\nCannot use it for: ' + element(component.element) + '\n' + 'The conflicting element is' + (inBody(conflict.element) ? ' ' : ' not ') + 'already in the DOM');
        }
      };
      var register = function (component) {
        var tagId = readOrTag(component);
        if (hasNonNullableKey(components, tagId)) {
          failOnDuplicate(component, tagId);
        }
        var extraArgs = [component];
        events.registerId(extraArgs, tagId, component.events);
        components[tagId] = component;
      };
      var unregister = function (component) {
        read(component.element).each(function (tagId) {
          delete components[tagId];
          events.unregisterId(tagId);
        });
      };
      var filter = function (type) {
        return events.filterByType(type);
      };
      var find = function (isAboveRoot, type, target) {
        return events.find(isAboveRoot, type, target);
      };
      var getById = function (id) {
        return get$c(components, id);
      };
      return {
        find: find,
        filter: filter,
        register: register,
        unregister: unregister,
        getById: getById
      };
    };

    var takeover$1 = function (root) {
      var isAboveRoot = function (el) {
        return parent(root.element).fold(always, function (parent) {
          return eq(el, parent);
        });
      };
      var registry = Registry();
      var lookup = function (eventName, target) {
        return registry.find(isAboveRoot, eventName, target);
      };
      var domEvents = setup$1(root.element, {
        triggerEvent: function (eventName, event) {
          return monitorEvent(eventName, event.target, function (logger) {
            return triggerUntilStopped(lookup, eventName, event, logger);
          });
        }
      });
      var systemApi = {
        debugInfo: constant$1('real'),
        triggerEvent: function (eventName, target, data) {
          monitorEvent(eventName, target, function (logger) {
            return triggerOnUntilStopped(lookup, eventName, data, target, logger);
          });
        },
        triggerFocus: function (target, originator) {
          read(target).fold(function () {
            focus$3(target);
          }, function (_alloyId) {
            monitorEvent(focus$4(), target, function (logger) {
              triggerHandler(lookup, focus$4(), {
                originator: originator,
                kill: noop,
                prevent: noop,
                target: target
              }, target, logger);
              return false;
            });
          });
        },
        triggerEscape: function (comp, simulatedEvent) {
          systemApi.triggerEvent('keydown', comp.element, simulatedEvent.event);
        },
        getByUid: function (uid) {
          return getByUid(uid);
        },
        getByDom: function (elem) {
          return getByDom(elem);
        },
        build: build$1,
        addToGui: function (c) {
          add(c);
        },
        removeFromGui: function (c) {
          remove(c);
        },
        addToWorld: function (c) {
          addToWorld(c);
        },
        removeFromWorld: function (c) {
          removeFromWorld(c);
        },
        broadcast: function (message) {
          broadcast$1(message);
        },
        broadcastOn: function (channels, message) {
          broadcastOn(channels, message);
        },
        broadcastEvent: function (eventName, event) {
          broadcastEvent(eventName, event);
        },
        isConnected: always
      };
      var addToWorld = function (component) {
        component.connect(systemApi);
        if (!isText(component.element)) {
          registry.register(component);
          each$1(component.components(), addToWorld);
          systemApi.triggerEvent(systemInit(), component.element, { target: component.element });
        }
      };
      var removeFromWorld = function (component) {
        if (!isText(component.element)) {
          each$1(component.components(), removeFromWorld);
          registry.unregister(component);
        }
        component.disconnect();
      };
      var add = function (component) {
        attach(root, component);
      };
      var remove = function (component) {
        detach(component);
      };
      var destroy = function () {
        domEvents.unbind();
        remove$7(root.element);
      };
      var broadcastData = function (data) {
        var receivers = registry.filter(receive$1());
        each$1(receivers, function (receiver) {
          var descHandler = receiver.descHandler;
          var handler = getCurried(descHandler);
          handler(data);
        });
      };
      var broadcast$1 = function (message) {
        broadcastData({
          universal: true,
          data: message
        });
      };
      var broadcastOn = function (channels, message) {
        broadcastData({
          universal: false,
          channels: channels,
          data: message
        });
      };
      var broadcastEvent = function (eventName, event) {
        var listeners = registry.filter(eventName);
        return broadcast(listeners, event);
      };
      var getByUid = function (uid) {
        return registry.getById(uid).fold(function () {
          return Result.error(new Error('Could not find component with uid: "' + uid + '" in system.'));
        }, Result.value);
      };
      var getByDom = function (elem) {
        var uid = read(elem).getOr('not found');
        return getByUid(uid);
      };
      addToWorld(root);
      return {
        root: root,
        element: root.element,
        destroy: destroy,
        add: add,
        remove: remove,
        getByUid: getByUid,
        getByDom: getByDom,
        addToWorld: addToWorld,
        removeFromWorld: removeFromWorld,
        broadcast: broadcast$1,
        broadcastOn: broadcastOn,
        broadcastEvent: broadcastEvent
      };
    };

    var READ_ONLY_MODE_CLASS = resolve('readonly-mode');
    var EDIT_MODE_CLASS = resolve('edit-mode');
    function OuterContainer (spec) {
      var root = build$1(Container.sketch({
        dom: { classes: [resolve('outer-container')].concat(spec.classes) },
        containerBehaviours: derive$2([Swapping.config({
            alpha: READ_ONLY_MODE_CLASS,
            omega: EDIT_MODE_CLASS
          })])
      }));
      return takeover$1(root);
    }

    function AndroidRealm (scrollIntoView) {
      var alloy = OuterContainer({ classes: [resolve('android-container')] });
      var toolbar = ScrollingToolbar();
      var webapp = api$2();
      var switchToEdit = makeEditSwitch(webapp);
      var socket = makeSocket();
      var dropup = build(noop, scrollIntoView);
      alloy.add(toolbar.wrapper);
      alloy.add(socket);
      alloy.add(dropup.component);
      var setToolbarGroups = function (rawGroups) {
        var groups = toolbar.createGroups(rawGroups);
        toolbar.setGroups(groups);
      };
      var setContextToolbar = function (rawGroups) {
        var groups = toolbar.createGroups(rawGroups);
        toolbar.setContextToolbar(groups);
      };
      var focusToolbar = function () {
        toolbar.focus();
      };
      var restoreToolbar = function () {
        toolbar.restoreToolbar();
      };
      var init = function (spec) {
        webapp.set(produce$1(spec));
      };
      var exit = function () {
        webapp.run(function (w) {
          w.exit();
          Replacing.remove(socket, switchToEdit);
        });
      };
      var updateMode$1 = function (readOnly) {
        updateMode(socket, switchToEdit, readOnly, alloy.root);
      };
      return {
        system: alloy,
        element: alloy.element,
        init: init,
        exit: exit,
        setToolbarGroups: setToolbarGroups,
        setContextToolbar: setContextToolbar,
        focusToolbar: focusToolbar,
        restoreToolbar: restoreToolbar,
        updateMode: updateMode$1,
        socket: socket,
        dropup: dropup
      };
    }

    var input = function (parent, operation) {
      var input = SugarElement.fromTag('input');
      setAll(input, {
        opacity: '0',
        position: 'absolute',
        top: '-1000px',
        left: '-1000px'
      });
      append$2(parent, input);
      focus$3(input);
      operation(input);
      remove$7(input);
    };

    var refresh = function (winScope) {
      var sel = winScope.getSelection();
      if (sel.rangeCount > 0) {
        var br = sel.getRangeAt(0);
        var r = winScope.document.createRange();
        r.setStart(br.startContainer, br.startOffset);
        r.setEnd(br.endContainer, br.endOffset);
        sel.removeAllRanges();
        sel.addRange(r);
      }
    };

    var resume = function (cWin, frame) {
      active().each(function (active) {
        if (!eq(active, frame)) {
          blur$1(active);
        }
      });
      cWin.focus();
      focus$3(SugarElement.fromDom(cWin.document.body));
      refresh(cWin);
    };

    var stubborn = function (outerBody, cWin, page, frame) {
      var toEditing = function () {
        resume(cWin, frame);
      };
      var toReading = function () {
        input(outerBody, blur$1);
      };
      var captureInput = bind(page, 'keydown', function (evt) {
        if (!contains$1([
            'input',
            'textarea'
          ], name$1(evt.target))) {
          toEditing();
        }
      });
      var onToolbarTouch = noop;
      var destroy = function () {
        captureInput.unbind();
      };
      return {
        toReading: toReading,
        toEditing: toEditing,
        onToolbarTouch: onToolbarTouch,
        destroy: destroy
      };
    };

    var initEvents = function (editorApi, iosApi, toolstrip, socket, _dropup) {
      var saveSelectionFirst = function () {
        iosApi.run(function (api) {
          api.highlightSelection();
        });
      };
      var refreshIosSelection = function () {
        iosApi.run(function (api) {
          api.refreshSelection();
        });
      };
      var scrollToY = function (yTop, height) {
        var y = yTop - socket.dom.scrollTop;
        iosApi.run(function (api) {
          api.scrollIntoView(y, y + height);
        });
      };
      var scrollToElement = function (_target) {
        scrollToY(iosApi, socket);
      };
      var scrollToCursor = function () {
        editorApi.getCursorBox().each(function (box) {
          scrollToY(box.top, box.height);
        });
      };
      var clearSelection = function () {
        iosApi.run(function (api) {
          api.clearSelection();
        });
      };
      var clearAndRefresh = function () {
        clearSelection();
        refreshThrottle.throttle();
      };
      var refreshView = function () {
        scrollToCursor();
        iosApi.run(function (api) {
          api.syncHeight();
        });
      };
      var reposition = function () {
        var toolbarHeight = get$7(toolstrip);
        iosApi.run(function (api) {
          api.setViewportOffset(toolbarHeight);
        });
        refreshIosSelection();
        refreshView();
      };
      var toEditing = function () {
        iosApi.run(function (api) {
          api.toEditing();
        });
      };
      var toReading = function () {
        iosApi.run(function (api) {
          api.toReading();
        });
      };
      var onToolbarTouch = function (event) {
        iosApi.run(function (api) {
          api.onToolbarTouch(event);
        });
      };
      var tapping = monitor(editorApi);
      var refreshThrottle = last(refreshView, 300);
      var listeners = [
        editorApi.onKeyup(clearAndRefresh),
        editorApi.onNodeChanged(refreshIosSelection),
        editorApi.onDomChanged(refreshThrottle.throttle),
        editorApi.onDomChanged(refreshIosSelection),
        editorApi.onScrollToCursor(function (tinyEvent) {
          tinyEvent.preventDefault();
          refreshThrottle.throttle();
        }),
        editorApi.onScrollToElement(function (event) {
          scrollToElement(event.element);
        }),
        editorApi.onToEditing(toEditing),
        editorApi.onToReading(toReading),
        bind(editorApi.doc, 'touchend', function (touchEvent) {
          if (eq(editorApi.html, touchEvent.target) || eq(editorApi.body, touchEvent.target)) ;
        }),
        bind(toolstrip, 'transitionend', function (transitionEvent) {
          if (transitionEvent.raw.propertyName === 'height') {
            reposition();
          }
        }),
        capture(toolstrip, 'touchstart', function (touchEvent) {
          saveSelectionFirst();
          onToolbarTouch(touchEvent);
          editorApi.onTouchToolstrip();
        }),
        bind(editorApi.body, 'touchstart', function (evt) {
          clearSelection();
          editorApi.onTouchContent();
          tapping.fireTouchstart(evt);
        }),
        tapping.onTouchmove(),
        tapping.onTouchend(),
        bind(editorApi.body, 'click', function (event) {
          event.kill();
        }),
        bind(toolstrip, 'touchmove', function () {
          editorApi.onToolbarScrollStart();
        })
      ];
      var destroy = function () {
        each$1(listeners, function (l) {
          l.unbind();
        });
      };
      return { destroy: destroy };
    };

    function FakeSelection (win, frame) {
      var doc = win.document;
      var container = SugarElement.fromTag('div');
      add$1(container, resolve('unfocused-selections'));
      append$2(SugarElement.fromDom(doc.documentElement), container);
      var onTouch = bind(container, 'touchstart', function (event) {
        event.prevent();
        resume(win, frame);
        clear();
      });
      var make = function (rectangle) {
        var span = SugarElement.fromTag('span');
        add(span, [
          resolve('layer-editor'),
          resolve('unfocused-selection')
        ]);
        setAll(span, {
          left: rectangle.left + 'px',
          top: rectangle.top + 'px',
          width: rectangle.width + 'px',
          height: rectangle.height + 'px'
        });
        return span;
      };
      var update = function () {
        clear();
        var rectangles = getRectangles(win);
        var spans = map$2(rectangles, make);
        append$1(container, spans);
      };
      var clear = function () {
        empty(container);
      };
      var destroy = function () {
        onTouch.unbind();
        remove$7(container);
      };
      var isActive = function () {
        return children(container).length > 0;
      };
      return {
        update: update,
        isActive: isActive,
        destroy: destroy,
        clear: clear
      };
    }

    var exports$1 = {}, module = { exports: exports$1 };
    (function (define, exports, module, require) {
      (function (f) {
        if (typeof exports === 'object' && typeof module !== 'undefined') {
          module.exports = f();
        } else if (typeof define === 'function' && define.amd) {
          define([], f);
        } else {
          var g;
          if (typeof window !== 'undefined') {
            g = window;
          } else if (typeof global !== 'undefined') {
            g = global;
          } else if (typeof self !== 'undefined') {
            g = self;
          } else {
            g = this;
          }
          g.EphoxContactWrapper = f();
        }
      }(function () {
        return function () {
          function r(e, n, t) {
            function o(i, f) {
              if (!n[i]) {
                if (!e[i]) {
                  var c = 'function' == typeof require && require;
                  if (!f && c)
                    return c(i, !0);
                  if (u)
                    return u(i, !0);
                  var a = new Error('Cannot find module \'' + i + '\'');
                  throw a.code = 'MODULE_NOT_FOUND', a;
                }
                var p = n[i] = { exports: {} };
                e[i][0].call(p.exports, function (r) {
                  var n = e[i][1][r];
                  return o(n || r);
                }, p, p.exports, r, e, n, t);
              }
              return n[i].exports;
            }
            for (var u = 'function' == typeof require && require, i = 0; i < t.length; i++)
              o(t[i]);
            return o;
          }
          return r;
        }()({
          1: [
            function (require, module, exports) {
              var process = module.exports = {};
              var cachedSetTimeout;
              var cachedClearTimeout;
              function defaultSetTimout() {
                throw new Error('setTimeout has not been defined');
              }
              function defaultClearTimeout() {
                throw new Error('clearTimeout has not been defined');
              }
              (function () {
                try {
                  if (typeof setTimeout === 'function') {
                    cachedSetTimeout = setTimeout;
                  } else {
                    cachedSetTimeout = defaultSetTimout;
                  }
                } catch (e) {
                  cachedSetTimeout = defaultSetTimout;
                }
                try {
                  if (typeof clearTimeout === 'function') {
                    cachedClearTimeout = clearTimeout;
                  } else {
                    cachedClearTimeout = defaultClearTimeout;
                  }
                } catch (e) {
                  cachedClearTimeout = defaultClearTimeout;
                }
              }());
              function runTimeout(fun) {
                if (cachedSetTimeout === setTimeout) {
                  return setTimeout(fun, 0);
                }
                if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
                  cachedSetTimeout = setTimeout;
                  return setTimeout(fun, 0);
                }
                try {
                  return cachedSetTimeout(fun, 0);
                } catch (e) {
                  try {
                    return cachedSetTimeout.call(null, fun, 0);
                  } catch (e) {
                    return cachedSetTimeout.call(this, fun, 0);
                  }
                }
              }
              function runClearTimeout(marker) {
                if (cachedClearTimeout === clearTimeout) {
                  return clearTimeout(marker);
                }
                if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
                  cachedClearTimeout = clearTimeout;
                  return clearTimeout(marker);
                }
                try {
                  return cachedClearTimeout(marker);
                } catch (e) {
                  try {
                    return cachedClearTimeout.call(null, marker);
                  } catch (e) {
                    return cachedClearTimeout.call(this, marker);
                  }
                }
              }
              var queue = [];
              var draining = false;
              var currentQueue;
              var queueIndex = -1;
              function cleanUpNextTick() {
                if (!draining || !currentQueue) {
                  return;
                }
                draining = false;
                if (currentQueue.length) {
                  queue = currentQueue.concat(queue);
                } else {
                  queueIndex = -1;
                }
                if (queue.length) {
                  drainQueue();
                }
              }
              function drainQueue() {
                if (draining) {
                  return;
                }
                var timeout = runTimeout(cleanUpNextTick);
                draining = true;
                var len = queue.length;
                while (len) {
                  currentQueue = queue;
                  queue = [];
                  while (++queueIndex < len) {
                    if (currentQueue) {
                      currentQueue[queueIndex].run();
                    }
                  }
                  queueIndex = -1;
                  len = queue.length;
                }
                currentQueue = null;
                draining = false;
                runClearTimeout(timeout);
              }
              process.nextTick = function (fun) {
                var args = new Array(arguments.length - 1);
                if (arguments.length > 1) {
                  for (var i = 1; i < arguments.length; i++) {
                    args[i - 1] = arguments[i];
                  }
                }
                queue.push(new Item(fun, args));
                if (queue.length === 1 && !draining) {
                  runTimeout(drainQueue);
                }
              };
              function Item(fun, array) {
                this.fun = fun;
                this.array = array;
              }
              Item.prototype.run = function () {
                this.fun.apply(null, this.array);
              };
              process.title = 'browser';
              process.browser = true;
              process.env = {};
              process.argv = [];
              process.version = '';
              process.versions = {};
              function noop() {
              }
              process.on = noop;
              process.addListener = noop;
              process.once = noop;
              process.off = noop;
              process.removeListener = noop;
              process.removeAllListeners = noop;
              process.emit = noop;
              process.prependListener = noop;
              process.prependOnceListener = noop;
              process.listeners = function (name) {
                return [];
              };
              process.binding = function (name) {
                throw new Error('process.binding is not supported');
              };
              process.cwd = function () {
                return '/';
              };
              process.chdir = function (dir) {
                throw new Error('process.chdir is not supported');
              };
              process.umask = function () {
                return 0;
              };
            },
            {}
          ],
          2: [
            function (require, module, exports) {
              (function (setImmediate) {
                (function (root) {
                  var setTimeoutFunc = setTimeout;
                  function noop() {
                  }
                  function bind(fn, thisArg) {
                    return function () {
                      fn.apply(thisArg, arguments);
                    };
                  }
                  function Promise(fn) {
                    if (typeof this !== 'object')
                      throw new TypeError('Promises must be constructed via new');
                    if (typeof fn !== 'function')
                      throw new TypeError('not a function');
                    this._state = 0;
                    this._handled = false;
                    this._value = undefined;
                    this._deferreds = [];
                    doResolve(fn, this);
                  }
                  function handle(self, deferred) {
                    while (self._state === 3) {
                      self = self._value;
                    }
                    if (self._state === 0) {
                      self._deferreds.push(deferred);
                      return;
                    }
                    self._handled = true;
                    Promise._immediateFn(function () {
                      var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
                      if (cb === null) {
                        (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
                        return;
                      }
                      var ret;
                      try {
                        ret = cb(self._value);
                      } catch (e) {
                        reject(deferred.promise, e);
                        return;
                      }
                      resolve(deferred.promise, ret);
                    });
                  }
                  function resolve(self, newValue) {
                    try {
                      if (newValue === self)
                        throw new TypeError('A promise cannot be resolved with itself.');
                      if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
                        var then = newValue.then;
                        if (newValue instanceof Promise) {
                          self._state = 3;
                          self._value = newValue;
                          finale(self);
                          return;
                        } else if (typeof then === 'function') {
                          doResolve(bind(then, newValue), self);
                          return;
                        }
                      }
                      self._state = 1;
                      self._value = newValue;
                      finale(self);
                    } catch (e) {
                      reject(self, e);
                    }
                  }
                  function reject(self, newValue) {
                    self._state = 2;
                    self._value = newValue;
                    finale(self);
                  }
                  function finale(self) {
                    if (self._state === 2 && self._deferreds.length === 0) {
                      Promise._immediateFn(function () {
                        if (!self._handled) {
                          Promise._unhandledRejectionFn(self._value);
                        }
                      });
                    }
                    for (var i = 0, len = self._deferreds.length; i < len; i++) {
                      handle(self, self._deferreds[i]);
                    }
                    self._deferreds = null;
                  }
                  function Handler(onFulfilled, onRejected, promise) {
                    this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
                    this.onRejected = typeof onRejected === 'function' ? onRejected : null;
                    this.promise = promise;
                  }
                  function doResolve(fn, self) {
                    var done = false;
                    try {
                      fn(function (value) {
                        if (done)
                          return;
                        done = true;
                        resolve(self, value);
                      }, function (reason) {
                        if (done)
                          return;
                        done = true;
                        reject(self, reason);
                      });
                    } catch (ex) {
                      if (done)
                        return;
                      done = true;
                      reject(self, ex);
                    }
                  }
                  Promise.prototype['catch'] = function (onRejected) {
                    return this.then(null, onRejected);
                  };
                  Promise.prototype.then = function (onFulfilled, onRejected) {
                    var prom = new this.constructor(noop);
                    handle(this, new Handler(onFulfilled, onRejected, prom));
                    return prom;
                  };
                  Promise.all = function (arr) {
                    var args = Array.prototype.slice.call(arr);
                    return new Promise(function (resolve, reject) {
                      if (args.length === 0)
                        return resolve([]);
                      var remaining = args.length;
                      function res(i, val) {
                        try {
                          if (val && (typeof val === 'object' || typeof val === 'function')) {
                            var then = val.then;
                            if (typeof then === 'function') {
                              then.call(val, function (val) {
                                res(i, val);
                              }, reject);
                              return;
                            }
                          }
                          args[i] = val;
                          if (--remaining === 0) {
                            resolve(args);
                          }
                        } catch (ex) {
                          reject(ex);
                        }
                      }
                      for (var i = 0; i < args.length; i++) {
                        res(i, args[i]);
                      }
                    });
                  };
                  Promise.resolve = function (value) {
                    if (value && typeof value === 'object' && value.constructor === Promise) {
                      return value;
                    }
                    return new Promise(function (resolve) {
                      resolve(value);
                    });
                  };
                  Promise.reject = function (value) {
                    return new Promise(function (resolve, reject) {
                      reject(value);
                    });
                  };
                  Promise.race = function (values) {
                    return new Promise(function (resolve, reject) {
                      for (var i = 0, len = values.length; i < len; i++) {
                        values[i].then(resolve, reject);
                      }
                    });
                  };
                  Promise._immediateFn = typeof setImmediate === 'function' ? function (fn) {
                    setImmediate(fn);
                  } : function (fn) {
                    setTimeoutFunc(fn, 0);
                  };
                  Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
                    if (typeof console !== 'undefined' && console) {
                      console.warn('Possible Unhandled Promise Rejection:', err);
                    }
                  };
                  Promise._setImmediateFn = function _setImmediateFn(fn) {
                    Promise._immediateFn = fn;
                  };
                  Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
                    Promise._unhandledRejectionFn = fn;
                  };
                  if (typeof module !== 'undefined' && module.exports) {
                    module.exports = Promise;
                  } else if (!root.Promise) {
                    root.Promise = Promise;
                  }
                }(this));
              }.call(this, require('timers').setImmediate));
            },
            { 'timers': 3 }
          ],
          3: [
            function (require, module, exports) {
              (function (setImmediate, clearImmediate) {
                var nextTick = require('process/browser.js').nextTick;
                var apply = Function.prototype.apply;
                var slice = Array.prototype.slice;
                var immediateIds = {};
                var nextImmediateId = 0;
                exports.setTimeout = function () {
                  return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
                };
                exports.setInterval = function () {
                  return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
                };
                exports.clearTimeout = exports.clearInterval = function (timeout) {
                  timeout.close();
                };
                function Timeout(id, clearFn) {
                  this._id = id;
                  this._clearFn = clearFn;
                }
                Timeout.prototype.unref = Timeout.prototype.ref = function () {
                };
                Timeout.prototype.close = function () {
                  this._clearFn.call(window, this._id);
                };
                exports.enroll = function (item, msecs) {
                  clearTimeout(item._idleTimeoutId);
                  item._idleTimeout = msecs;
                };
                exports.unenroll = function (item) {
                  clearTimeout(item._idleTimeoutId);
                  item._idleTimeout = -1;
                };
                exports._unrefActive = exports.active = function (item) {
                  clearTimeout(item._idleTimeoutId);
                  var msecs = item._idleTimeout;
                  if (msecs >= 0) {
                    item._idleTimeoutId = setTimeout(function onTimeout() {
                      if (item._onTimeout)
                        item._onTimeout();
                    }, msecs);
                  }
                };
                exports.setImmediate = typeof setImmediate === 'function' ? setImmediate : function (fn) {
                  var id = nextImmediateId++;
                  var args = arguments.length < 2 ? false : slice.call(arguments, 1);
                  immediateIds[id] = true;
                  nextTick(function onNextTick() {
                    if (immediateIds[id]) {
                      if (args) {
                        fn.apply(null, args);
                      } else {
                        fn.call(null);
                      }
                      exports.clearImmediate(id);
                    }
                  });
                  return id;
                };
                exports.clearImmediate = typeof clearImmediate === 'function' ? clearImmediate : function (id) {
                  delete immediateIds[id];
                };
              }.call(this, require('timers').setImmediate, require('timers').clearImmediate));
            },
            {
              'process/browser.js': 1,
              'timers': 3
            }
          ],
          4: [
            function (require, module, exports) {
              var promisePolyfill = require('promise-polyfill');
              var Global = function () {
                if (typeof window !== 'undefined') {
                  return window;
                } else {
                  return Function('return this;')();
                }
              }();
              module.exports = { boltExport: Global.Promise || promisePolyfill };
            },
            { 'promise-polyfill': 2 }
          ]
        }, {}, [4])(4);
      }));
    }(undefined, exports$1, module, undefined));
    var Promise$1 = module.exports.boltExport;

    var nu$1 = function (baseFn) {
      var data = Optional.none();
      var callbacks = [];
      var map = function (f) {
        return nu$1(function (nCallback) {
          get(function (data) {
            nCallback(f(data));
          });
        });
      };
      var get = function (nCallback) {
        if (isReady()) {
          call(nCallback);
        } else {
          callbacks.push(nCallback);
        }
      };
      var set = function (x) {
        if (!isReady()) {
          data = Optional.some(x);
          run(callbacks);
          callbacks = [];
        }
      };
      var isReady = function () {
        return data.isSome();
      };
      var run = function (cbs) {
        each$1(cbs, call);
      };
      var call = function (cb) {
        data.each(function (x) {
          setTimeout(function () {
            cb(x);
          }, 0);
        });
      };
      baseFn(set);
      return {
        get: get,
        map: map,
        isReady: isReady
      };
    };
    var pure$1 = function (a) {
      return nu$1(function (callback) {
        callback(a);
      });
    };
    var LazyValue = {
      nu: nu$1,
      pure: pure$1
    };

    var errorReporter = function (err) {
      setTimeout(function () {
        throw err;
      }, 0);
    };
    var make = function (run) {
      var get = function (callback) {
        run().then(callback, errorReporter);
      };
      var map = function (fab) {
        return make(function () {
          return run().then(fab);
        });
      };
      var bind = function (aFutureB) {
        return make(function () {
          return run().then(function (v) {
            return aFutureB(v).toPromise();
          });
        });
      };
      var anonBind = function (futureB) {
        return make(function () {
          return run().then(function () {
            return futureB.toPromise();
          });
        });
      };
      var toLazy = function () {
        return LazyValue.nu(get);
      };
      var toCached = function () {
        var cache = null;
        return make(function () {
          if (cache === null) {
            cache = run();
          }
          return cache;
        });
      };
      var toPromise = run;
      return {
        map: map,
        bind: bind,
        anonBind: anonBind,
        toLazy: toLazy,
        toCached: toCached,
        toPromise: toPromise,
        get: get
      };
    };
    var nu = function (baseFn) {
      return make(function () {
        return new Promise$1(baseFn);
      });
    };
    var pure = function (a) {
      return make(function () {
        return Promise$1.resolve(a);
      });
    };
    var Future = {
      nu: nu,
      pure: pure
    };

    var adjust = function (value, destination, amount) {
      if (Math.abs(value - destination) <= amount) {
        return Optional.none();
      } else if (value < destination) {
        return Optional.some(value + amount);
      } else {
        return Optional.some(value - amount);
      }
    };
    var create$1 = function () {
      var interval = null;
      var animate = function (getCurrent, destination, amount, increment, doFinish, rate) {
        var finished = false;
        var finish = function (v) {
          finished = true;
          doFinish(v);
        };
        global$2.clearInterval(interval);
        var abort = function (v) {
          global$2.clearInterval(interval);
          finish(v);
        };
        interval = global$2.setInterval(function () {
          var value = getCurrent();
          adjust(value, destination, amount).fold(function () {
            global$2.clearInterval(interval);
            finish(destination);
          }, function (s) {
            increment(s, abort);
            if (!finished) {
              var newValue = getCurrent();
              if (newValue !== s || Math.abs(newValue - destination) > Math.abs(value - destination)) {
                global$2.clearInterval(interval);
                finish(destination);
              }
            }
          });
        }, rate);
      };
      return { animate: animate };
    };

    var findDevice = function (deviceWidth, deviceHeight) {
      var devices = [
        {
          width: 320,
          height: 480,
          keyboard: {
            portrait: 300,
            landscape: 240
          }
        },
        {
          width: 320,
          height: 568,
          keyboard: {
            portrait: 300,
            landscape: 240
          }
        },
        {
          width: 375,
          height: 667,
          keyboard: {
            portrait: 305,
            landscape: 240
          }
        },
        {
          width: 414,
          height: 736,
          keyboard: {
            portrait: 320,
            landscape: 240
          }
        },
        {
          width: 768,
          height: 1024,
          keyboard: {
            portrait: 320,
            landscape: 400
          }
        },
        {
          width: 1024,
          height: 1366,
          keyboard: {
            portrait: 380,
            landscape: 460
          }
        }
      ];
      return findMap(devices, function (device) {
        return someIf(deviceWidth <= device.width && deviceHeight <= device.height, device.keyboard);
      }).getOr({
        portrait: deviceHeight / 5,
        landscape: deviceWidth / 4
      });
    };

    var softKeyboardLimits = function (outerWindow) {
      return findDevice(outerWindow.screen.width, outerWindow.screen.height);
    };
    var accountableKeyboardHeight = function (outerWindow) {
      var portrait = get$1(outerWindow).isPortrait();
      var limits = softKeyboardLimits(outerWindow);
      var keyboard = portrait ? limits.portrait : limits.landscape;
      var visualScreenHeight = portrait ? outerWindow.screen.height : outerWindow.screen.width;
      return visualScreenHeight - outerWindow.innerHeight > keyboard ? 0 : keyboard;
    };
    var getGreenzone = function (socket, dropup) {
      var outerWindow = owner$2(socket).dom.defaultView;
      var viewportHeight = get$7(socket) + get$7(dropup);
      var acc = accountableKeyboardHeight(outerWindow);
      return viewportHeight - acc;
    };
    var updatePadding = function (contentBody, socket, dropup) {
      var greenzoneHeight = getGreenzone(socket, dropup);
      var deltaHeight = get$7(socket) + get$7(dropup) - greenzoneHeight;
      set$5(contentBody, 'padding-bottom', deltaHeight + 'px');
    };

    var fixture = Adt.generate([
      {
        fixed: [
          'element',
          'property',
          'offsetY'
        ]
      },
      {
        scroller: [
          'element',
          'offsetY'
        ]
      }
    ]);
    var yFixedData = 'data-' + resolve('position-y-fixed');
    var yFixedProperty = 'data-' + resolve('y-property');
    var yScrollingData = 'data-' + resolve('scrolling');
    var windowSizeData = 'data-' + resolve('last-window-height');
    var getYFixedData = function (element) {
      return safeParse(element, yFixedData);
    };
    var getYFixedProperty = function (element) {
      return get$b(element, yFixedProperty);
    };
    var getLastWindowSize = function (element) {
      return safeParse(element, windowSizeData);
    };
    var classifyFixed = function (element, offsetY) {
      var prop = getYFixedProperty(element);
      return fixture.fixed(element, prop, offsetY);
    };
    var classifyScrolling = function (element, offsetY) {
      return fixture.scroller(element, offsetY);
    };
    var classify = function (element) {
      var offsetY = getYFixedData(element);
      var classifier = get$b(element, yScrollingData) === 'true' ? classifyScrolling : classifyFixed;
      return classifier(element, offsetY);
    };
    var findFixtures = function (container) {
      var candidates = descendants(container, '[' + yFixedData + ']');
      return map$2(candidates, classify);
    };
    var takeoverToolbar = function (toolbar) {
      var oldToolbarStyle = get$b(toolbar, 'style');
      setAll(toolbar, {
        position: 'absolute',
        top: '0px'
      });
      set$8(toolbar, yFixedData, '0px');
      set$8(toolbar, yFixedProperty, 'top');
      var restore = function () {
        set$8(toolbar, 'style', oldToolbarStyle || '');
        remove$6(toolbar, yFixedData);
        remove$6(toolbar, yFixedProperty);
      };
      return { restore: restore };
    };
    var takeoverViewport = function (toolbarHeight, height, viewport) {
      var oldViewportStyle = get$b(viewport, 'style');
      register$2(viewport);
      setAll(viewport, {
        position: 'absolute',
        height: height + 'px',
        width: '100%',
        top: toolbarHeight + 'px'
      });
      set$8(viewport, yFixedData, toolbarHeight + 'px');
      set$8(viewport, yScrollingData, 'true');
      set$8(viewport, yFixedProperty, 'top');
      var restore = function () {
        deregister(viewport);
        set$8(viewport, 'style', oldViewportStyle || '');
        remove$6(viewport, yFixedData);
        remove$6(viewport, yScrollingData);
        remove$6(viewport, yFixedProperty);
      };
      return { restore: restore };
    };
    var takeoverDropup = function (dropup) {
      var oldDropupStyle = get$b(dropup, 'style');
      setAll(dropup, {
        position: 'absolute',
        bottom: '0px'
      });
      set$8(dropup, yFixedData, '0px');
      set$8(dropup, yFixedProperty, 'bottom');
      var restore = function () {
        set$8(dropup, 'style', oldDropupStyle || '');
        remove$6(dropup, yFixedData);
        remove$6(dropup, yFixedProperty);
      };
      return { restore: restore };
    };
    var deriveViewportHeight = function (viewport, toolbarHeight, dropupHeight) {
      var outerWindow = owner$2(viewport).dom.defaultView;
      var winH = outerWindow.innerHeight;
      set$8(viewport, windowSizeData, winH + 'px');
      return winH - toolbarHeight - dropupHeight;
    };
    var takeover = function (viewport, contentBody, toolbar, dropup) {
      var outerWindow = owner$2(viewport).dom.defaultView;
      var toolbarSetup = takeoverToolbar(toolbar);
      var toolbarHeight = get$7(toolbar);
      var dropupHeight = get$7(dropup);
      var viewportHeight = deriveViewportHeight(viewport, toolbarHeight, dropupHeight);
      var viewportSetup = takeoverViewport(toolbarHeight, viewportHeight, viewport);
      var dropupSetup = takeoverDropup(dropup);
      var isActive = true;
      var restore = function () {
        isActive = false;
        toolbarSetup.restore();
        viewportSetup.restore();
        dropupSetup.restore();
      };
      var isExpanding = function () {
        var currentWinHeight = outerWindow.innerHeight;
        var lastWinHeight = getLastWindowSize(viewport);
        return currentWinHeight > lastWinHeight;
      };
      var refresh = function () {
        if (isActive) {
          var newToolbarHeight = get$7(toolbar);
          var dropupHeight_1 = get$7(dropup);
          var newHeight = deriveViewportHeight(viewport, newToolbarHeight, dropupHeight_1);
          set$8(viewport, yFixedData, newToolbarHeight + 'px');
          set$5(viewport, 'height', newHeight + 'px');
          updatePadding(contentBody, viewport, dropup);
        }
      };
      var setViewportOffset = function (newYOffset) {
        var offsetPx = newYOffset + 'px';
        set$8(viewport, yFixedData, offsetPx);
        refresh();
      };
      updatePadding(contentBody, viewport, dropup);
      return {
        setViewportOffset: setViewportOffset,
        isExpanding: isExpanding,
        isShrinking: not(isExpanding),
        refresh: refresh,
        restore: restore
      };
    };

    var animator = create$1();
    var ANIMATION_STEP = 15;
    var NUM_TOP_ANIMATION_FRAMES = 10;
    var ANIMATION_RATE = 10;
    var lastScroll = 'data-' + resolve('last-scroll-top');
    var getTop = function (element) {
      var raw = getRaw(element, 'top').getOr('0');
      return parseInt(raw, 10);
    };
    var getScrollTop = function (element) {
      return parseInt(element.dom.scrollTop, 10);
    };
    var moveScrollAndTop = function (element, destination, finalTop) {
      return Future.nu(function (callback) {
        var getCurrent = curry(getScrollTop, element);
        var update = function (newScroll) {
          element.dom.scrollTop = newScroll;
          set$5(element, 'top', getTop(element) + ANIMATION_STEP + 'px');
        };
        var finish = function () {
          element.dom.scrollTop = destination;
          set$5(element, 'top', finalTop + 'px');
          callback(destination);
        };
        animator.animate(getCurrent, destination, ANIMATION_STEP, update, finish, ANIMATION_RATE);
      });
    };
    var moveOnlyScroll = function (element, destination) {
      return Future.nu(function (callback) {
        var getCurrent = curry(getScrollTop, element);
        set$8(element, lastScroll, getCurrent());
        var update = function (newScroll, abort) {
          var previous = safeParse(element, lastScroll);
          if (previous !== element.dom.scrollTop) {
            abort(element.dom.scrollTop);
          } else {
            element.dom.scrollTop = newScroll;
            set$8(element, lastScroll, newScroll);
          }
        };
        var finish = function () {
          element.dom.scrollTop = destination;
          set$8(element, lastScroll, destination);
          callback(destination);
        };
        var distance = Math.abs(destination - getCurrent());
        var step = Math.ceil(distance / NUM_TOP_ANIMATION_FRAMES);
        animator.animate(getCurrent, destination, step, update, finish, ANIMATION_RATE);
      });
    };
    var moveOnlyTop = function (element, destination) {
      return Future.nu(function (callback) {
        var getCurrent = curry(getTop, element);
        var update = function (newTop) {
          set$5(element, 'top', newTop + 'px');
        };
        var finish = function () {
          update(destination);
          callback(destination);
        };
        var distance = Math.abs(destination - getCurrent());
        var step = Math.ceil(distance / NUM_TOP_ANIMATION_FRAMES);
        animator.animate(getCurrent, destination, step, update, finish, ANIMATION_RATE);
      });
    };
    var updateTop = function (element, amount) {
      var newTop = amount + getYFixedData(element) + 'px';
      set$5(element, 'top', newTop);
    };
    var moveWindowScroll = function (toolbar, viewport, destY) {
      var outerWindow = owner$2(toolbar).dom.defaultView;
      return Future.nu(function (callback) {
        updateTop(toolbar, destY);
        updateTop(viewport, destY);
        outerWindow.scrollTo(0, destY);
        callback(destY);
      });
    };

    function BackgroundActivity (doAction) {
      var action = Cell(LazyValue.pure({}));
      var start = function (value) {
        var future = LazyValue.nu(function (callback) {
          return doAction(value).get(callback);
        });
        action.set(future);
      };
      var idle = function (g) {
        action.get().get(function () {
          g();
        });
      };
      return {
        start: start,
        idle: idle
      };
    }

    var scrollIntoView = function (cWin, socket, dropup, top, bottom) {
      var greenzone = getGreenzone(socket, dropup);
      var refreshCursor = curry(refresh, cWin);
      if (top > greenzone || bottom > greenzone) {
        moveOnlyScroll(socket, socket.dom.scrollTop - greenzone + bottom).get(refreshCursor);
      } else if (top < 0) {
        moveOnlyScroll(socket, socket.dom.scrollTop + top).get(refreshCursor);
      } else ;
    };

    var par$1 = function (asyncValues, nu) {
      return nu(function (callback) {
        var r = [];
        var count = 0;
        var cb = function (i) {
          return function (value) {
            r[i] = value;
            count++;
            if (count >= asyncValues.length) {
              callback(r);
            }
          };
        };
        if (asyncValues.length === 0) {
          callback([]);
        } else {
          each$1(asyncValues, function (asyncValue, i) {
            asyncValue.get(cb(i));
          });
        }
      });
    };

    var par = function (futures) {
      return par$1(futures, Future.nu);
    };

    var updateFixed = function (element, property, winY, offsetY) {
      var destination = winY + offsetY;
      set$5(element, property, destination + 'px');
      return Future.pure(offsetY);
    };
    var updateScrollingFixed = function (element, winY, offsetY) {
      var destTop = winY + offsetY;
      var oldProp = getRaw(element, 'top').getOr(offsetY);
      var delta = destTop - parseInt(oldProp, 10);
      var destScroll = element.dom.scrollTop + delta;
      return moveScrollAndTop(element, destScroll, destTop);
    };
    var updateFixture = function (fixture, winY) {
      return fixture.fold(function (element, property, offsetY) {
        return updateFixed(element, property, winY, offsetY);
      }, function (element, offsetY) {
        return updateScrollingFixed(element, winY, offsetY);
      });
    };
    var updatePositions = function (container, winY) {
      var fixtures = findFixtures(container);
      var updates = map$2(fixtures, function (fixture) {
        return updateFixture(fixture, winY);
      });
      return par(updates);
    };

    var VIEW_MARGIN = 5;
    var register = function (toolstrip, socket, container, outerWindow, structure, cWin) {
      var scroller = BackgroundActivity(function (y) {
        return moveWindowScroll(toolstrip, socket, y);
      });
      var scrollBounds = function () {
        var rects = getRectangles(cWin);
        return Optional.from(rects[0]).bind(function (rect) {
          var viewTop = rect.top - socket.dom.scrollTop;
          var outside = viewTop > outerWindow.innerHeight + VIEW_MARGIN || viewTop < -VIEW_MARGIN;
          return outside ? Optional.some({
            top: viewTop,
            bottom: viewTop + rect.height
          }) : Optional.none();
        });
      };
      var scrollThrottle = last(function () {
        scroller.idle(function () {
          updatePositions(container, outerWindow.pageYOffset).get(function () {
            var extraScroll = scrollBounds();
            extraScroll.each(function (extra) {
              socket.dom.scrollTop = socket.dom.scrollTop + extra.top;
            });
            scroller.start(0);
            structure.refresh();
          });
        });
      }, 1000);
      var onScroll = bind(SugarElement.fromDom(outerWindow), 'scroll', function () {
        if (outerWindow.pageYOffset < 0) {
          return;
        }
        scrollThrottle.throttle();
      });
      updatePositions(container, outerWindow.pageYOffset).get(identity);
      return { unbind: onScroll.unbind };
    };
    var setup = function (bag) {
      var cWin = bag.cWin;
      var ceBody = bag.ceBody;
      var socket = bag.socket;
      var toolstrip = bag.toolstrip;
      var contentElement = bag.contentElement;
      var keyboardType = bag.keyboardType;
      var outerWindow = bag.outerWindow;
      var dropup = bag.dropup;
      var outerBody = bag.outerBody;
      var structure = takeover(socket, ceBody, toolstrip, dropup);
      var keyboardModel = keyboardType(outerBody, cWin, body(), contentElement);
      var toEditing = function () {
        keyboardModel.toEditing();
        clearSelection();
      };
      var toReading = function () {
        keyboardModel.toReading();
      };
      var onToolbarTouch = function (_event) {
        keyboardModel.onToolbarTouch();
      };
      var onOrientation = onChange(outerWindow, {
        onChange: noop,
        onReady: structure.refresh
      });
      onOrientation.onAdjustment(function () {
        structure.refresh();
      });
      var onResize = bind(SugarElement.fromDom(outerWindow), 'resize', function () {
        if (structure.isExpanding()) {
          structure.refresh();
        }
      });
      var onScroll = register(toolstrip, socket, outerBody, outerWindow, structure, cWin);
      var unfocusedSelection = FakeSelection(cWin, contentElement);
      var refreshSelection = function () {
        if (unfocusedSelection.isActive()) {
          unfocusedSelection.update();
        }
      };
      var highlightSelection = function () {
        unfocusedSelection.update();
      };
      var clearSelection = function () {
        unfocusedSelection.clear();
      };
      var scrollIntoView$1 = function (top, bottom) {
        scrollIntoView(cWin, socket, dropup, top, bottom);
      };
      var syncHeight = function () {
        set$5(contentElement, 'height', contentElement.dom.contentWindow.document.body.scrollHeight + 'px');
      };
      var setViewportOffset = function (newYOffset) {
        structure.setViewportOffset(newYOffset);
        moveOnlyTop(socket, newYOffset).get(identity);
      };
      var destroy = function () {
        structure.restore();
        onOrientation.destroy();
        onScroll.unbind();
        onResize.unbind();
        keyboardModel.destroy();
        unfocusedSelection.destroy();
        input(body(), blur$1);
      };
      return {
        toEditing: toEditing,
        toReading: toReading,
        onToolbarTouch: onToolbarTouch,
        refreshSelection: refreshSelection,
        clearSelection: clearSelection,
        highlightSelection: highlightSelection,
        scrollIntoView: scrollIntoView$1,
        updateToolbarPadding: noop,
        setViewportOffset: setViewportOffset,
        syncHeight: syncHeight,
        refreshStructure: structure.refresh,
        destroy: destroy
      };
    };

    var create = function (platform, mask) {
      var meta = tag();
      var priorState = value();
      var scrollEvents = value();
      var iosApi = api$2();
      var iosEvents = api$2();
      var enter = function () {
        mask.hide();
        var doc = SugarElement.fromDom(document);
        getActiveApi(platform.editor).each(function (editorApi) {
          priorState.set({
            socketHeight: getRaw(platform.socket, 'height'),
            iframeHeight: getRaw(editorApi.frame, 'height'),
            outerScroll: document.body.scrollTop
          });
          scrollEvents.set({ exclusives: exclusive(doc, '.' + scrollable) });
          add$1(platform.container, resolve('fullscreen-maximized'));
          clobberStyles(platform.container, editorApi.body);
          meta.maximize();
          set$5(platform.socket, 'overflow', 'scroll');
          set$5(platform.socket, '-webkit-overflow-scrolling', 'touch');
          focus$3(editorApi.body);
          iosApi.set(setup({
            cWin: editorApi.win,
            ceBody: editorApi.body,
            socket: platform.socket,
            toolstrip: platform.toolstrip,
            dropup: platform.dropup.element,
            contentElement: editorApi.frame,
            outerBody: platform.body,
            outerWindow: platform.win,
            keyboardType: stubborn
          }));
          iosApi.run(function (api) {
            api.syncHeight();
          });
          iosEvents.set(initEvents(editorApi, iosApi, platform.toolstrip, platform.socket, platform.dropup));
        });
      };
      var exit = function () {
        meta.restore();
        iosEvents.clear();
        iosApi.clear();
        mask.show();
        priorState.on(function (s) {
          s.socketHeight.each(function (h) {
            set$5(platform.socket, 'height', h);
          });
          s.iframeHeight.each(function (h) {
            set$5(platform.editor.getFrame(), 'height', h);
          });
          document.body.scrollTop = s.scrollTop;
        });
        priorState.clear();
        scrollEvents.on(function (s) {
          s.exclusives.unbind();
        });
        scrollEvents.clear();
        remove$3(platform.container, resolve('fullscreen-maximized'));
        restoreStyles();
        deregister(platform.toolbar);
        remove$2(platform.socket, 'overflow');
        remove$2(platform.socket, '-webkit-overflow-scrolling');
        blur$1(platform.editor.getFrame());
        getActiveApi(platform.editor).each(function (editorApi) {
          editorApi.clearSelection();
        });
      };
      var refreshStructure = function () {
        iosApi.run(function (api) {
          api.refreshStructure();
        });
      };
      return {
        enter: enter,
        refreshStructure: refreshStructure,
        exit: exit
      };
    };

    var produce = function (raw) {
      var mobile = asRawOrDie$1('Getting IosWebapp schema', MobileSchema, raw);
      set$5(mobile.toolstrip, 'width', '100%');
      set$5(mobile.container, 'position', 'relative');
      var onView = function () {
        mobile.setReadOnly(mobile.readOnlyOnInit());
        mode.enter();
      };
      var mask = build$1(sketch(onView, mobile.translate));
      mobile.alloy.add(mask);
      var maskApi = {
        show: function () {
          mobile.alloy.add(mask);
        },
        hide: function () {
          mobile.alloy.remove(mask);
        }
      };
      var mode = create(mobile, maskApi);
      return {
        setReadOnly: mobile.setReadOnly,
        refreshStructure: mode.refreshStructure,
        enter: mode.enter,
        exit: mode.exit,
        destroy: noop
      };
    };

    function IosRealm (scrollIntoView) {
      var alloy = OuterContainer({ classes: [resolve('ios-container')] });
      var toolbar = ScrollingToolbar();
      var webapp = api$2();
      var switchToEdit = makeEditSwitch(webapp);
      var socket = makeSocket();
      var dropup = build(function () {
        webapp.run(function (w) {
          w.refreshStructure();
        });
      }, scrollIntoView);
      alloy.add(toolbar.wrapper);
      alloy.add(socket);
      alloy.add(dropup.component);
      var setToolbarGroups = function (rawGroups) {
        var groups = toolbar.createGroups(rawGroups);
        toolbar.setGroups(groups);
      };
      var setContextToolbar = function (rawGroups) {
        var groups = toolbar.createGroups(rawGroups);
        toolbar.setContextToolbar(groups);
      };
      var focusToolbar = function () {
        toolbar.focus();
      };
      var restoreToolbar = function () {
        toolbar.restoreToolbar();
      };
      var init = function (spec) {
        webapp.set(produce(spec));
      };
      var exit = function () {
        webapp.run(function (w) {
          Replacing.remove(socket, switchToEdit);
          w.exit();
        });
      };
      var updateMode$1 = function (readOnly) {
        updateMode(socket, switchToEdit, readOnly, alloy.root);
      };
      return {
        system: alloy,
        element: alloy.element,
        init: init,
        exit: exit,
        setToolbarGroups: setToolbarGroups,
        setContextToolbar: setContextToolbar,
        focusToolbar: focusToolbar,
        restoreToolbar: restoreToolbar,
        updateMode: updateMode$1,
        socket: socket,
        dropup: dropup
      };
    }

    var global$1 = tinymce.util.Tools.resolve('tinymce.EditorManager');

    var derive = function (editor) {
      var base = Optional.from(getSkinUrl(editor)).getOrThunk(function () {
        return global$1.baseURL + '/skins/ui/oxide';
      });
      return {
        content: base + '/content.mobile.min.css',
        ui: base + '/skin.mobile.min.css'
      };
    };

    var fireChange = function (realm, command, state) {
      realm.system.broadcastOn([formatChanged], {
        command: command,
        state: state
      });
    };
    var init = function (realm, editor) {
      var allFormats = keys(editor.formatter.get());
      each$1(allFormats, function (command) {
        editor.formatter.formatChanged(command, function (state) {
          fireChange(realm, command, state);
        });
      });
      each$1([
        'ul',
        'ol'
      ], function (command) {
        editor.selection.selectorChanged(command, function (state, _data) {
          fireChange(realm, command, state);
        });
      });
    };

    var fireSkinLoaded = function (editor) {
      return function () {
        var done = function () {
          editor._skinLoaded = true;
          editor.fire('SkinLoaded');
        };
        if (editor.initialized) {
          done();
        } else {
          editor.on('init', done);
        }
      };
    };

    var READING = 'toReading';
    var EDITING = 'toEditing';
    var renderMobileTheme = function (editor) {
      var renderUI = function () {
        var targetNode = editor.getElement();
        var cssUrls = derive(editor);
        if (isSkinDisabled(editor) === false) {
          var styleSheetLoader_1 = global$5.DOM.styleSheetLoader;
          editor.contentCSS.push(cssUrls.content);
          styleSheetLoader_1.load(cssUrls.ui, fireSkinLoaded(editor));
          editor.on('remove', function () {
            return styleSheetLoader_1.unload(cssUrls.ui);
          });
        } else {
          fireSkinLoaded(editor)();
        }
        var doScrollIntoView = function () {
          editor.fire('ScrollIntoView');
        };
        var realm = detect$1().os.isAndroid() ? AndroidRealm(doScrollIntoView) : IosRealm(doScrollIntoView);
        var original = SugarElement.fromDom(targetNode);
        attachSystemAfter(original, realm.system);
        var findFocusIn = function (elem) {
          return search(elem).bind(function (focused) {
            return realm.system.getByDom(focused).toOptional();
          });
        };
        var outerWindow = targetNode.ownerDocument.defaultView;
        var orientation = onChange(outerWindow, {
          onChange: function () {
            var alloy = realm.system;
            alloy.broadcastOn([orientationChanged], { width: getActualWidth(outerWindow) });
          },
          onReady: noop
        });
        var setReadOnly = function (dynamicGroup, readOnlyGroups, mainGroups, ro) {
          if (ro === false) {
            editor.selection.collapse();
          }
          var toolbars = configureToolbar(dynamicGroup, readOnlyGroups, mainGroups);
          realm.setToolbarGroups(ro === true ? toolbars.readOnly : toolbars.main);
          editor.setMode(ro === true ? 'readonly' : 'design');
          editor.fire(ro === true ? READING : EDITING);
          realm.updateMode(ro);
        };
        var configureToolbar = function (dynamicGroup, readOnlyGroups, mainGroups) {
          var dynamic = dynamicGroup.get();
          var toolbars = {
            readOnly: dynamic.backToMask.concat(readOnlyGroups.get()),
            main: dynamic.backToMask.concat(mainGroups.get())
          };
          return toolbars;
        };
        var bindHandler = function (label, handler) {
          editor.on(label, handler);
          return {
            unbind: function () {
              editor.off(label);
            }
          };
        };
        editor.on('init', function () {
          realm.init({
            editor: {
              getFrame: function () {
                return SugarElement.fromDom(editor.contentAreaContainer.querySelector('iframe'));
              },
              onDomChanged: function () {
                return { unbind: noop };
              },
              onToReading: function (handler) {
                return bindHandler(READING, handler);
              },
              onToEditing: function (handler) {
                return bindHandler(EDITING, handler);
              },
              onScrollToCursor: function (handler) {
                editor.on('ScrollIntoView', function (tinyEvent) {
                  handler(tinyEvent);
                });
                var unbind = function () {
                  editor.off('ScrollIntoView');
                  orientation.destroy();
                };
                return { unbind: unbind };
              },
              onTouchToolstrip: function () {
                hideDropup();
              },
              onTouchContent: function () {
                var toolbar = SugarElement.fromDom(editor.editorContainer.querySelector('.' + resolve('toolbar')));
                findFocusIn(toolbar).each(emitExecute);
                realm.restoreToolbar();
                hideDropup();
              },
              onTapContent: function (evt) {
                var target = evt.target;
                if (name$1(target) === 'img') {
                  editor.selection.select(target.dom);
                  evt.kill();
                } else if (name$1(target) === 'a') {
                  var component = realm.system.getByDom(SugarElement.fromDom(editor.editorContainer));
                  component.each(function (container) {
                    if (Swapping.isAlpha(container)) {
                      openLink(target.dom);
                    }
                  });
                }
              }
            },
            container: SugarElement.fromDom(editor.editorContainer),
            socket: SugarElement.fromDom(editor.contentAreaContainer),
            toolstrip: SugarElement.fromDom(editor.editorContainer.querySelector('.' + resolve('toolstrip'))),
            toolbar: SugarElement.fromDom(editor.editorContainer.querySelector('.' + resolve('toolbar'))),
            dropup: realm.dropup,
            alloy: realm.system,
            translate: noop,
            setReadOnly: function (ro) {
              setReadOnly(dynamicGroup, readOnlyGroups, mainGroups, ro);
            },
            readOnlyOnInit: function () {
              return readOnlyOnInit();
            }
          });
          var hideDropup = function () {
            realm.dropup.disappear(function () {
              realm.system.broadcastOn([dropupDismissed], {});
            });
          };
          var backToMaskGroup = {
            label: 'The first group',
            scrollable: false,
            items: [forToolbar('back', function () {
                editor.selection.collapse();
                realm.exit();
              }, {}, editor)]
          };
          var backToReadOnlyGroup = {
            label: 'Back to read only',
            scrollable: false,
            items: [forToolbar('readonly-back', function () {
                setReadOnly(dynamicGroup, readOnlyGroups, mainGroups, true);
              }, {}, editor)]
          };
          var readOnlyGroup = {
            label: 'The read only mode group',
            scrollable: true,
            items: []
          };
          var features = setup$3(realm, editor);
          var items = detect(editor, features);
          var actionGroup = {
            label: 'the action group',
            scrollable: true,
            items: items
          };
          var extraGroup = {
            label: 'The extra group',
            scrollable: false,
            items: []
          };
          var mainGroups = Cell([
            actionGroup,
            extraGroup
          ]);
          var readOnlyGroups = Cell([
            readOnlyGroup,
            extraGroup
          ]);
          var dynamicGroup = Cell({
            backToMask: [backToMaskGroup],
            backToReadOnly: [backToReadOnlyGroup]
          });
          init(realm, editor);
        });
        editor.on('remove', function () {
          realm.exit();
        });
        editor.on('detach', function () {
          detachSystem(realm.system);
          realm.system.destroy();
        });
        return {
          iframeContainer: realm.socket.element.dom,
          editorContainer: realm.element.dom
        };
      };
      return {
        getNotificationManagerImpl: function () {
          return {
            open: constant$1({
              progressBar: { value: noop },
              close: noop,
              text: noop,
              getEl: constant$1(null),
              moveTo: noop,
              moveRel: noop,
              settings: {}
            }),
            close: noop,
            reposition: noop,
            getArgs: constant$1({})
          };
        },
        renderUI: renderUI
      };
    };
    function Theme () {
      global$4.add('mobile', renderMobileTheme);
    }

    Theme();

}());
